@ecomiq/storefront 1.0.0 → 1.0.2
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/README.md +66 -19
- package/dist/chunk-PCLA4TZF.js +359 -0
- package/dist/chunk-PCLA4TZF.js.map +1 -0
- package/dist/chunk-Q762YXCQ.js +175 -0
- package/dist/chunk-Q762YXCQ.js.map +1 -0
- package/dist/chunk-TDQ53V3E.js +1598 -0
- package/dist/chunk-TDQ53V3E.js.map +1 -0
- package/dist/{index-C-xqLr1g.d.ts → chunks/client.d.ts} +6577 -4565
- package/dist/chunks/client.js +2046 -0
- package/dist/chunks/client.js.map +1 -0
- package/dist/chunks/config.js +3 -0
- package/dist/chunks/config.js.map +1 -0
- package/dist/chunks/server-nextjs.d.ts +33 -0
- package/dist/chunks/server-nextjs.js +30 -0
- package/dist/chunks/server-nextjs.js.map +1 -0
- package/dist/chunks/server-tanstack.d.ts +22 -0
- package/dist/chunks/server-tanstack.js +30 -0
- package/dist/chunks/server-tanstack.js.map +1 -0
- package/dist/ecomiq-shell-ui-SWIFLQVM.js +8 -0
- package/dist/ecomiq-shell-ui-SWIFLQVM.js.map +1 -0
- package/dist/format-currency-oJD9jGYW.d.ts +6751 -0
- package/dist/index.d.ts +20 -30
- package/dist/index.js +11 -103
- package/dist/index.js.map +1 -1
- package/dist/index.server.d.ts +8 -0
- package/dist/index.server.js +7 -0
- package/dist/index.server.js.map +1 -0
- package/dist/nextjs/api.js +1 -174
- package/dist/nextjs/api.js.map +1 -1
- package/dist/nextjs.d.ts +13 -41
- package/dist/nextjs.js +11 -2964
- package/dist/nextjs.js.map +1 -1
- package/dist/nextjs.server.d.ts +1 -0
- package/dist/nextjs.server.js +1 -0
- package/dist/nextjs.server.js.map +1 -0
- package/dist/tanstack/api.js +3 -171
- package/dist/tanstack/api.js.map +1 -1
- package/dist/tanstack.d.ts +13 -30
- package/dist/tanstack.js +11 -2964
- package/dist/tanstack.js.map +1 -1
- package/dist/tanstack.server.d.ts +1 -0
- package/dist/tanstack.server.js +1 -0
- package/dist/tanstack.server.js.map +1 -0
- package/package.json +13 -5
- /package/dist/{..d.ts → chunks/config.d.ts} +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,30 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
declare function clearEcomiqConfigCache(): void;
|
|
22
|
-
/**
|
|
23
|
-
* Identificador de tienda para settings (API / KV).
|
|
24
|
-
* 1. `slugStore` en `ecomiq.config.*` si existe.
|
|
25
|
-
* 2. Si no, deriva del header `Host` (`resolveStorefrontSettingsHost`).
|
|
26
|
-
*/
|
|
27
|
-
declare function resolvePublicStoreKey(hostHeader: string | null | undefined, cwd?: string): string;
|
|
28
|
-
declare function hasEcomiqSlugStoreConfig(cwd?: string): boolean;
|
|
29
|
-
|
|
30
|
-
export { type EcomiqConfig, EcomiqConfigSchema, clearEcomiqConfigCache, hasEcomiqSlugStoreConfig, loadEcomiqConfig, resolvePublicStoreKey };
|
|
1
|
+
export type { EcomiqConfig } from "./chunks/config";
|
|
2
|
+
export {
|
|
3
|
+
EcomiqConfigSchema,
|
|
4
|
+
loadEcomiqConfig,
|
|
5
|
+
clearEcomiqConfigCache,
|
|
6
|
+
resolvePublicStoreKey,
|
|
7
|
+
hasEcomiqSlugStoreConfig,
|
|
8
|
+
} from "./chunks/config";
|
|
9
|
+
export {
|
|
10
|
+
EcomiqProvider,
|
|
11
|
+
useStoreProducts,
|
|
12
|
+
useStoreCollections,
|
|
13
|
+
useStorePages,
|
|
14
|
+
useStoreCart,
|
|
15
|
+
useStore,
|
|
16
|
+
useCart,
|
|
17
|
+
useStorefrontSession,
|
|
18
|
+
useStorefrontAuthClient,
|
|
19
|
+
} from "./chunks/client";
|
|
20
|
+
export type { EcomiqProviderProps } from "./chunks/client";
|
package/dist/index.js
CHANGED
|
@@ -1,103 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
let h = hostHeader.trim().toLowerCase();
|
|
13
|
-
const colon = h.indexOf(":");
|
|
14
|
-
if (colon !== -1) h = h.slice(0, colon);
|
|
15
|
-
if (h.startsWith("www.")) h = h.slice(4);
|
|
16
|
-
return h;
|
|
17
|
-
}
|
|
18
|
-
function resolveStorefrontSettingsHost(hostHeader) {
|
|
19
|
-
const host = normalizeStoreHost(hostHeader);
|
|
20
|
-
if (!host) {
|
|
21
|
-
throw Object.assign(new Error("Host inv\xE1lido para tienda"), { status: 400 });
|
|
22
|
-
}
|
|
23
|
-
if (host === ECOMIQ_APP_APEX) {
|
|
24
|
-
throw Object.assign(new Error("Host apex ecomiq.app sin slug de tienda"), { status: 400 });
|
|
25
|
-
}
|
|
26
|
-
if (ECOMIQ_APP_SUFFIX.some((suffix) => host.endsWith(suffix))) {
|
|
27
|
-
const slug = host.slice(0, -(ECOMIQ_APP_SUFFIX.find((suffix) => host.endsWith(suffix))?.length ?? 0));
|
|
28
|
-
if (!slug) {
|
|
29
|
-
throw Object.assign(new Error("Host sin slug para ecomiq.app"), { status: 400 });
|
|
30
|
-
}
|
|
31
|
-
return slug;
|
|
32
|
-
}
|
|
33
|
-
return host;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// src/core/config/ecomiq-config.ts
|
|
37
|
-
var CONFIG_FILENAMES = [
|
|
38
|
-
"ecomiq.config.js",
|
|
39
|
-
"ecomiq.config.cjs",
|
|
40
|
-
"ecomiq.config.mjs"
|
|
41
|
-
];
|
|
42
|
-
var EcomiqConfigSchema = z.object({
|
|
43
|
-
/**
|
|
44
|
-
* Slug de tienda en Ecomiq (p. ej. `mi-tienda` para `mi-tienda.ecomiq.app`).
|
|
45
|
-
* Si está definido, tiene prioridad sobre el `Host` de la request (útil en `localhost`).
|
|
46
|
-
*/
|
|
47
|
-
slugStore: z.string().min(1).optional()
|
|
48
|
-
});
|
|
49
|
-
var cachedConfig;
|
|
50
|
-
function parseExportedConfig(raw) {
|
|
51
|
-
const candidate = raw && typeof raw === "object" && "default" in raw ? raw.default : raw;
|
|
52
|
-
const parsed = EcomiqConfigSchema.safeParse(candidate);
|
|
53
|
-
if (!parsed.success) {
|
|
54
|
-
console.warn(
|
|
55
|
-
"[ecomiq] ecomiq.config.* inv\xE1lido:",
|
|
56
|
-
parsed.error.flatten().fieldErrors
|
|
57
|
-
);
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
const slugStore = parsed.data.slugStore?.trim();
|
|
61
|
-
return slugStore ? { slugStore } : {};
|
|
62
|
-
}
|
|
63
|
-
function loadEcomiqConfig(cwd = process.cwd()) {
|
|
64
|
-
if (cachedConfig !== void 0) return cachedConfig;
|
|
65
|
-
for (const filename of CONFIG_FILENAMES) {
|
|
66
|
-
const configPath = join(cwd, filename);
|
|
67
|
-
if (!existsSync(configPath)) continue;
|
|
68
|
-
try {
|
|
69
|
-
const requireFromApp = createRequire(join(cwd, "package.json"));
|
|
70
|
-
const loaded = requireFromApp(configPath);
|
|
71
|
-
const parsed = parseExportedConfig(loaded);
|
|
72
|
-
cachedConfig = parsed;
|
|
73
|
-
return cachedConfig;
|
|
74
|
-
} catch (error) {
|
|
75
|
-
console.warn(`[ecomiq] No se pudo cargar ${configPath}:`, error);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
cachedConfig = null;
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
function clearEcomiqConfigCache() {
|
|
82
|
-
cachedConfig = void 0;
|
|
83
|
-
}
|
|
84
|
-
function resolvePublicStoreKey(hostHeader, cwd) {
|
|
85
|
-
const slugFromConfig = loadEcomiqConfig(cwd)?.slugStore?.trim();
|
|
86
|
-
if (slugFromConfig) return slugFromConfig;
|
|
87
|
-
if (!hostHeader?.trim()) {
|
|
88
|
-
throw Object.assign(
|
|
89
|
-
new Error(
|
|
90
|
-
"Host is required, o define slugStore en ecomiq.config.js en la ra\xEDz del proyecto"
|
|
91
|
-
),
|
|
92
|
-
{ status: 400 }
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
return resolveStorefrontSettingsHost(hostHeader);
|
|
96
|
-
}
|
|
97
|
-
function hasEcomiqSlugStoreConfig(cwd) {
|
|
98
|
-
return Boolean(loadEcomiqConfig(cwd)?.slugStore?.trim());
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export { EcomiqConfigSchema, clearEcomiqConfigCache, hasEcomiqSlugStoreConfig, loadEcomiqConfig, resolvePublicStoreKey };
|
|
102
|
-
//# sourceMappingURL=index.js.map
|
|
103
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
export {
|
|
2
|
+
EcomiqProvider,
|
|
3
|
+
useStoreProducts,
|
|
4
|
+
useStoreCollections,
|
|
5
|
+
useStorePages,
|
|
6
|
+
useStoreCart,
|
|
7
|
+
useStore,
|
|
8
|
+
useCart,
|
|
9
|
+
useStorefrontSession,
|
|
10
|
+
useStorefrontAuthClient,
|
|
11
|
+
} from "./chunks/client.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/client/storefront-settings-kv.service.ts","../src/core/config/ecomiq-config.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { getCloudflareContext } from \"@opennextjs/cloudflare\";\nimport { StorefrontSettingsSchema } from \"@ecomiq/storefront/core\";\nimport type { StorefrontSettings } from \"@ecomiq/storefront/core\";\n\n/** Debe coincidir con el `binding` en wrangler.jsonc (`kv_namespaces`). */\nexport const ECOMIQ_CLIENTS_STORE_KV_BINDING = \"ecomiq_clients_store\" as const;\n\nconst ECOMIQ_APP_APEX = \"ecomiq.app\";\nconst ECOMIQ_APP_SUFFIX = [`.${ECOMIQ_APP_APEX}`, `.localhost`];\n\ntype KvJsonGet = {\n get(key: string, options: { type: \"json\" }): Promise<unknown>;\n};\n\n/** Host sin puerto, minúsculas, sin `www.`. */\nexport function normalizeStoreHost(hostHeader: string): string {\n let h = hostHeader.trim().toLowerCase();\n const colon = h.indexOf(\":\");\n if (colon !== -1) h = h.slice(0, colon);\n if (h.startsWith(\"www.\")) h = h.slice(4);\n return h;\n}\n\n/**\n * Identificador de tienda a partir del `Host`: slug en `*.ecomiq.app`, FQDN en dominio propio.\n * Misma semántica que el sufijo de `buildStorefrontKvSnapshotKey` (sin el prefijo KV).\n */\nexport function resolveStorefrontSettingsHost(hostHeader: string): string {\n const host = normalizeStoreHost(hostHeader);\n if (!host) {\n throw Object.assign(new Error(\"Host inválido para tienda\"), { status: 400 });\n }\n if (host === ECOMIQ_APP_APEX) {\n throw Object.assign(new Error(\"Host apex ecomiq.app sin slug de tienda\"), { status: 400 });\n }\n if (ECOMIQ_APP_SUFFIX.some(suffix => host.endsWith(suffix))) {\n const slug = host.slice(0, -(ECOMIQ_APP_SUFFIX.find(suffix => host.endsWith(suffix))?.length ?? 0));\n if (!slug) {\n throw Object.assign(new Error(\"Host sin slug para ecomiq.app\"), { status: 400 });\n }\n return slug;\n }\n return host;\n}\n\n/**\n * Clave KV del snapshot de tienda.\n * - `*.ecomiq.app` → `storefront:snapshots:store:<slug>` (todo lo que va antes de `.ecomiq.app`, p. ej. `plata950`).\n * - Dominio propio (p. ej. `plata950.com`) → `storefront:snapshots:store:<dominio completo>`.\n */\nexport function buildStorefrontKvSnapshotKeyFromStoreKey(storeKey: string): string {\n const key = storeKey.trim();\n if (!key) {\n throw Object.assign(new Error(\"Store key vacío para KV\"), { status: 400 });\n }\n return `storefront:snapshots:store:${key}`;\n}\n\nexport function buildStorefrontKvSnapshotKey(hostHeader: string): string {\n return buildStorefrontKvSnapshotKeyFromStoreKey(\n resolveStorefrontSettingsHost(hostHeader),\n );\n}\n\nfunction getKvNamespace(env: unknown): KvJsonGet | undefined {\n if (!env || typeof env !== \"object\") return undefined;\n const ns = (env as Record<string, unknown>)[ECOMIQ_CLIENTS_STORE_KV_BINDING];\n if (!ns || typeof ns !== \"object\" || typeof (ns as KvJsonGet).get !== \"function\") {\n return undefined;\n }\n return ns as KvJsonGet;\n}\n\n/**\n * Lee settings desde KV con clave ya resuelta (slug o dominio).\n */\nexport async function getStorefrontSettingsFromKvByStoreKey(\n storeKey: string,\n): Promise<StorefrontSettings> {\n const { env } = await getCloudflareContext({ async: true });\n const kv = getKvNamespace(env);\n if (!kv) {\n const err = new Error(\n `Binding KV \"${ECOMIQ_CLIENTS_STORE_KV_BINDING}\" no encontrado. Configura kv_namespaces en wrangler.`\n );\n throw Object.assign(err, { status: 500 });\n }\n\n const cacheKey = buildStorefrontKvSnapshotKeyFromStoreKey(storeKey);\n const raw = await kv.get(cacheKey, { type: \"json\" });\n if (raw == null) {\n const err = new Error(\"Store settings not found in KV\");\n throw Object.assign(err, { status: 404 });\n }\n\n return StorefrontSettingsSchema.parse(raw);\n}\n\n/**\n * Lee settings desde KV (`ecomiq_clients_store`) usando la clave según el host.\n */\nexport async function getStorefrontSettingsFromKv(hostHeader: string): Promise<StorefrontSettings> {\n return getStorefrontSettingsFromKvByStoreKey(\n resolveStorefrontSettingsHost(hostHeader),\n );\n}\n","import { existsSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\nimport { resolveStorefrontSettingsHost } from \"../client/storefront-settings-kv.service\";\n\nconst CONFIG_FILENAMES = [\n \"ecomiq.config.js\",\n \"ecomiq.config.cjs\",\n \"ecomiq.config.mjs\",\n] as const;\n\nexport const EcomiqConfigSchema = z.object({\n /**\n * Slug de tienda en Ecomiq (p. ej. `mi-tienda` para `mi-tienda.ecomiq.app`).\n * Si está definido, tiene prioridad sobre el `Host` de la request (útil en `localhost`).\n */\n slugStore: z.string().min(1).optional(),\n});\n\nexport type EcomiqConfig = z.infer<typeof EcomiqConfigSchema>;\n\nlet cachedConfig: EcomiqConfig | null | undefined;\n\nfunction parseExportedConfig(raw: unknown): EcomiqConfig | null {\n const candidate =\n raw && typeof raw === \"object\" && \"default\" in (raw as object)\n ? (raw as { default: unknown }).default\n : raw;\n const parsed = EcomiqConfigSchema.safeParse(candidate);\n if (!parsed.success) {\n console.warn(\n \"[ecomiq] ecomiq.config.* inválido:\",\n parsed.error.flatten().fieldErrors,\n );\n return null;\n }\n const slugStore = parsed.data.slugStore?.trim();\n return slugStore ? { slugStore } : {};\n}\n\n/**\n * Carga `ecomiq.config.js` (o `.cjs` / `.mjs`) desde la raíz del proyecto (`process.cwd()`).\n * Resultado en caché por proceso.\n */\nexport function loadEcomiqConfig(cwd = process.cwd()): EcomiqConfig | null {\n if (cachedConfig !== undefined) return cachedConfig;\n\n for (const filename of CONFIG_FILENAMES) {\n const configPath = join(cwd, filename);\n if (!existsSync(configPath)) continue;\n\n try {\n const requireFromApp = createRequire(join(cwd, \"package.json\"));\n const loaded = requireFromApp(configPath) as unknown;\n const parsed = parseExportedConfig(loaded);\n cachedConfig = parsed;\n return cachedConfig;\n } catch (error) {\n console.warn(`[ecomiq] No se pudo cargar ${configPath}:`, error);\n }\n }\n\n cachedConfig = null;\n return null;\n}\n\n/** Limpia la caché (tests o recarga en dev). */\nexport function clearEcomiqConfigCache(): void {\n cachedConfig = undefined;\n}\n\n/**\n * Identificador de tienda para settings (API / KV).\n * 1. `slugStore` en `ecomiq.config.*` si existe.\n * 2. Si no, deriva del header `Host` (`resolveStorefrontSettingsHost`).\n */\nexport function resolvePublicStoreKey(\n hostHeader: string | null | undefined,\n cwd?: string,\n): string {\n const slugFromConfig = loadEcomiqConfig(cwd)?.slugStore?.trim();\n if (slugFromConfig) return slugFromConfig;\n\n if (!hostHeader?.trim()) {\n throw Object.assign(\n new Error(\n \"Host is required, o define slugStore en ecomiq.config.js en la raíz del proyecto\",\n ),\n { status: 400 },\n );\n }\n\n return resolveStorefrontSettingsHost(hostHeader);\n}\n\nexport function hasEcomiqSlugStoreConfig(cwd?: string): boolean {\n return Boolean(loadEcomiqConfig(cwd)?.slugStore?.trim());\n}\n"]}
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":""}
|
package/dist/nextjs/api.js
CHANGED
|
@@ -1,179 +1,6 @@
|
|
|
1
|
+
import { handleStoreProxyRequest } from '../chunk-Q762YXCQ.js';
|
|
1
2
|
import { NextResponse } from 'next/server';
|
|
2
3
|
|
|
3
|
-
// src/react/frameworks/nextjs/api/store-handler.ts
|
|
4
|
-
|
|
5
|
-
// src/core/constants/api-paths.ts
|
|
6
|
-
var STOREFRONT_API_PATH_PREFIX = "v1";
|
|
7
|
-
|
|
8
|
-
// src/core/constants/storefront-ecomiq-oauth-cookie.ts
|
|
9
|
-
var STOREFRONT_ECOMIQ_OAUTH_COOKIE_NAME = "ecomiq_sf_oauth_at";
|
|
10
|
-
|
|
11
|
-
// src/core/server/store-proxy-handler.ts
|
|
12
|
-
var DEFAULT_API_BASE_URL = "https://storefront.ecomiq.pe";
|
|
13
|
-
function jsonError(status, message, error) {
|
|
14
|
-
return Response.json({ error, message, status }, { status });
|
|
15
|
-
}
|
|
16
|
-
async function ensureStoreContext(request) {
|
|
17
|
-
const xStoreId = request.headers.get("x-store-id")?.trim();
|
|
18
|
-
const xStoreDomain = request.headers.get("x-store-domain")?.trim();
|
|
19
|
-
if (xStoreDomain) {
|
|
20
|
-
return {
|
|
21
|
-
ok: true,
|
|
22
|
-
storeId: xStoreId || "",
|
|
23
|
-
storeDomain: xStoreDomain || null
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
if (!xStoreId) {
|
|
27
|
-
return {
|
|
28
|
-
ok: false,
|
|
29
|
-
response: jsonError(
|
|
30
|
-
400,
|
|
31
|
-
"X-Store-Id is required",
|
|
32
|
-
"Store context required"
|
|
33
|
-
)
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
return {
|
|
37
|
-
ok: true,
|
|
38
|
-
storeId: xStoreId || "",
|
|
39
|
-
storeDomain: xStoreDomain || null
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
var SKIP_FORWARD_HEADERS = /* @__PURE__ */ new Set([
|
|
43
|
-
"host",
|
|
44
|
-
"connection",
|
|
45
|
-
"content-length",
|
|
46
|
-
"transfer-encoding",
|
|
47
|
-
"x-store-id",
|
|
48
|
-
"x-store-domain",
|
|
49
|
-
"authorization",
|
|
50
|
-
"cookie",
|
|
51
|
-
"cookie2",
|
|
52
|
-
"set-cookie",
|
|
53
|
-
"x-forwarded-for",
|
|
54
|
-
"x-forwarded-proto",
|
|
55
|
-
"x-forwarded-host",
|
|
56
|
-
"x-real-ip",
|
|
57
|
-
"forwarded",
|
|
58
|
-
"cf-connecting-ip",
|
|
59
|
-
"cf-connecting-ipv6",
|
|
60
|
-
"true-client-ip",
|
|
61
|
-
"cf-ipcountry",
|
|
62
|
-
"cf-ray",
|
|
63
|
-
"cf-visitor"
|
|
64
|
-
]);
|
|
65
|
-
function getClientIp(request) {
|
|
66
|
-
const candidates = [
|
|
67
|
-
request.headers.get("cf-connecting-ip"),
|
|
68
|
-
request.headers.get("true-client-ip"),
|
|
69
|
-
request.headers.get("x-real-ip")
|
|
70
|
-
];
|
|
71
|
-
for (const value of candidates) {
|
|
72
|
-
const trimmed = value?.trim();
|
|
73
|
-
if (trimmed) return trimmed;
|
|
74
|
-
}
|
|
75
|
-
const xff = request.headers.get("x-forwarded-for");
|
|
76
|
-
if (xff?.trim()) {
|
|
77
|
-
const first = xff.split(",")[0]?.trim();
|
|
78
|
-
if (first) return first;
|
|
79
|
-
}
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
function getCookieValue(request, name) {
|
|
83
|
-
const cookieHeader = request.headers.get("cookie");
|
|
84
|
-
if (!cookieHeader) return void 0;
|
|
85
|
-
for (const part of cookieHeader.split(";")) {
|
|
86
|
-
const [rawKey, ...rest] = part.trim().split("=");
|
|
87
|
-
if (rawKey?.trim() === name) {
|
|
88
|
-
return decodeURIComponent(rest.join("="));
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
return void 0;
|
|
92
|
-
}
|
|
93
|
-
function buildUpstreamRequest(request, pathSegments, config, storeId, storeDomain) {
|
|
94
|
-
const requestUrl = new URL(request.url);
|
|
95
|
-
const base = (config.apiBaseUrl ?? DEFAULT_API_BASE_URL).replace(/\/$/, "");
|
|
96
|
-
const userPath = pathSegments.length ? pathSegments.join("/") : "";
|
|
97
|
-
const path = userPath ? `${STOREFRONT_API_PATH_PREFIX}/${userPath}` : STOREFRONT_API_PATH_PREFIX;
|
|
98
|
-
const search = requestUrl.searchParams.toString();
|
|
99
|
-
const url = search ? `${base}/${path}?${search}` : `${base}/${path}`;
|
|
100
|
-
const headers = new Headers();
|
|
101
|
-
request.headers.forEach((value, key) => {
|
|
102
|
-
const lower = key.toLowerCase();
|
|
103
|
-
if (!SKIP_FORWARD_HEADERS.has(lower)) {
|
|
104
|
-
headers.set(key, value);
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
headers.set("X-Store-Id", storeId);
|
|
108
|
-
if (storeDomain) {
|
|
109
|
-
headers.set("X-Store-domain", storeDomain);
|
|
110
|
-
}
|
|
111
|
-
const clientIp = getClientIp(request);
|
|
112
|
-
if (clientIp) {
|
|
113
|
-
headers.set("X-Forwarded-For", clientIp);
|
|
114
|
-
}
|
|
115
|
-
const forwardedProto = request.headers.get("cf-visitor")?.match(/"scheme":"(https?)"/)?.[1] ?? requestUrl.protocol.replace(":", "") ?? "https";
|
|
116
|
-
headers.set("X-Forwarded-Proto", forwardedProto);
|
|
117
|
-
const forwardedHost = request.headers.get("host") ?? requestUrl.host;
|
|
118
|
-
if (forwardedHost) {
|
|
119
|
-
headers.set("X-Forwarded-Host", forwardedHost);
|
|
120
|
-
}
|
|
121
|
-
const incomingAuth = request.headers.get("authorization")?.trim();
|
|
122
|
-
const storefrontOAuth = getCookieValue(request, STOREFRONT_ECOMIQ_OAUTH_COOKIE_NAME)?.trim();
|
|
123
|
-
if (incomingAuth && /^Bearer\s+\S+/i.test(incomingAuth)) {
|
|
124
|
-
headers.set("Authorization", incomingAuth);
|
|
125
|
-
} else if (storefrontOAuth) {
|
|
126
|
-
headers.set("Authorization", `Bearer ${storefrontOAuth}`);
|
|
127
|
-
}
|
|
128
|
-
headers.set("Accept-Encoding", "identity");
|
|
129
|
-
const init = {
|
|
130
|
-
method: request.method,
|
|
131
|
-
headers
|
|
132
|
-
};
|
|
133
|
-
const bodyMethods = ["POST", "PUT", "PATCH"];
|
|
134
|
-
if (bodyMethods.includes(request.method) && request.body) {
|
|
135
|
-
init.body = request.body;
|
|
136
|
-
init.duplex = "half";
|
|
137
|
-
}
|
|
138
|
-
return { url, init };
|
|
139
|
-
}
|
|
140
|
-
function isResponseBodyForbidden(status) {
|
|
141
|
-
return status === 204 || status === 205 || status === 304;
|
|
142
|
-
}
|
|
143
|
-
async function handleStoreProxyRequest(request, pathSegments, config = {}) {
|
|
144
|
-
const storeContext = await ensureStoreContext(request);
|
|
145
|
-
if (!storeContext.ok) {
|
|
146
|
-
return storeContext.response;
|
|
147
|
-
}
|
|
148
|
-
const { storeId, storeDomain } = storeContext;
|
|
149
|
-
const { url, init } = buildUpstreamRequest(
|
|
150
|
-
request,
|
|
151
|
-
pathSegments,
|
|
152
|
-
config,
|
|
153
|
-
storeId,
|
|
154
|
-
storeDomain
|
|
155
|
-
);
|
|
156
|
-
const upstream = await fetch(url, init);
|
|
157
|
-
const responseHeaders = new Headers(upstream.headers);
|
|
158
|
-
const status = upstream.status;
|
|
159
|
-
if (isResponseBodyForbidden(status)) {
|
|
160
|
-
responseHeaders.delete("content-length");
|
|
161
|
-
responseHeaders.delete("content-type");
|
|
162
|
-
return new Response(null, {
|
|
163
|
-
status,
|
|
164
|
-
statusText: upstream.statusText,
|
|
165
|
-
headers: responseHeaders
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
const body = await upstream.text();
|
|
169
|
-
return new Response(body, {
|
|
170
|
-
status,
|
|
171
|
-
statusText: upstream.statusText,
|
|
172
|
-
headers: responseHeaders
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// src/react/frameworks/nextjs/api/store-handler.ts
|
|
177
4
|
function toNextJsStoreApiHandler(config = {}) {
|
|
178
5
|
const handler = async (request, context) => {
|
|
179
6
|
const params = await context.params;
|
package/dist/nextjs/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/constants/api-paths.ts","../../src/core/constants/storefront-ecomiq-oauth-cookie.ts","../../src/core/server/store-proxy-handler.ts","../../src/react/frameworks/nextjs/api/store-handler.ts"],"names":[],"mappings":"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","file":"api.js","sourcesContent":["/** Prefijo base de la API storefront (ej. v1/storefront). */\nexport const STOREFRONT_API_PATH_PREFIX = \"v1\";\n","/** Cookie HttpOnly con el bearer OAuth storefront; solo path `/api/store` (no navega a todo el sitio). */\nexport const STOREFRONT_ECOMIQ_OAUTH_COOKIE_NAME = \"ecomiq_sf_oauth_at\";\n\n/** Debe coincidir con el prefijo de la ruta proxy en Next (`app/api/store/...`). */\nexport const STOREFRONT_ECOMIQ_OAUTH_COOKIE_PATH = \"/api/store\";\n","import { STOREFRONT_API_PATH_PREFIX } from \"../constants/api-paths\";\nimport { STOREFRONT_ECOMIQ_OAUTH_COOKIE_NAME } from \"../constants/storefront-ecomiq-oauth-cookie\";\n\nconst DEFAULT_API_BASE_URL = \"https://storefront.ecomiq.pe\";\n\nexport type StoreProxyHandlerConfig = {\n /** Base URL del API de storefront. Default: `https://storefront.ecomiq.pe` */\n apiBaseUrl?: string;\n};\n\ntype StoreContextResult =\n | {\n ok: true;\n storeId: string;\n storeDomain: string | null;\n }\n | { ok: false; response: Response };\n\nfunction jsonError(status: number, message: string, error: string): Response {\n return Response.json({ error, message, status }, { status });\n}\n\nasync function ensureStoreContext(request: Request): Promise<StoreContextResult> {\n const xStoreId = request.headers.get(\"x-store-id\")?.trim();\n const xStoreDomain = request.headers.get(\"x-store-domain\")?.trim();\n if (xStoreDomain) {\n return {\n ok: true,\n storeId: xStoreId || \"\",\n storeDomain: xStoreDomain || null,\n };\n }\n if (!xStoreId) {\n return {\n ok: false,\n response: jsonError(\n 400,\n \"X-Store-Id is required\",\n \"Store context required\",\n ),\n };\n }\n\n return {\n ok: true,\n storeId: xStoreId || \"\",\n storeDomain: xStoreDomain || null,\n };\n}\n\nconst SKIP_FORWARD_HEADERS = new Set([\n \"host\",\n \"connection\",\n \"content-length\",\n \"transfer-encoding\",\n \"x-store-id\",\n \"x-store-domain\",\n \"authorization\",\n \"cookie\",\n \"cookie2\",\n \"set-cookie\",\n \"x-forwarded-for\",\n \"x-forwarded-proto\",\n \"x-forwarded-host\",\n \"x-real-ip\",\n \"forwarded\",\n \"cf-connecting-ip\",\n \"cf-connecting-ipv6\",\n \"true-client-ip\",\n \"cf-ipcountry\",\n \"cf-ray\",\n \"cf-visitor\",\n]);\n\nfunction getClientIp(request: Request): string | null {\n const candidates = [\n request.headers.get(\"cf-connecting-ip\"),\n request.headers.get(\"true-client-ip\"),\n request.headers.get(\"x-real-ip\"),\n ];\n for (const value of candidates) {\n const trimmed = value?.trim();\n if (trimmed) return trimmed;\n }\n const xff = request.headers.get(\"x-forwarded-for\");\n if (xff?.trim()) {\n const first = xff.split(\",\")[0]?.trim();\n if (first) return first;\n }\n return null;\n}\n\nfunction getCookieValue(request: Request, name: string): string | undefined {\n const cookieHeader = request.headers.get(\"cookie\");\n if (!cookieHeader) return undefined;\n for (const part of cookieHeader.split(\";\")) {\n const [rawKey, ...rest] = part.trim().split(\"=\");\n if (rawKey?.trim() === name) {\n return decodeURIComponent(rest.join(\"=\"));\n }\n }\n return undefined;\n}\n\nfunction buildUpstreamRequest(\n request: Request,\n pathSegments: string[],\n config: StoreProxyHandlerConfig,\n storeId: string,\n storeDomain: string | null,\n): { url: string; init: RequestInit & { duplex?: \"half\" } } {\n const requestUrl = new URL(request.url);\n const base = (config.apiBaseUrl ?? DEFAULT_API_BASE_URL).replace(/\\/$/, \"\");\n const userPath = pathSegments.length ? pathSegments.join(\"/\") : \"\";\n const path = userPath\n ? `${STOREFRONT_API_PATH_PREFIX}/${userPath}`\n : STOREFRONT_API_PATH_PREFIX;\n const search = requestUrl.searchParams.toString();\n const url = search ? `${base}/${path}?${search}` : `${base}/${path}`;\n\n const headers = new Headers();\n request.headers.forEach((value, key) => {\n const lower = key.toLowerCase();\n if (!SKIP_FORWARD_HEADERS.has(lower)) {\n headers.set(key, value);\n }\n });\n headers.set(\"X-Store-Id\", storeId);\n if (storeDomain) {\n headers.set(\"X-Store-domain\", storeDomain);\n }\n\n const clientIp = getClientIp(request);\n if (clientIp) {\n headers.set(\"X-Forwarded-For\", clientIp);\n }\n const forwardedProto =\n request.headers.get(\"cf-visitor\")?.match(/\"scheme\":\"(https?)\"/)?.[1] ??\n requestUrl.protocol.replace(\":\", \"\") ??\n \"https\";\n headers.set(\"X-Forwarded-Proto\", forwardedProto);\n const forwardedHost = request.headers.get(\"host\") ?? requestUrl.host;\n if (forwardedHost) {\n headers.set(\"X-Forwarded-Host\", forwardedHost);\n }\n\n const incomingAuth = request.headers.get(\"authorization\")?.trim();\n const storefrontOAuth = getCookieValue(request, STOREFRONT_ECOMIQ_OAUTH_COOKIE_NAME)?.trim();\n\n if (incomingAuth && /^Bearer\\s+\\S+/i.test(incomingAuth)) {\n headers.set(\"Authorization\", incomingAuth);\n } else if (storefrontOAuth) {\n headers.set(\"Authorization\", `Bearer ${storefrontOAuth}`);\n }\n headers.set(\"Accept-Encoding\", \"identity\");\n\n const init: RequestInit & { duplex?: \"half\" } = {\n method: request.method,\n headers,\n };\n\n const bodyMethods = [\"POST\", \"PUT\", \"PATCH\"];\n if (bodyMethods.includes(request.method) && request.body) {\n init.body = request.body;\n init.duplex = \"half\";\n }\n\n return { url, init };\n}\n\nfunction isResponseBodyForbidden(status: number): boolean {\n return status === 204 || status === 205 || status === 304;\n}\n\n/**\n * Proxy BFF `/api/store/*` → upstream Ecomiq. Usa Web Fetch API (`Request` / `Response`).\n */\nexport async function handleStoreProxyRequest(\n request: Request,\n pathSegments: string[],\n config: StoreProxyHandlerConfig = {},\n): Promise<Response> {\n const storeContext = await ensureStoreContext(request);\n if (!storeContext.ok) {\n return storeContext.response;\n }\n\n const { storeId, storeDomain } = storeContext;\n const { url, init } = buildUpstreamRequest(\n request,\n pathSegments,\n config,\n storeId,\n storeDomain,\n );\n\n const upstream = await fetch(url, init);\n const responseHeaders = new Headers(upstream.headers);\n const status = upstream.status;\n\n if (isResponseBodyForbidden(status)) {\n responseHeaders.delete(\"content-length\");\n responseHeaders.delete(\"content-type\");\n return new Response(null, {\n status,\n statusText: upstream.statusText,\n headers: responseHeaders,\n });\n }\n\n const body = await upstream.text();\n return new Response(body, {\n status,\n statusText: upstream.statusText,\n headers: responseHeaders,\n });\n}\n","import type { NextRequest } from \"next/server\";\nimport { NextResponse } from \"next/server\";\nimport {\n handleStoreProxyRequest,\n type StoreProxyHandlerConfig,\n} from \"../../../../core/server/store-proxy-handler\";\n\nexport type StoreApiHandlerConfig = StoreProxyHandlerConfig;\n\n/**\n * Crea los handlers de ruta para montar la API de store como proxy en Next.js App Router.\n *\n * ```ts\n * // app/api/store/[...path]/route.ts\n * import { toNextJsStoreApiHandler } from \"@ecomiq/storefront/nextjs/api\";\n *\n * export const { GET, POST, PUT, PATCH, DELETE } = toNextJsStoreApiHandler({\n * apiBaseUrl: process.env.STOREFRONT_API_URL,\n * });\n * ```\n */\nexport function toNextJsStoreApiHandler(config: StoreApiHandlerConfig = {}) {\n const handler = async (\n request: NextRequest,\n context: { params: Promise<{ path?: string[] }> },\n ): Promise<NextResponse> => {\n const params = await context.params;\n const pathSegments = params.path ?? [];\n const response = await handleStoreProxyRequest(\n request,\n pathSegments,\n config,\n );\n return new NextResponse(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n });\n };\n\n return {\n GET: handler,\n POST: handler,\n PUT: handler,\n PATCH: handler,\n DELETE: handler,\n };\n}\n\nexport { handleStoreProxyRequest } from \"../../../../core/server/store-proxy-handler\";\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/react/frameworks/nextjs/api/store-handler.ts"],"names":[],"mappings":";;;AAqBO,SAAS,uBAAA,CAAwB,MAAA,GAAgC,EAAC,EAAG;AAC1E,EAAA,MAAM,OAAA,GAAU,OACd,OAAA,EACA,OAAA,KAC0B;AAC1B,IAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,MAAA;AAC7B,IAAA,MAAM,YAAA,GAAe,MAAA,CAAO,IAAA,IAAQ,EAAC;AACrC,IAAA,MAAM,WAAW,MAAM,uBAAA;AAAA,MACrB,OAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,OAAO,IAAI,YAAA,CAAa,QAAA,CAAS,IAAA,EAAM;AAAA,MACrC,QAAQ,QAAA,CAAS,MAAA;AAAA,MACjB,YAAY,QAAA,CAAS,UAAA;AAAA,MACrB,SAAS,QAAA,CAAS;AAAA,KACnB,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,OAAA;AAAA,IACL,IAAA,EAAM,OAAA;AAAA,IACN,GAAA,EAAK,OAAA;AAAA,IACL,KAAA,EAAO,OAAA;AAAA,IACP,MAAA,EAAQ;AAAA,GACV;AACF","file":"api.js","sourcesContent":["import type { NextRequest } from \"next/server\";\nimport { NextResponse } from \"next/server\";\nimport {\n handleStoreProxyRequest,\n type StoreProxyHandlerConfig,\n} from \"../../../../core/server/store-proxy-handler\";\n\nexport type StoreApiHandlerConfig = StoreProxyHandlerConfig;\n\n/**\n * Crea los handlers de ruta para montar la API de store como proxy en Next.js App Router.\n *\n * ```ts\n * // app/api/store/[...path]/route.ts\n * import { toNextJsStoreApiHandler } from \"@ecomiq/storefront/nextjs/api\";\n *\n * export const { GET, POST, PUT, PATCH, DELETE } = toNextJsStoreApiHandler({\n * apiBaseUrl: process.env.STOREFRONT_API_URL,\n * });\n * ```\n */\nexport function toNextJsStoreApiHandler(config: StoreApiHandlerConfig = {}) {\n const handler = async (\n request: NextRequest,\n context: { params: Promise<{ path?: string[] }> },\n ): Promise<NextResponse> => {\n const params = await context.params;\n const pathSegments = params.path ?? [];\n const response = await handleStoreProxyRequest(\n request,\n pathSegments,\n config,\n );\n return new NextResponse(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n });\n };\n\n return {\n GET: handler,\n POST: handler,\n PUT: handler,\n PATCH: handler,\n DELETE: handler,\n };\n}\n\nexport { handleStoreProxyRequest } from \"../../../../core/server/store-proxy-handler\";\n"]}
|
package/dist/nextjs.d.ts
CHANGED
|
@@ -1,41 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Devuelve el host completo de la request (ej. "plata950.ecomiq.pe", "localhost:3000").
|
|
17
|
-
*/
|
|
18
|
-
declare function getHostname(): Promise<string | null>;
|
|
19
|
-
|
|
20
|
-
type GetPublicStoreOptions = {
|
|
21
|
-
/** Si se omite, se usa `resolvePublicStoreSettingsSource()` (variable de entorno). */
|
|
22
|
-
source?: PublicStoreSettingsSource;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Obtiene la tienda pública (Next.js App Router).
|
|
27
|
-
* Usa `headers()` para resolver host y origen del proxy.
|
|
28
|
-
*
|
|
29
|
-
* Identificador de tienda:
|
|
30
|
-
* 1. `slugStore` en `ecomiq.config.js` (prioridad en localhost).
|
|
31
|
-
* 2. Si no, deriva del header `Host`.
|
|
32
|
-
*/
|
|
33
|
-
declare function getPublicStore(options?: GetPublicStoreOptions): Promise<PublicStoreResult>;
|
|
34
|
-
/**
|
|
35
|
-
* Igual que `getPublicStore` pero con headers explícitos (tests, middleware custom).
|
|
36
|
-
*/
|
|
37
|
-
declare function getPublicStoreFromHeaders(headerList: {
|
|
38
|
-
get(name: string): string | null;
|
|
39
|
-
}, options?: Omit<FetchPublicStoreSettingsOptions, "host">): Promise<PublicStoreResult>;
|
|
40
|
-
|
|
41
|
-
export { FetchPublicStoreSettingsOptions, PublicStoreResult, PublicStoreSettingsSource, getHostname, getPublicStore, getPublicStoreFromHeaders };
|
|
1
|
+
export * from "./chunks/server-nextjs";
|
|
2
|
+
export {
|
|
3
|
+
EcomiqProvider,
|
|
4
|
+
useStoreProducts,
|
|
5
|
+
useStoreCollections,
|
|
6
|
+
useStorePages,
|
|
7
|
+
useStoreCart,
|
|
8
|
+
useStore,
|
|
9
|
+
useCart,
|
|
10
|
+
useStorefrontSession,
|
|
11
|
+
useStorefrontAuthClient,
|
|
12
|
+
} from "./chunks/client";
|
|
13
|
+
export type { EcomiqProviderProps } from "./chunks/client";
|