@vue-storefront/next 8.0.0-next.3 → 8.0.0-next.4
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/dist/asyncToGenerator-BI_VpA62.cjs +32 -0
- package/dist/asyncToGenerator-Co5zHbo3.mjs +27 -0
- package/dist/client.cjs +72 -0
- package/dist/client.d.cts +38 -1
- package/dist/client.d.mts +39 -2
- package/dist/client.mjs +73 -2
- package/dist/index.cjs +12 -35
- package/dist/index.d.cts +2 -11
- package/dist/index.d.mts +3 -12
- package/dist/index.mjs +10 -33
- package/dist/server.cjs +23 -0
- package/dist/server.d.cts +9 -0
- package/dist/server.d.mts +9 -0
- package/dist/server.mjs +21 -0
- package/package.json +6 -1
- /package/dist/{index-BPhD221E.d.mts → index-7rf5ab-V.d.mts} +0 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region \0@oxc-project+runtime@0.115.0/helpers/asyncToGenerator.js
|
|
2
|
+
function asyncGeneratorStep(n, t, e, r, o, a, c) {
|
|
3
|
+
try {
|
|
4
|
+
var i = n[a](c), u = i.value;
|
|
5
|
+
} catch (n) {
|
|
6
|
+
e(n);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
i.done ? t(u) : Promise.resolve(u).then(r, o);
|
|
10
|
+
}
|
|
11
|
+
function _asyncToGenerator(n) {
|
|
12
|
+
return function() {
|
|
13
|
+
var t = this, e = arguments;
|
|
14
|
+
return new Promise(function(r, o) {
|
|
15
|
+
var a = n.apply(t, e);
|
|
16
|
+
function _next(n) {
|
|
17
|
+
asyncGeneratorStep(a, r, o, _next, _throw, "next", n);
|
|
18
|
+
}
|
|
19
|
+
function _throw(n) {
|
|
20
|
+
asyncGeneratorStep(a, r, o, _next, _throw, "throw", n);
|
|
21
|
+
}
|
|
22
|
+
_next(void 0);
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
Object.defineProperty(exports, "_asyncToGenerator", {
|
|
28
|
+
enumerable: true,
|
|
29
|
+
get: function() {
|
|
30
|
+
return _asyncToGenerator;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region \0@oxc-project+runtime@0.115.0/helpers/asyncToGenerator.js
|
|
2
|
+
function asyncGeneratorStep(n, t, e, r, o, a, c) {
|
|
3
|
+
try {
|
|
4
|
+
var i = n[a](c), u = i.value;
|
|
5
|
+
} catch (n) {
|
|
6
|
+
e(n);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
i.done ? t(u) : Promise.resolve(u).then(r, o);
|
|
10
|
+
}
|
|
11
|
+
function _asyncToGenerator(n) {
|
|
12
|
+
return function() {
|
|
13
|
+
var t = this, e = arguments;
|
|
14
|
+
return new Promise(function(r, o) {
|
|
15
|
+
var a = n.apply(t, e);
|
|
16
|
+
function _next(n) {
|
|
17
|
+
asyncGeneratorStep(a, r, o, _next, _throw, "next", n);
|
|
18
|
+
}
|
|
19
|
+
function _throw(n) {
|
|
20
|
+
asyncGeneratorStep(a, r, o, _next, _throw, "throw", n);
|
|
21
|
+
}
|
|
22
|
+
_next(void 0);
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { _asyncToGenerator as t };
|
package/dist/client.cjs
CHANGED
|
@@ -206,7 +206,79 @@ function createAlokaiContext() {
|
|
|
206
206
|
}, rest);
|
|
207
207
|
}
|
|
208
208
|
//#endregion
|
|
209
|
+
//#region src/storefront-events.ts
|
|
210
|
+
/**
|
|
211
|
+
* Creates a typed pub/sub for storefront domain events. The app defines its own event map and creates
|
|
212
|
+
* the bound helpers once; modules (analytics, personalization, search) emit and subscribe without the
|
|
213
|
+
* core knowing who listens. Client-only — the subscriber registry is created per call, so emitting from
|
|
214
|
+
* a server component reaches no listeners.
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```ts
|
|
218
|
+
* 'use client';
|
|
219
|
+
* import { createStorefrontEvents } from '@vue-storefront/next/client';
|
|
220
|
+
*
|
|
221
|
+
* export interface StorefrontEventMap {
|
|
222
|
+
* 'cart:productAdded': { productId: string };
|
|
223
|
+
* }
|
|
224
|
+
*
|
|
225
|
+
* export const { emitStorefrontEvent, subscribeStorefrontEvent, useStorefrontEvent } =
|
|
226
|
+
* createStorefrontEvents<StorefrontEventMap>();
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
function createStorefrontEvents() {
|
|
230
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
231
|
+
/**
|
|
232
|
+
* Emit a domain event. No-op when nothing is subscribed.
|
|
233
|
+
*/
|
|
234
|
+
function emitStorefrontEvent(type, payload) {
|
|
235
|
+
var _handlers$get;
|
|
236
|
+
(_handlers$get = handlers.get(type)) === null || _handlers$get === void 0 || _handlers$get.forEach((handler) => handler(payload));
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Subscribe to a domain event. Returns an unsubscribe function.
|
|
240
|
+
*/
|
|
241
|
+
function subscribeStorefrontEvent(type, handler) {
|
|
242
|
+
var _handlers$get2;
|
|
243
|
+
const set = (_handlers$get2 = handlers.get(type)) !== null && _handlers$get2 !== void 0 ? _handlers$get2 : /* @__PURE__ */ new Set();
|
|
244
|
+
set.add(handler);
|
|
245
|
+
handlers.set(type, set);
|
|
246
|
+
return () => set.delete(handler);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Subscribe to a domain event for the lifetime of the calling component. The handler is read through
|
|
250
|
+
* a ref so an inline (unmemoized) handler doesn't re-subscribe on every render.
|
|
251
|
+
*/
|
|
252
|
+
function useStorefrontEvent(type, handler) {
|
|
253
|
+
const handlerRef = (0, react.useRef)(handler);
|
|
254
|
+
handlerRef.current = handler;
|
|
255
|
+
(0, react.useEffect)(() => subscribeStorefrontEvent(type, (payload) => handlerRef.current(payload)), [type]);
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Emits a domain event once on mount. Lets server-rendered pages (which cannot call the client
|
|
259
|
+
* emitter directly) announce page-level events such as a PDP view. Give it a `key` tied to the entity
|
|
260
|
+
* (e.g. the product id + sku) so it remounts — and re-emits — when navigating between same-route
|
|
261
|
+
* pages. A ref guard keeps React Strict Mode's double-invoked effect (dev) to a single emit per mount.
|
|
262
|
+
*/
|
|
263
|
+
function StorefrontEventEmitter({ event, payload }) {
|
|
264
|
+
const didEmit = (0, react.useRef)(false);
|
|
265
|
+
(0, react.useEffect)(() => {
|
|
266
|
+
if (didEmit.current) return;
|
|
267
|
+
didEmit.current = true;
|
|
268
|
+
emitStorefrontEvent(event, payload);
|
|
269
|
+
}, []);
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
emitStorefrontEvent,
|
|
274
|
+
StorefrontEventEmitter,
|
|
275
|
+
subscribeStorefrontEvent,
|
|
276
|
+
useStorefrontEvent
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
//#endregion
|
|
209
280
|
exports.__toESM = __toESM;
|
|
210
281
|
exports.createAlokaiContext = createAlokaiContext;
|
|
211
282
|
exports.createSfStateProvider = createSfStateProvider;
|
|
283
|
+
exports.createStorefrontEvents = createStorefrontEvents;
|
|
212
284
|
exports.env = require_env.env;
|
package/dist/client.d.cts
CHANGED
|
@@ -40,4 +40,41 @@ import { SDKApi } from "@alokai/connect/sdk";
|
|
|
40
40
|
*/
|
|
41
41
|
declare function createAlokaiContext<TSdk extends SDKApi<any>, TSfContract extends SfContract>(): CreateSdkContextReturn<TSdk, TSfContract>;
|
|
42
42
|
//#endregion
|
|
43
|
-
|
|
43
|
+
//#region src/storefront-events.d.ts
|
|
44
|
+
/**
|
|
45
|
+
* Handler for a storefront event of type `TType` in the event map `TMap`.
|
|
46
|
+
*/
|
|
47
|
+
type StorefrontEventHandler<TMap, TType extends keyof TMap> = (payload: TMap[TType]) => void;
|
|
48
|
+
/**
|
|
49
|
+
* Creates a typed pub/sub for storefront domain events. The app defines its own event map and creates
|
|
50
|
+
* the bound helpers once; modules (analytics, personalization, search) emit and subscribe without the
|
|
51
|
+
* core knowing who listens. Client-only — the subscriber registry is created per call, so emitting from
|
|
52
|
+
* a server component reaches no listeners.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* 'use client';
|
|
57
|
+
* import { createStorefrontEvents } from '@vue-storefront/next/client';
|
|
58
|
+
*
|
|
59
|
+
* export interface StorefrontEventMap {
|
|
60
|
+
* 'cart:productAdded': { productId: string };
|
|
61
|
+
* }
|
|
62
|
+
*
|
|
63
|
+
* export const { emitStorefrontEvent, subscribeStorefrontEvent, useStorefrontEvent } =
|
|
64
|
+
* createStorefrontEvents<StorefrontEventMap>();
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
declare function createStorefrontEvents<TMap>(): {
|
|
68
|
+
emitStorefrontEvent: <TType extends keyof TMap>(type: TType, payload: TMap[TType]) => void;
|
|
69
|
+
StorefrontEventEmitter: <TType extends keyof TMap>({
|
|
70
|
+
event,
|
|
71
|
+
payload
|
|
72
|
+
}: {
|
|
73
|
+
event: TType;
|
|
74
|
+
payload: TMap[TType];
|
|
75
|
+
}) => null;
|
|
76
|
+
subscribeStorefrontEvent: <TType extends keyof TMap>(type: TType, handler: StorefrontEventHandler<TMap, TType>) => () => void;
|
|
77
|
+
useStorefrontEvent: <TType extends keyof TMap>(type: TType, handler: StorefrontEventHandler<TMap, TType>) => void;
|
|
78
|
+
};
|
|
79
|
+
//#endregion
|
|
80
|
+
export { type CreateSdkContextReturn, Maybe, SfContract, SfState, SfStateProps, StorefrontEventHandler, createAlokaiContext, createSfStateProvider, createStorefrontEvents, env };
|
package/dist/client.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as SfContract, d as createSfStateProvider, l as SfState, r as CreateSdkContextReturn, s as Maybe, t as env, u as SfStateProps } from "./index-
|
|
1
|
+
import { c as SfContract, d as createSfStateProvider, l as SfState, r as CreateSdkContextReturn, s as Maybe, t as env, u as SfStateProps } from "./index-7rf5ab-V.mjs";
|
|
2
2
|
import { SDKApi } from "@alokai/connect/sdk";
|
|
3
3
|
|
|
4
4
|
//#region src/alokai-provider.d.ts
|
|
@@ -40,4 +40,41 @@ import { SDKApi } from "@alokai/connect/sdk";
|
|
|
40
40
|
*/
|
|
41
41
|
declare function createAlokaiContext<TSdk extends SDKApi<any>, TSfContract extends SfContract>(): CreateSdkContextReturn<TSdk, TSfContract>;
|
|
42
42
|
//#endregion
|
|
43
|
-
|
|
43
|
+
//#region src/storefront-events.d.ts
|
|
44
|
+
/**
|
|
45
|
+
* Handler for a storefront event of type `TType` in the event map `TMap`.
|
|
46
|
+
*/
|
|
47
|
+
type StorefrontEventHandler<TMap, TType extends keyof TMap> = (payload: TMap[TType]) => void;
|
|
48
|
+
/**
|
|
49
|
+
* Creates a typed pub/sub for storefront domain events. The app defines its own event map and creates
|
|
50
|
+
* the bound helpers once; modules (analytics, personalization, search) emit and subscribe without the
|
|
51
|
+
* core knowing who listens. Client-only — the subscriber registry is created per call, so emitting from
|
|
52
|
+
* a server component reaches no listeners.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* 'use client';
|
|
57
|
+
* import { createStorefrontEvents } from '@vue-storefront/next/client';
|
|
58
|
+
*
|
|
59
|
+
* export interface StorefrontEventMap {
|
|
60
|
+
* 'cart:productAdded': { productId: string };
|
|
61
|
+
* }
|
|
62
|
+
*
|
|
63
|
+
* export const { emitStorefrontEvent, subscribeStorefrontEvent, useStorefrontEvent } =
|
|
64
|
+
* createStorefrontEvents<StorefrontEventMap>();
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
declare function createStorefrontEvents<TMap>(): {
|
|
68
|
+
emitStorefrontEvent: <TType extends keyof TMap>(type: TType, payload: TMap[TType]) => void;
|
|
69
|
+
StorefrontEventEmitter: <TType extends keyof TMap>({
|
|
70
|
+
event,
|
|
71
|
+
payload
|
|
72
|
+
}: {
|
|
73
|
+
event: TType;
|
|
74
|
+
payload: TMap[TType];
|
|
75
|
+
}) => null;
|
|
76
|
+
subscribeStorefrontEvent: <TType extends keyof TMap>(type: TType, handler: StorefrontEventHandler<TMap, TType>) => () => void;
|
|
77
|
+
useStorefrontEvent: <TType extends keyof TMap>(type: TType, handler: StorefrontEventHandler<TMap, TType>) => void;
|
|
78
|
+
};
|
|
79
|
+
//#endregion
|
|
80
|
+
export { type CreateSdkContextReturn, Maybe, SfContract, SfState, SfStateProps, StorefrontEventHandler, createAlokaiContext, createSfStateProvider, createStorefrontEvents, env };
|
package/dist/client.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { n as _objectSpread2, r as PUBLIC_ENV_KEY, t as env } from "./env-9UiGUnbx.mjs";
|
|
3
3
|
import { AlokaiInstrumentation } from "@alokai/instrumentation-next-component";
|
|
4
4
|
import Script from "next/script";
|
|
5
|
-
import React, { createContext, useContext, useRef } from "react";
|
|
5
|
+
import React, { createContext, useContext, useEffect, useRef } from "react";
|
|
6
6
|
import { createStore, useStore } from "zustand";
|
|
7
7
|
//#region src/env/get-public-env.ts
|
|
8
8
|
/**
|
|
@@ -181,4 +181,75 @@ function createAlokaiContext() {
|
|
|
181
181
|
}, rest);
|
|
182
182
|
}
|
|
183
183
|
//#endregion
|
|
184
|
-
|
|
184
|
+
//#region src/storefront-events.ts
|
|
185
|
+
/**
|
|
186
|
+
* Creates a typed pub/sub for storefront domain events. The app defines its own event map and creates
|
|
187
|
+
* the bound helpers once; modules (analytics, personalization, search) emit and subscribe without the
|
|
188
|
+
* core knowing who listens. Client-only — the subscriber registry is created per call, so emitting from
|
|
189
|
+
* a server component reaches no listeners.
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* ```ts
|
|
193
|
+
* 'use client';
|
|
194
|
+
* import { createStorefrontEvents } from '@vue-storefront/next/client';
|
|
195
|
+
*
|
|
196
|
+
* export interface StorefrontEventMap {
|
|
197
|
+
* 'cart:productAdded': { productId: string };
|
|
198
|
+
* }
|
|
199
|
+
*
|
|
200
|
+
* export const { emitStorefrontEvent, subscribeStorefrontEvent, useStorefrontEvent } =
|
|
201
|
+
* createStorefrontEvents<StorefrontEventMap>();
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
function createStorefrontEvents() {
|
|
205
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
206
|
+
/**
|
|
207
|
+
* Emit a domain event. No-op when nothing is subscribed.
|
|
208
|
+
*/
|
|
209
|
+
function emitStorefrontEvent(type, payload) {
|
|
210
|
+
var _handlers$get;
|
|
211
|
+
(_handlers$get = handlers.get(type)) === null || _handlers$get === void 0 || _handlers$get.forEach((handler) => handler(payload));
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Subscribe to a domain event. Returns an unsubscribe function.
|
|
215
|
+
*/
|
|
216
|
+
function subscribeStorefrontEvent(type, handler) {
|
|
217
|
+
var _handlers$get2;
|
|
218
|
+
const set = (_handlers$get2 = handlers.get(type)) !== null && _handlers$get2 !== void 0 ? _handlers$get2 : /* @__PURE__ */ new Set();
|
|
219
|
+
set.add(handler);
|
|
220
|
+
handlers.set(type, set);
|
|
221
|
+
return () => set.delete(handler);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Subscribe to a domain event for the lifetime of the calling component. The handler is read through
|
|
225
|
+
* a ref so an inline (unmemoized) handler doesn't re-subscribe on every render.
|
|
226
|
+
*/
|
|
227
|
+
function useStorefrontEvent(type, handler) {
|
|
228
|
+
const handlerRef = useRef(handler);
|
|
229
|
+
handlerRef.current = handler;
|
|
230
|
+
useEffect(() => subscribeStorefrontEvent(type, (payload) => handlerRef.current(payload)), [type]);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Emits a domain event once on mount. Lets server-rendered pages (which cannot call the client
|
|
234
|
+
* emitter directly) announce page-level events such as a PDP view. Give it a `key` tied to the entity
|
|
235
|
+
* (e.g. the product id + sku) so it remounts — and re-emits — when navigating between same-route
|
|
236
|
+
* pages. A ref guard keeps React Strict Mode's double-invoked effect (dev) to a single emit per mount.
|
|
237
|
+
*/
|
|
238
|
+
function StorefrontEventEmitter({ event, payload }) {
|
|
239
|
+
const didEmit = useRef(false);
|
|
240
|
+
useEffect(() => {
|
|
241
|
+
if (didEmit.current) return;
|
|
242
|
+
didEmit.current = true;
|
|
243
|
+
emitStorefrontEvent(event, payload);
|
|
244
|
+
}, []);
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
emitStorefrontEvent,
|
|
249
|
+
StorefrontEventEmitter,
|
|
250
|
+
subscribeStorefrontEvent,
|
|
251
|
+
useStorefrontEvent
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
//#endregion
|
|
255
|
+
export { createAlokaiContext, createSfStateProvider, createStorefrontEvents, env };
|
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_env = require("./env-BK6gqfbp.cjs");
|
|
3
3
|
require("./client.cjs");
|
|
4
|
+
const require_asyncToGenerator = require("./asyncToGenerator-BI_VpA62.cjs");
|
|
4
5
|
let _alokai_connect_logger = require("@alokai/connect/logger");
|
|
5
6
|
let _alokai_connect_sdk = require("@alokai/connect/sdk");
|
|
6
7
|
//#region src/logger/injectMetadata.ts
|
|
@@ -82,12 +83,9 @@ function deriveMediaHostEnvName(hostKey) {
|
|
|
82
83
|
return `NEXT_PUBLIC_${hostKey.replaceAll("-", "_").toUpperCase()}_MEDIA_HOST`;
|
|
83
84
|
}
|
|
84
85
|
const HOST_KEY_PATTERN = /^(?=.*[a-z])[a-z0-9-]+$/;
|
|
85
|
-
const ENV_NAME_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
86
86
|
function resolveHost(key, config) {
|
|
87
|
-
var _config$
|
|
87
|
+
var _config$variant, _config$buildUpstream, _config$cacheControl, _config$encodePath;
|
|
88
88
|
if (!HOST_KEY_PATTERN.test(key)) throw new Error(`Invalid image optimizer host key "${key}". Use lowercase letters, digits and hyphens only - the key becomes a URL segment and an env variable name fragment.`);
|
|
89
|
-
const mediaHostEnvName = (_config$mediaHostEnvN = config.mediaHostEnvName) !== null && _config$mediaHostEnvN !== void 0 ? _config$mediaHostEnvN : deriveMediaHostEnvName(key);
|
|
90
|
-
if (!ENV_NAME_PATTERN.test(mediaHostEnvName)) throw new Error(`Invalid mediaHostEnvName "${mediaHostEnvName}" for host "${key}". Pass the NAME of the env variable (e.g. "NEXT_PUBLIC_CT_MEDIA_HOST"), not its value.`);
|
|
91
89
|
const variant = variants[(_config$variant = config.variant) !== null && _config$variant !== void 0 ? _config$variant : "default"];
|
|
92
90
|
return {
|
|
93
91
|
buildUpstreamUrl: (_config$buildUpstream = config.buildUpstreamUrl) !== null && _config$buildUpstream !== void 0 ? _config$buildUpstream : variant.buildUpstreamUrl,
|
|
@@ -95,33 +93,7 @@ function resolveHost(key, config) {
|
|
|
95
93
|
encodePath: (_config$encodePath = config.encodePath) !== null && _config$encodePath !== void 0 ? _config$encodePath : variant.encodePath,
|
|
96
94
|
key,
|
|
97
95
|
loader: config.loader,
|
|
98
|
-
mediaHostEnvName
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
//#endregion
|
|
102
|
-
//#region \0@oxc-project+runtime@0.115.0/helpers/asyncToGenerator.js
|
|
103
|
-
function asyncGeneratorStep(n, t, e, r, o, a, c) {
|
|
104
|
-
try {
|
|
105
|
-
var i = n[a](c), u = i.value;
|
|
106
|
-
} catch (n) {
|
|
107
|
-
e(n);
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
i.done ? t(u) : Promise.resolve(u).then(r, o);
|
|
111
|
-
}
|
|
112
|
-
function _asyncToGenerator(n) {
|
|
113
|
-
return function() {
|
|
114
|
-
var t = this, e = arguments;
|
|
115
|
-
return new Promise(function(r, o) {
|
|
116
|
-
var a = n.apply(t, e);
|
|
117
|
-
function _next(n) {
|
|
118
|
-
asyncGeneratorStep(a, r, o, _next, _throw, "next", n);
|
|
119
|
-
}
|
|
120
|
-
function _throw(n) {
|
|
121
|
-
asyncGeneratorStep(a, r, o, _next, _throw, "throw", n);
|
|
122
|
-
}
|
|
123
|
-
_next(void 0);
|
|
124
|
-
});
|
|
96
|
+
mediaHostEnvName: deriveMediaHostEnvName(key)
|
|
125
97
|
};
|
|
126
98
|
}
|
|
127
99
|
//#endregion
|
|
@@ -168,11 +140,15 @@ function createImageOptimizer(config) {
|
|
|
168
140
|
"the media host URL, e.g. \"ct\" reads NEXT_PUBLIC_CT_MEDIA_HOST."
|
|
169
141
|
].join("\n"));
|
|
170
142
|
const hosts = resolveHosts(config.hosts);
|
|
143
|
+
const warnedMissingHosts = /* @__PURE__ */ new Set();
|
|
171
144
|
function loader({ quality, src, width }) {
|
|
172
145
|
for (const host of hosts) {
|
|
173
146
|
const mediaHost = require_env.env(host.mediaHostEnvName);
|
|
174
147
|
if (!mediaHost) {
|
|
175
|
-
|
|
148
|
+
if (!warnedMissingHosts.has(host.key)) {
|
|
149
|
+
warnedMissingHosts.add(host.key);
|
|
150
|
+
getLogger().warning(`${host.mediaHostEnvName} is not defined, skipping image optimization for host "${host.key}".`);
|
|
151
|
+
}
|
|
176
152
|
continue;
|
|
177
153
|
}
|
|
178
154
|
const normalizedHost = mediaHost.replace(/\/$/, "");
|
|
@@ -196,7 +172,7 @@ function createImageOptimizer(config) {
|
|
|
196
172
|
return _GET.apply(this, arguments);
|
|
197
173
|
}
|
|
198
174
|
function _GET() {
|
|
199
|
-
_GET = _asyncToGenerator(function* (_request, { params }) {
|
|
175
|
+
_GET = require_asyncToGenerator._asyncToGenerator(function* (_request, { params }) {
|
|
200
176
|
var _env, _upstream$headers$get;
|
|
201
177
|
const { host: hostKey, path } = yield params;
|
|
202
178
|
const host = hosts.find((entry) => entry.key === hostKey);
|
|
@@ -206,11 +182,12 @@ function createImageOptimizer(config) {
|
|
|
206
182
|
if (!mediaHost) return errorResponse(`${host.mediaHostEnvName} is not defined`, 500);
|
|
207
183
|
let upstream;
|
|
208
184
|
try {
|
|
209
|
-
upstream = yield fetch(host.buildUpstreamUrl(mediaHost, path));
|
|
185
|
+
upstream = yield fetch(host.buildUpstreamUrl(mediaHost, path), { redirect: "manual" });
|
|
210
186
|
} catch (error) {
|
|
211
187
|
getLogger().error(`Failed to fetch upstream image for host "${hostKey}": ${String(error)}`);
|
|
212
188
|
return errorResponse("Failed to fetch upstream image", 502);
|
|
213
189
|
}
|
|
190
|
+
if (upstream.status >= 300 && upstream.status < 400) return errorResponse("Upstream redirect is not allowed", 502);
|
|
214
191
|
return new Response(upstream.body, {
|
|
215
192
|
headers: {
|
|
216
193
|
"cache-control": upstream.ok ? host.cacheControl : ERROR_CACHE_CONTROL,
|
|
@@ -311,7 +288,7 @@ function normalizeRequestHeaders(requestHeaders) {
|
|
|
311
288
|
}
|
|
312
289
|
function resolveDynamicContext(context) {
|
|
313
290
|
return require_env._objectSpread2(require_env._objectSpread2({}, context), {}, { getRequestHeaders() {
|
|
314
|
-
return _asyncToGenerator(function* () {
|
|
291
|
+
return require_asyncToGenerator._asyncToGenerator(function* () {
|
|
315
292
|
var _context$getRequestHe;
|
|
316
293
|
const normalizedHeaders = normalizeRequestHeaders(yield (_context$getRequestHe = context.getRequestHeaders) === null || _context$getRequestHe === void 0 ? void 0 : _context$getRequestHe.call(context));
|
|
317
294
|
const requestHeaders = Object.fromEntries(Object.entries(normalizedHeaders).filter(([key]) => !BLACKLISTED_HEADERS.has(key)));
|
package/dist/index.d.cts
CHANGED
|
@@ -35,7 +35,7 @@ type ImageOptimizerHostConfig = ImageOptimizerDelegatedHostConfig | ImageOptimiz
|
|
|
35
35
|
* delegated to the given loader and never proxied, so the proxy-side options
|
|
36
36
|
* do not apply.
|
|
37
37
|
*/
|
|
38
|
-
interface ImageOptimizerDelegatedHostConfig
|
|
38
|
+
interface ImageOptimizerDelegatedHostConfig {
|
|
39
39
|
buildUpstreamUrl?: never;
|
|
40
40
|
cacheControl?: never;
|
|
41
41
|
encodePath?: never;
|
|
@@ -50,7 +50,7 @@ interface ImageOptimizerDelegatedHostConfig extends ImageOptimizerHostBaseConfig
|
|
|
50
50
|
* Host proxied through `/img-proxy/{key}/...` so the image CDN in front of
|
|
51
51
|
* the storefront (Alokai Image Optimizer) can transform the response.
|
|
52
52
|
*/
|
|
53
|
-
interface ImageOptimizerProxiedHostConfig
|
|
53
|
+
interface ImageOptimizerProxiedHostConfig {
|
|
54
54
|
/** Server-side hook overriding the variant's upstream URL reconstruction. */
|
|
55
55
|
buildUpstreamUrl?: BuildUpstreamUrlHook;
|
|
56
56
|
/**
|
|
@@ -71,15 +71,6 @@ interface ImageOptimizerProxiedHostConfig extends ImageOptimizerHostBaseConfig {
|
|
|
71
71
|
*/
|
|
72
72
|
variant?: ImageOptimizerVariant;
|
|
73
73
|
}
|
|
74
|
-
interface ImageOptimizerHostBaseConfig {
|
|
75
|
-
/**
|
|
76
|
-
* NAME of the env variable holding the media host URL (not the URL
|
|
77
|
-
* itself).
|
|
78
|
-
*
|
|
79
|
-
* @default `NEXT_PUBLIC_{KEY}_MEDIA_HOST` derived from the host key
|
|
80
|
-
*/
|
|
81
|
-
mediaHostEnvName?: string;
|
|
82
|
-
}
|
|
83
74
|
type ImageOptimizerVariant = "default" | "sapcc";
|
|
84
75
|
/**
|
|
85
76
|
* Builds the path emitted after `/img-proxy/{key}` on the loader (client)
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as CreateSdkReturn, i as CreateSdkOptions, n as Config, o as InjectedContext, t as env } from "./index-
|
|
1
|
+
import { a as CreateSdkReturn, i as CreateSdkOptions, n as Config, o as InjectedContext, t as env } from "./index-7rf5ab-V.mjs";
|
|
2
2
|
import * as _alokai_connect_logger0 from "@alokai/connect/logger";
|
|
3
3
|
import { buildModule, defineGetConfigSwitcherHeader } from "@alokai/connect/sdk";
|
|
4
4
|
import { ImageLoaderProps } from "next/image";
|
|
@@ -35,7 +35,7 @@ type ImageOptimizerHostConfig = ImageOptimizerDelegatedHostConfig | ImageOptimiz
|
|
|
35
35
|
* delegated to the given loader and never proxied, so the proxy-side options
|
|
36
36
|
* do not apply.
|
|
37
37
|
*/
|
|
38
|
-
interface ImageOptimizerDelegatedHostConfig
|
|
38
|
+
interface ImageOptimizerDelegatedHostConfig {
|
|
39
39
|
buildUpstreamUrl?: never;
|
|
40
40
|
cacheControl?: never;
|
|
41
41
|
encodePath?: never;
|
|
@@ -50,7 +50,7 @@ interface ImageOptimizerDelegatedHostConfig extends ImageOptimizerHostBaseConfig
|
|
|
50
50
|
* Host proxied through `/img-proxy/{key}/...` so the image CDN in front of
|
|
51
51
|
* the storefront (Alokai Image Optimizer) can transform the response.
|
|
52
52
|
*/
|
|
53
|
-
interface ImageOptimizerProxiedHostConfig
|
|
53
|
+
interface ImageOptimizerProxiedHostConfig {
|
|
54
54
|
/** Server-side hook overriding the variant's upstream URL reconstruction. */
|
|
55
55
|
buildUpstreamUrl?: BuildUpstreamUrlHook;
|
|
56
56
|
/**
|
|
@@ -71,15 +71,6 @@ interface ImageOptimizerProxiedHostConfig extends ImageOptimizerHostBaseConfig {
|
|
|
71
71
|
*/
|
|
72
72
|
variant?: ImageOptimizerVariant;
|
|
73
73
|
}
|
|
74
|
-
interface ImageOptimizerHostBaseConfig {
|
|
75
|
-
/**
|
|
76
|
-
* NAME of the env variable holding the media host URL (not the URL
|
|
77
|
-
* itself).
|
|
78
|
-
*
|
|
79
|
-
* @default `NEXT_PUBLIC_{KEY}_MEDIA_HOST` derived from the host key
|
|
80
|
-
*/
|
|
81
|
-
mediaHostEnvName?: string;
|
|
82
|
-
}
|
|
83
74
|
type ImageOptimizerVariant = "default" | "sapcc";
|
|
84
75
|
/**
|
|
85
76
|
* Builds the path emitted after `/img-proxy/{key}` on the loader (client)
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { n as _objectSpread2, t as env } from "./env-9UiGUnbx.mjs";
|
|
2
|
+
import { t as _asyncToGenerator } from "./asyncToGenerator-Co5zHbo3.mjs";
|
|
2
3
|
import { LoggerFactory, LoggerType } from "@alokai/connect/logger";
|
|
3
4
|
import { buildModule, defineGetConfigSwitcherHeader, initSDK, middlewareModule } from "@alokai/connect/sdk";
|
|
4
5
|
//#region src/logger/injectMetadata.ts
|
|
@@ -80,12 +81,9 @@ function deriveMediaHostEnvName(hostKey) {
|
|
|
80
81
|
return `NEXT_PUBLIC_${hostKey.replaceAll("-", "_").toUpperCase()}_MEDIA_HOST`;
|
|
81
82
|
}
|
|
82
83
|
const HOST_KEY_PATTERN = /^(?=.*[a-z])[a-z0-9-]+$/;
|
|
83
|
-
const ENV_NAME_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
84
84
|
function resolveHost(key, config) {
|
|
85
|
-
var _config$
|
|
85
|
+
var _config$variant, _config$buildUpstream, _config$cacheControl, _config$encodePath;
|
|
86
86
|
if (!HOST_KEY_PATTERN.test(key)) throw new Error(`Invalid image optimizer host key "${key}". Use lowercase letters, digits and hyphens only - the key becomes a URL segment and an env variable name fragment.`);
|
|
87
|
-
const mediaHostEnvName = (_config$mediaHostEnvN = config.mediaHostEnvName) !== null && _config$mediaHostEnvN !== void 0 ? _config$mediaHostEnvN : deriveMediaHostEnvName(key);
|
|
88
|
-
if (!ENV_NAME_PATTERN.test(mediaHostEnvName)) throw new Error(`Invalid mediaHostEnvName "${mediaHostEnvName}" for host "${key}". Pass the NAME of the env variable (e.g. "NEXT_PUBLIC_CT_MEDIA_HOST"), not its value.`);
|
|
89
87
|
const variant = variants[(_config$variant = config.variant) !== null && _config$variant !== void 0 ? _config$variant : "default"];
|
|
90
88
|
return {
|
|
91
89
|
buildUpstreamUrl: (_config$buildUpstream = config.buildUpstreamUrl) !== null && _config$buildUpstream !== void 0 ? _config$buildUpstream : variant.buildUpstreamUrl,
|
|
@@ -93,33 +91,7 @@ function resolveHost(key, config) {
|
|
|
93
91
|
encodePath: (_config$encodePath = config.encodePath) !== null && _config$encodePath !== void 0 ? _config$encodePath : variant.encodePath,
|
|
94
92
|
key,
|
|
95
93
|
loader: config.loader,
|
|
96
|
-
mediaHostEnvName
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
//#endregion
|
|
100
|
-
//#region \0@oxc-project+runtime@0.115.0/helpers/asyncToGenerator.js
|
|
101
|
-
function asyncGeneratorStep(n, t, e, r, o, a, c) {
|
|
102
|
-
try {
|
|
103
|
-
var i = n[a](c), u = i.value;
|
|
104
|
-
} catch (n) {
|
|
105
|
-
e(n);
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
i.done ? t(u) : Promise.resolve(u).then(r, o);
|
|
109
|
-
}
|
|
110
|
-
function _asyncToGenerator(n) {
|
|
111
|
-
return function() {
|
|
112
|
-
var t = this, e = arguments;
|
|
113
|
-
return new Promise(function(r, o) {
|
|
114
|
-
var a = n.apply(t, e);
|
|
115
|
-
function _next(n) {
|
|
116
|
-
asyncGeneratorStep(a, r, o, _next, _throw, "next", n);
|
|
117
|
-
}
|
|
118
|
-
function _throw(n) {
|
|
119
|
-
asyncGeneratorStep(a, r, o, _next, _throw, "throw", n);
|
|
120
|
-
}
|
|
121
|
-
_next(void 0);
|
|
122
|
-
});
|
|
94
|
+
mediaHostEnvName: deriveMediaHostEnvName(key)
|
|
123
95
|
};
|
|
124
96
|
}
|
|
125
97
|
//#endregion
|
|
@@ -166,11 +138,15 @@ function createImageOptimizer(config) {
|
|
|
166
138
|
"the media host URL, e.g. \"ct\" reads NEXT_PUBLIC_CT_MEDIA_HOST."
|
|
167
139
|
].join("\n"));
|
|
168
140
|
const hosts = resolveHosts(config.hosts);
|
|
141
|
+
const warnedMissingHosts = /* @__PURE__ */ new Set();
|
|
169
142
|
function loader({ quality, src, width }) {
|
|
170
143
|
for (const host of hosts) {
|
|
171
144
|
const mediaHost = env(host.mediaHostEnvName);
|
|
172
145
|
if (!mediaHost) {
|
|
173
|
-
|
|
146
|
+
if (!warnedMissingHosts.has(host.key)) {
|
|
147
|
+
warnedMissingHosts.add(host.key);
|
|
148
|
+
getLogger().warning(`${host.mediaHostEnvName} is not defined, skipping image optimization for host "${host.key}".`);
|
|
149
|
+
}
|
|
174
150
|
continue;
|
|
175
151
|
}
|
|
176
152
|
const normalizedHost = mediaHost.replace(/\/$/, "");
|
|
@@ -204,11 +180,12 @@ function createImageOptimizer(config) {
|
|
|
204
180
|
if (!mediaHost) return errorResponse(`${host.mediaHostEnvName} is not defined`, 500);
|
|
205
181
|
let upstream;
|
|
206
182
|
try {
|
|
207
|
-
upstream = yield fetch(host.buildUpstreamUrl(mediaHost, path));
|
|
183
|
+
upstream = yield fetch(host.buildUpstreamUrl(mediaHost, path), { redirect: "manual" });
|
|
208
184
|
} catch (error) {
|
|
209
185
|
getLogger().error(`Failed to fetch upstream image for host "${hostKey}": ${String(error)}`);
|
|
210
186
|
return errorResponse("Failed to fetch upstream image", 502);
|
|
211
187
|
}
|
|
188
|
+
if (upstream.status >= 300 && upstream.status < 400) return errorResponse("Upstream redirect is not allowed", 502);
|
|
212
189
|
return new Response(upstream.body, {
|
|
213
190
|
headers: {
|
|
214
191
|
"cache-control": upstream.ok ? host.cacheControl : ERROR_CACHE_CONTROL,
|
package/dist/server.cjs
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
require("./client.cjs");
|
|
3
|
+
const require_asyncToGenerator = require("./asyncToGenerator-BI_VpA62.cjs");
|
|
4
|
+
let next_headers = require("next/headers");
|
|
5
|
+
//#region src/current-path.ts
|
|
6
|
+
/**
|
|
7
|
+
* Returns the current request path (`pathname` + `search`) inside a Server Component, as exposed by
|
|
8
|
+
* {@link createAlokaiMiddleware} on the request headers. Reading it through this helper keeps the
|
|
9
|
+
* underlying header names (`x-pathname` / `x-search`) an implementation detail of the framework.
|
|
10
|
+
*/
|
|
11
|
+
function getCurrentPath() {
|
|
12
|
+
return _getCurrentPath.apply(this, arguments);
|
|
13
|
+
}
|
|
14
|
+
function _getCurrentPath() {
|
|
15
|
+
_getCurrentPath = require_asyncToGenerator._asyncToGenerator(function* () {
|
|
16
|
+
var _requestHeaders$get, _requestHeaders$get2;
|
|
17
|
+
const requestHeaders = yield (0, next_headers.headers)();
|
|
18
|
+
return `${(_requestHeaders$get = requestHeaders.get("x-pathname")) !== null && _requestHeaders$get !== void 0 ? _requestHeaders$get : ""}${(_requestHeaders$get2 = requestHeaders.get("x-search")) !== null && _requestHeaders$get2 !== void 0 ? _requestHeaders$get2 : ""}`;
|
|
19
|
+
});
|
|
20
|
+
return _getCurrentPath.apply(this, arguments);
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
exports.getCurrentPath = getCurrentPath;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/current-path.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Returns the current request path (`pathname` + `search`) inside a Server Component, as exposed by
|
|
4
|
+
* {@link createAlokaiMiddleware} on the request headers. Reading it through this helper keeps the
|
|
5
|
+
* underlying header names (`x-pathname` / `x-search`) an implementation detail of the framework.
|
|
6
|
+
*/
|
|
7
|
+
declare function getCurrentPath(): Promise<string>;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { getCurrentPath };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/current-path.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Returns the current request path (`pathname` + `search`) inside a Server Component, as exposed by
|
|
4
|
+
* {@link createAlokaiMiddleware} on the request headers. Reading it through this helper keeps the
|
|
5
|
+
* underlying header names (`x-pathname` / `x-search`) an implementation detail of the framework.
|
|
6
|
+
*/
|
|
7
|
+
declare function getCurrentPath(): Promise<string>;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { getCurrentPath };
|
package/dist/server.mjs
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { t as _asyncToGenerator } from "./asyncToGenerator-Co5zHbo3.mjs";
|
|
2
|
+
import { headers } from "next/headers";
|
|
3
|
+
//#region src/current-path.ts
|
|
4
|
+
/**
|
|
5
|
+
* Returns the current request path (`pathname` + `search`) inside a Server Component, as exposed by
|
|
6
|
+
* {@link createAlokaiMiddleware} on the request headers. Reading it through this helper keeps the
|
|
7
|
+
* underlying header names (`x-pathname` / `x-search`) an implementation detail of the framework.
|
|
8
|
+
*/
|
|
9
|
+
function getCurrentPath() {
|
|
10
|
+
return _getCurrentPath.apply(this, arguments);
|
|
11
|
+
}
|
|
12
|
+
function _getCurrentPath() {
|
|
13
|
+
_getCurrentPath = _asyncToGenerator(function* () {
|
|
14
|
+
var _requestHeaders$get, _requestHeaders$get2;
|
|
15
|
+
const requestHeaders = yield headers();
|
|
16
|
+
return `${(_requestHeaders$get = requestHeaders.get("x-pathname")) !== null && _requestHeaders$get !== void 0 ? _requestHeaders$get : ""}${(_requestHeaders$get2 = requestHeaders.get("x-search")) !== null && _requestHeaders$get2 !== void 0 ? _requestHeaders$get2 : ""}`;
|
|
17
|
+
});
|
|
18
|
+
return _getCurrentPath.apply(this, arguments);
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { getCurrentPath };
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/vuestorefront/enterprise.git"
|
|
8
8
|
},
|
|
9
|
-
"version": "8.0.0-next.
|
|
9
|
+
"version": "8.0.0-next.4",
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
12
|
"types": "./dist/index.d.mts",
|
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
"types": "./dist/client.d.mts",
|
|
18
18
|
"import": "./dist/client.mjs",
|
|
19
19
|
"require": "./dist/client.cjs"
|
|
20
|
+
},
|
|
21
|
+
"./server": {
|
|
22
|
+
"types": "./dist/server.d.mts",
|
|
23
|
+
"import": "./dist/server.mjs",
|
|
24
|
+
"require": "./dist/server.cjs"
|
|
20
25
|
}
|
|
21
26
|
},
|
|
22
27
|
"files": [
|
|
File without changes
|