@ecomiq/storefront 1.1.9 → 2.0.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.
Files changed (134) hide show
  1. package/README.md +30 -415
  2. package/bin/ecomiq.mjs +165 -0
  3. package/package.json +72 -94
  4. package/src/api-proxy.ts +194 -0
  5. package/src/auth/create-storefront-auth.ts +35 -0
  6. package/src/auth/ecomiq-oauth-password-client.ts +26 -0
  7. package/src/auth/ecomiq-oauth-password-constants.ts +26 -0
  8. package/src/auth/ecomiq-oauth-password-plugin.ts +299 -0
  9. package/src/auth/ecomiq-oauth-password-types.ts +25 -0
  10. package/src/auth/ecomiq-storefront-sign-in.ts +47 -0
  11. package/src/auth/env.ts +7 -0
  12. package/src/cart-session.ts +241 -0
  13. package/src/client.ts +48 -0
  14. package/src/codegen.mjs +704 -0
  15. package/src/components/checkout/cart-sync.ts +143 -0
  16. package/src/components/checkout/checkout-external-update-banner.tsx +15 -0
  17. package/src/components/checkout/checkout-form-controls.tsx +139 -0
  18. package/src/components/checkout/checkout-line-items.tsx +43 -0
  19. package/src/components/checkout/checkout-order-summary.tsx +156 -0
  20. package/src/components/checkout/checkout-payment-section.tsx +215 -0
  21. package/src/components/checkout/checkout-session-view.tsx +240 -0
  22. package/src/components/checkout/checkout-shipping-address-section.tsx +266 -0
  23. package/src/components/checkout/checkout-shipping-section.tsx +90 -0
  24. package/src/components/checkout/checkout-states.tsx +73 -0
  25. package/src/components/checkout/form-schema.ts +229 -0
  26. package/src/components/checkout/format.ts +27 -0
  27. package/src/components/checkout/index.ts +51 -0
  28. package/src/components/checkout/types.ts +43 -0
  29. package/src/components/checkout/use-checkout-geo.ts +50 -0
  30. package/src/components/checkout/use-checkout-session.ts +583 -0
  31. package/src/components/hero.tsx +291 -0
  32. package/src/config.d.ts +69 -0
  33. package/src/config.mjs +165 -0
  34. package/src/index.ts +274 -0
  35. package/src/link.tsx +2 -0
  36. package/src/pages/checkout.$checkoutId.tsx +60 -0
  37. package/src/pages/checkout.tsx +31 -0
  38. package/src/pages/thank-you.tsx +53 -0
  39. package/src/providers/auth.tsx +69 -0
  40. package/src/providers/cart.tsx +275 -0
  41. package/src/providers/ecomiq.ts +137 -0
  42. package/src/providers/index.ts +26 -0
  43. package/src/public-config.ts +44 -0
  44. package/src/review-submission.ts +89 -0
  45. package/src/runtime/context.ts +1 -0
  46. package/src/runtime/default-layout.tsx +80 -0
  47. package/src/runtime/head.ts +126 -0
  48. package/src/runtime/page.tsx +82 -0
  49. package/src/runtime/postcss-browser-stub.mjs +5 -0
  50. package/src/server-config-store.ts +26 -0
  51. package/src/server.ts +279 -0
  52. package/src/styles.css +76 -0
  53. package/src/ui/badge.tsx +32 -0
  54. package/src/ui/button.tsx +31 -0
  55. package/src/ui/card.tsx +31 -0
  56. package/src/ui/carousel.tsx +218 -0
  57. package/src/ui/cn.ts +6 -0
  58. package/src/ui/index.ts +8 -0
  59. package/src/ui/separator.tsx +6 -0
  60. package/src/ui/skeleton.tsx +6 -0
  61. package/src/ui/storefront-error.tsx +49 -0
  62. package/src/utils.ts +36 -0
  63. package/src/vite-inline.mjs +135 -0
  64. package/templates/__root.tsx +77 -0
  65. package/templates/router.tsx +19 -0
  66. package/dist/chunk-64GLOWMJ.js +0 -216
  67. package/dist/chunk-64GLOWMJ.js.map +0 -1
  68. package/dist/chunk-AKD5IDEB.js +0 -177
  69. package/dist/chunk-AKD5IDEB.js.map +0 -1
  70. package/dist/chunk-EFEVJJWF.js +0 -1345
  71. package/dist/chunk-EFEVJJWF.js.map +0 -1
  72. package/dist/chunk-NAJQB5DN.js +0 -155
  73. package/dist/chunk-NAJQB5DN.js.map +0 -1
  74. package/dist/chunk-OABDGTBI.js +0 -253
  75. package/dist/chunk-OABDGTBI.js.map +0 -1
  76. package/dist/chunk-Q4U5OEUT.js +0 -21
  77. package/dist/chunk-Q4U5OEUT.js.map +0 -1
  78. package/dist/chunk-S7CPZ4UE.js +0 -6
  79. package/dist/chunk-S7CPZ4UE.js.map +0 -1
  80. package/dist/chunks/client.css +0 -984
  81. package/dist/chunks/client.css.map +0 -1
  82. package/dist/chunks/client.d.ts +0 -10759
  83. package/dist/chunks/client.js +0 -5398
  84. package/dist/chunks/client.js.map +0 -1
  85. package/dist/chunks/config.d.ts +0 -31
  86. package/dist/chunks/config.js +0 -5
  87. package/dist/chunks/config.js.map +0 -1
  88. package/dist/chunks/core-public.d.ts +0 -130
  89. package/dist/chunks/core-public.js +0 -92
  90. package/dist/chunks/core-public.js.map +0 -1
  91. package/dist/chunks/server-nextjs.d.ts +0 -33
  92. package/dist/chunks/server-nextjs.js +0 -59
  93. package/dist/chunks/server-nextjs.js.map +0 -1
  94. package/dist/chunks/server-tanstack.d.ts +0 -22
  95. package/dist/chunks/server-tanstack.js +0 -40
  96. package/dist/chunks/server-tanstack.js.map +0 -1
  97. package/dist/collection-DU7gREXS.d.ts +0 -4062
  98. package/dist/ecomiq-oauth-password-plugin-B_gMdGuc.d.ts +0 -3631
  99. package/dist/ecomiq-shell-ui-SWIFLQVM.js +0 -8
  100. package/dist/ecomiq-shell-ui-SWIFLQVM.js.map +0 -1
  101. package/dist/index.d.ts +0 -9
  102. package/dist/index.js +0 -1
  103. package/dist/index.js.map +0 -1
  104. package/dist/index.server.d.ts +0 -9
  105. package/dist/index.server.js +0 -8
  106. package/dist/index.server.js.map +0 -1
  107. package/dist/nextjs/api.d.ts +0 -45
  108. package/dist/nextjs/api.js +0 -32
  109. package/dist/nextjs/api.js.map +0 -1
  110. package/dist/nextjs/globals.css +0 -13
  111. package/dist/nextjs.d.ts +0 -2
  112. package/dist/nextjs.js +0 -2
  113. package/dist/nextjs.js.map +0 -1
  114. package/dist/nextjs.server.d.ts +0 -18
  115. package/dist/nextjs.server.js +0 -1
  116. package/dist/nextjs.server.js.map +0 -1
  117. package/dist/postcss.config.mjs +0 -6
  118. package/dist/react/checkout-page.css +0 -855
  119. package/dist/react/client.css +0 -984
  120. package/dist/react/payment-provider.css +0 -91
  121. package/dist/react/thank-you-page.css +0 -105
  122. package/dist/react.d.ts +0 -1
  123. package/dist/react.js +0 -2
  124. package/dist/react.js.map +0 -1
  125. package/dist/store-proxy-handler-CNzKlTFA.d.ts +0 -10
  126. package/dist/tanstack/api.d.ts +0 -41
  127. package/dist/tanstack/api.js +0 -30
  128. package/dist/tanstack/api.js.map +0 -1
  129. package/dist/tanstack.d.ts +0 -1
  130. package/dist/tanstack.js +0 -2
  131. package/dist/tanstack.js.map +0 -1
  132. package/dist/tanstack.server.d.ts +0 -18
  133. package/dist/tanstack.server.js +0 -1
  134. package/dist/tanstack.server.js.map +0 -1
@@ -1,216 +0,0 @@
1
- import { DEFAULT_CURRENCY_CODE } from './chunk-Q4U5OEUT.js';
2
- import { z } from 'zod';
3
-
4
- var StorefrontCheckoutSettingsSchema = z.object({
5
- allowGuestCheckout: z.boolean().optional(),
6
- identityScope: z.enum(["store", "tenant", "global"]).optional(),
7
- signInMethods: z.array(z.string()).optional()
8
- });
9
- var looseRecord = z.record(z.string(), z.unknown());
10
- var StorefrontThemeConfigSchema = z.object({
11
- name: z.string().nullable().optional(),
12
- mode: z.string().nullable().optional(),
13
- colors: looseRecord.optional(),
14
- fonts: looseRecord.optional(),
15
- assets: looseRecord.optional()
16
- }).passthrough();
17
- var StorefrontFeaturesEnabledSchema = z.object({
18
- flags: looseRecord.optional()
19
- }).passthrough();
20
- var StorefrontCmsBrandingSchema = z.object({
21
- logoUrl: z.string().nullable().optional(),
22
- logoDarkUrl: z.string().nullable().optional(),
23
- faviconUrl: z.string().nullable().optional(),
24
- socialImageUrl: z.string().nullable().optional()
25
- });
26
- var StorefrontCmsSeoSchema = z.object({
27
- siteName: z.string().nullable().optional(),
28
- metaTitle: z.string().nullable().optional(),
29
- metaDescription: z.string().nullable().optional(),
30
- titleTemplate: z.string().nullable().optional(),
31
- robotsIndex: z.boolean().optional()
32
- });
33
- var StorefrontCmsSocialLinksSchema = z.object({
34
- instagram: z.string().nullable().optional(),
35
- facebook: z.string().nullable().optional(),
36
- tiktok: z.string().nullable().optional(),
37
- youtube: z.string().nullable().optional(),
38
- x: z.string().nullable().optional()
39
- });
40
- var StorefrontCmsContactSchema = z.object({
41
- supportEmail: z.string().nullable().optional(),
42
- phone: z.string().nullable().optional(),
43
- whatsapp: z.string().nullable().optional(),
44
- address: z.string().nullable().optional(),
45
- socialLinks: StorefrontCmsSocialLinksSchema.optional()
46
- });
47
- var StorefrontCmsTrackingSchema = z.object({
48
- googleAnalyticsMeasurementId: z.string().nullable().optional(),
49
- metaPixelId: z.string().nullable().optional(),
50
- googleTagManagerContainerId: z.string().nullable().optional()
51
- });
52
- var StorefrontCmsCustomScriptsSchema = z.object({
53
- enabled: z.boolean().optional(),
54
- head: z.string().nullable().optional(),
55
- bodyEnd: z.string().nullable().optional()
56
- });
57
- var StorefrontCmsChannelsSchema = z.object({
58
- storefront: z.object({
59
- enabled: z.boolean().optional()
60
- }).optional(),
61
- pos: z.object({
62
- enabled: z.boolean().optional()
63
- }).optional()
64
- });
65
- var StorefrontCmsSettingsSchema = z.object({
66
- themeKey: z.string().optional(),
67
- channels: StorefrontCmsChannelsSchema.optional(),
68
- branding: StorefrontCmsBrandingSchema.optional(),
69
- seo: StorefrontCmsSeoSchema.optional(),
70
- contact: StorefrontCmsContactSchema.optional(),
71
- tracking: StorefrontCmsTrackingSchema.optional(),
72
- customScripts: StorefrontCmsCustomScriptsSchema.optional(),
73
- updatedOn: z.string().nullable().optional()
74
- });
75
- var StorefrontCmsPageSchema = z.object({
76
- id: z.string(),
77
- name: z.string(),
78
- slug: z.string(),
79
- channel: z.string().transform((value) => value.toLowerCase()).pipe(z.enum(["storefront", "pos"])).default("storefront"),
80
- layout: z.string().optional(),
81
- version: z.number().optional(),
82
- settings: z.record(z.string(), z.unknown()).optional().nullable(),
83
- sections: z.array(z.unknown()).optional(),
84
- status: z.string().optional(),
85
- hasPublishedVersion: z.boolean().optional(),
86
- publishedOn: z.string().nullable().optional(),
87
- publishedBy: z.string().nullable().optional(),
88
- createdOn: z.string().nullable().optional(),
89
- updatedOn: z.string().nullable().optional(),
90
- createdBy: z.string().nullable().optional(),
91
- updatedBy: z.string().nullable().optional(),
92
- lastModifiedBy: z.string().nullable().optional()
93
- }).passthrough();
94
- var StorefrontSettingsLegacyFlatSchema = z.object({
95
- id: z.coerce.string(),
96
- tenantId: z.string().nullable().optional(),
97
- name: z.string(),
98
- slug: z.coerce.string().optional(),
99
- description: z.string().nullable().optional(),
100
- visibility: z.string().nullable().optional(),
101
- logo: z.string().nullable().optional(),
102
- favicon: z.string().nullable().optional(),
103
- icon: z.string().nullable().optional(),
104
- currency: z.string().nullable().optional(),
105
- language: z.string().nullable().optional(),
106
- themeConfig: z.unknown().optional().nullable(),
107
- featuresEnabled: z.unknown().optional().nullable(),
108
- checkoutSettings: StorefrontCheckoutSettingsSchema.optional().nullable()
109
- }).passthrough();
110
- function unwrapSettingsResponseBody(v) {
111
- if (!v || typeof v !== "object" || Array.isArray(v)) return v;
112
- const o = v;
113
- if ("data" in o && o.data != null && typeof o.data === "object" && !Array.isArray(o.data)) {
114
- return o.data;
115
- }
116
- return v;
117
- }
118
- function isLegacyFlatSettingsPayload(v) {
119
- if (!v || typeof v !== "object" || Array.isArray(v)) return false;
120
- const o = v;
121
- if ("store" in o || "schemaVersion" in o || "cms" in o) return false;
122
- return (typeof o.id === "string" || typeof o.id === "number") && typeof o.name === "string";
123
- }
124
- function normalizeStorefrontSettingsPayload(v) {
125
- const body = unwrapSettingsResponseBody(v);
126
- if (!isLegacyFlatSettingsPayload(body)) return body;
127
- const raw = body;
128
- const parsed = StorefrontSettingsLegacyFlatSchema.safeParse(raw);
129
- if (!parsed.success) return body;
130
- const l = parsed.data;
131
- const currency = l.currency?.trim() ? l.currency : DEFAULT_CURRENCY_CODE;
132
- const language = l.language?.trim() ? l.language : "es";
133
- const slug = l.slug?.trim() ? l.slug : l.id;
134
- return {
135
- schemaVersion: 0,
136
- generatedAt: (/* @__PURE__ */ new Date(0)).toISOString(),
137
- store: {
138
- id: l.id,
139
- tenantId: l.tenantId ?? void 0,
140
- name: l.name,
141
- slug,
142
- description: l.description ?? null,
143
- logo: l.logo ?? null,
144
- icon: l.icon ?? null,
145
- visibility: l.visibility ?? void 0,
146
- currency,
147
- language,
148
- themeConfig: l.themeConfig ?? void 0,
149
- featuresEnabled: l.featuresEnabled ?? void 0,
150
- checkoutSettings: l.checkoutSettings ?? void 0
151
- },
152
- cms: {
153
- settings: {
154
- branding: {
155
- faviconUrl: l.favicon ?? null,
156
- logoUrl: l.logo ?? null,
157
- logoDarkUrl: null,
158
- socialImageUrl: null
159
- }
160
- },
161
- pages: []
162
- }
163
- };
164
- }
165
- var StorefrontStoreSchema = z.object({
166
- id: z.string(),
167
- tenantId: z.string().optional(),
168
- sellerId: z.string().optional(),
169
- plan: z.string().optional(),
170
- storageLimitBytes: z.number().optional(),
171
- monthlyTransferLimitBytes: z.number().optional(),
172
- maxUploadSizeBytes: z.number().optional(),
173
- maxStores: z.number().optional(),
174
- maxMembers: z.number().optional(),
175
- maxProducts: z.number().optional(),
176
- maxCategories: z.number().optional(),
177
- maxBrands: z.number().optional(),
178
- maxAttributes: z.number().optional(),
179
- maxCollections: z.number().optional(),
180
- enableApi: z.boolean().optional(),
181
- isActive: z.boolean().optional(),
182
- name: z.string(),
183
- description: z.string().nullable().optional(),
184
- avatarUrl: z.string().nullable().optional(),
185
- logo: z.string().nullable().optional(),
186
- icon: z.string().nullable().optional(),
187
- slug: z.string(),
188
- domain: z.string().nullable().optional(),
189
- domains: z.array(z.string()).optional(),
190
- timeZone: z.string().nullable().optional(),
191
- currency: z.string(),
192
- language: z.string(),
193
- visibility: z.string().optional(),
194
- privateAccessHash: z.string().nullable().optional(),
195
- privateAccessVersion: z.number().optional(),
196
- themeConfig: StorefrontThemeConfigSchema.optional(),
197
- featuresEnabled: StorefrontFeaturesEnabledSchema.optional(),
198
- checkoutSettings: StorefrontCheckoutSettingsSchema.optional().nullable()
199
- }).passthrough();
200
- var StorefrontSettingsEnvelopeSchema = z.object({
201
- schemaVersion: z.number(),
202
- generatedAt: z.string(),
203
- store: StorefrontStoreSchema,
204
- cms: z.object({
205
- settings: StorefrontCmsSettingsSchema,
206
- pages: z.array(StorefrontCmsPageSchema)
207
- })
208
- }).passthrough();
209
- var StorefrontSettingsSchema = z.preprocess(
210
- normalizeStorefrontSettingsPayload,
211
- StorefrontSettingsEnvelopeSchema
212
- );
213
-
214
- export { StorefrontSettingsSchema, StorefrontStoreSchema };
215
- //# sourceMappingURL=chunk-64GLOWMJ.js.map
216
- //# sourceMappingURL=chunk-64GLOWMJ.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/models/store.ts"],"names":[],"mappings":"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","file":"chunk-64GLOWMJ.js","sourcesContent":["import { z } from \"zod\";\nimport { DEFAULT_CURRENCY_CODE } from \"../constants/currency\";\n\nexport const StorefrontCheckoutSettingsSchema = z.object({\n allowGuestCheckout: z.boolean().optional(),\n identityScope: z.enum([\"store\", \"tenant\", \"global\"]).optional(),\n signInMethods: z.array(z.string()).optional(),\n});\n\nexport type StorefrontCheckoutSettings = z.infer<\n typeof StorefrontCheckoutSettingsSchema\n>;\n\nconst looseRecord = z.record(z.string(), z.unknown());\n\nexport const StorefrontThemeConfigSchema = z\n .object({\n name: z.string().nullable().optional(),\n mode: z.string().nullable().optional(),\n colors: looseRecord.optional(),\n fonts: looseRecord.optional(),\n assets: looseRecord.optional(),\n })\n .passthrough();\n\nexport const StorefrontFeaturesEnabledSchema = z\n .object({\n flags: looseRecord.optional(),\n })\n .passthrough();\n\nexport const StorefrontCmsBrandingSchema = z.object({\n logoUrl: z.string().nullable().optional(),\n logoDarkUrl: z.string().nullable().optional(),\n faviconUrl: z.string().nullable().optional(),\n socialImageUrl: z.string().nullable().optional(),\n});\n\nexport const StorefrontCmsSeoSchema = z.object({\n siteName: z.string().nullable().optional(),\n metaTitle: z.string().nullable().optional(),\n metaDescription: z.string().nullable().optional(),\n titleTemplate: z.string().nullable().optional(),\n robotsIndex: z.boolean().optional(),\n});\n\nexport const StorefrontCmsSocialLinksSchema = z.object({\n instagram: z.string().nullable().optional(),\n facebook: z.string().nullable().optional(),\n tiktok: z.string().nullable().optional(),\n youtube: z.string().nullable().optional(),\n x: z.string().nullable().optional(),\n});\n\nexport const StorefrontCmsContactSchema = z.object({\n supportEmail: z.string().nullable().optional(),\n phone: z.string().nullable().optional(),\n whatsapp: z.string().nullable().optional(),\n address: z.string().nullable().optional(),\n socialLinks: StorefrontCmsSocialLinksSchema.optional(),\n});\n\nexport const StorefrontCmsTrackingSchema = z.object({\n googleAnalyticsMeasurementId: z.string().nullable().optional(),\n metaPixelId: z.string().nullable().optional(),\n googleTagManagerContainerId: z.string().nullable().optional(),\n});\n\nexport const StorefrontCmsCustomScriptsSchema = z.object({\n enabled: z.boolean().optional(),\n head: z.string().nullable().optional(),\n bodyEnd: z.string().nullable().optional(),\n});\n\nexport const StorefrontCmsChannelsSchema = z.object({\n storefront: z\n .object({\n enabled: z.boolean().optional(),\n })\n .optional(),\n pos: z\n .object({\n enabled: z.boolean().optional(),\n })\n .optional(),\n});\n\nexport const StorefrontCmsSettingsSchema = z.object({\n themeKey: z.string().optional(),\n channels: StorefrontCmsChannelsSchema.optional(),\n branding: StorefrontCmsBrandingSchema.optional(),\n seo: StorefrontCmsSeoSchema.optional(),\n contact: StorefrontCmsContactSchema.optional(),\n tracking: StorefrontCmsTrackingSchema.optional(),\n customScripts: StorefrontCmsCustomScriptsSchema.optional(),\n updatedOn: z.string().nullable().optional(),\n});\n\nexport const StorefrontCmsPageSchema = z\n .object({\n id: z.string(),\n name: z.string(),\n slug: z.string(),\n channel: z\n .string()\n .transform((value) => value.toLowerCase())\n .pipe(z.enum([\"storefront\", \"pos\"]))\n .default(\"storefront\"),\n layout: z.string().optional(),\n version: z.number().optional(),\n settings: z.record(z.string(), z.unknown()).optional().nullable(),\n sections: z.array(z.unknown()).optional(),\n status: z.string().optional(),\n hasPublishedVersion: z.boolean().optional(),\n publishedOn: z.string().nullable().optional(),\n publishedBy: z.string().nullable().optional(),\n createdOn: z.string().nullable().optional(),\n updatedOn: z.string().nullable().optional(),\n createdBy: z.string().nullable().optional(),\n updatedBy: z.string().nullable().optional(),\n lastModifiedBy: z.string().nullable().optional(),\n })\n .passthrough();\n\n/** Respuesta antigua GET /settings (objeto plano sin `store` / `cms`). */\nexport const StorefrontSettingsLegacyFlatSchema = z\n .object({\n id: z.coerce.string(),\n tenantId: z.string().nullable().optional(),\n name: z.string(),\n slug: z.coerce.string().optional(),\n description: z.string().nullable().optional(),\n visibility: z.string().nullable().optional(),\n logo: z.string().nullable().optional(),\n favicon: z.string().nullable().optional(),\n icon: z.string().nullable().optional(),\n currency: z.string().nullable().optional(),\n language: z.string().nullable().optional(),\n themeConfig: z.unknown().optional().nullable(),\n featuresEnabled: z.unknown().optional().nullable(),\n checkoutSettings: StorefrontCheckoutSettingsSchema.optional().nullable(),\n })\n .passthrough();\n\nexport type StorefrontSettingsLegacyFlat = z.infer<\n typeof StorefrontSettingsLegacyFlatSchema\n>;\n\nfunction unwrapSettingsResponseBody(v: unknown): unknown {\n if (!v || typeof v !== \"object\" || Array.isArray(v)) return v;\n const o = v as Record<string, unknown>;\n if (\n \"data\" in o &&\n o.data != null &&\n typeof o.data === \"object\" &&\n !Array.isArray(o.data)\n ) {\n return o.data;\n }\n return v;\n}\n\nfunction isLegacyFlatSettingsPayload(v: unknown): v is Record<string, unknown> {\n if (!v || typeof v !== \"object\" || Array.isArray(v)) return false;\n const o = v as Record<string, unknown>;\n if (\"store\" in o || \"schemaVersion\" in o || \"cms\" in o) return false;\n return (\n (typeof o.id === \"string\" || typeof o.id === \"number\") &&\n typeof o.name === \"string\"\n );\n}\n\n/** Convierte el JSON plano legacy al sobre actual (misma forma que el API nuevo). */\nexport function normalizeStorefrontSettingsPayload(v: unknown): unknown {\n const body = unwrapSettingsResponseBody(v);\n if (!isLegacyFlatSettingsPayload(body)) return body;\n const raw = body;\n const parsed = StorefrontSettingsLegacyFlatSchema.safeParse(raw);\n if (!parsed.success) return body;\n\n const l = parsed.data;\n const currency = l.currency?.trim() ? l.currency : DEFAULT_CURRENCY_CODE;\n const language = l.language?.trim() ? l.language : \"es\";\n const slug = l.slug?.trim() ? l.slug : l.id;\n\n return {\n schemaVersion: 0,\n generatedAt: new Date(0).toISOString(),\n store: {\n id: l.id,\n tenantId: l.tenantId ?? undefined,\n name: l.name,\n slug,\n description: l.description ?? null,\n logo: l.logo ?? null,\n icon: l.icon ?? null,\n visibility: l.visibility ?? undefined,\n currency,\n language,\n themeConfig: l.themeConfig ?? undefined,\n featuresEnabled: l.featuresEnabled ?? undefined,\n checkoutSettings: l.checkoutSettings ?? undefined,\n },\n cms: {\n settings: {\n branding: {\n faviconUrl: l.favicon ?? null,\n logoUrl: l.logo ?? null,\n logoDarkUrl: null,\n socialImageUrl: null,\n },\n },\n pages: [],\n },\n };\n}\n\nexport const StorefrontStoreSchema = z\n .object({\n id: z.string(),\n tenantId: z.string().optional(),\n sellerId: z.string().optional(),\n plan: z.string().optional(),\n storageLimitBytes: z.number().optional(),\n monthlyTransferLimitBytes: z.number().optional(),\n maxUploadSizeBytes: z.number().optional(),\n maxStores: z.number().optional(),\n maxMembers: z.number().optional(),\n maxProducts: z.number().optional(),\n maxCategories: z.number().optional(),\n maxBrands: z.number().optional(),\n maxAttributes: z.number().optional(),\n maxCollections: z.number().optional(),\n enableApi: z.boolean().optional(),\n isActive: z.boolean().optional(),\n name: z.string(),\n description: z.string().nullable().optional(),\n avatarUrl: z.string().nullable().optional(),\n logo: z.string().nullable().optional(),\n icon: z.string().nullable().optional(),\n slug: z.string(),\n domain: z.string().nullable().optional(),\n domains: z.array(z.string()).optional(),\n timeZone: z.string().nullable().optional(),\n currency: z.string(),\n language: z.string(),\n visibility: z.string().optional(),\n privateAccessHash: z.string().nullable().optional(),\n privateAccessVersion: z.number().optional(),\n themeConfig: StorefrontThemeConfigSchema.optional(),\n featuresEnabled: StorefrontFeaturesEnabledSchema.optional(),\n checkoutSettings: StorefrontCheckoutSettingsSchema.optional().nullable(),\n })\n .passthrough();\n\nconst StorefrontSettingsEnvelopeSchema = z\n .object({\n schemaVersion: z.number(),\n generatedAt: z.string(),\n store: StorefrontStoreSchema,\n cms: z.object({\n settings: StorefrontCmsSettingsSchema,\n pages: z.array(StorefrontCmsPageSchema),\n }),\n })\n .passthrough();\n\n/** Acepta sobre nuevo o JSON plano legacy; siempre valida contra el sobre normalizado. */\nexport const StorefrontSettingsSchema = z.preprocess(\n normalizeStorefrontSettingsPayload,\n StorefrontSettingsEnvelopeSchema,\n);\n\nexport type StorefrontSettings = z.infer<typeof StorefrontSettingsSchema>;\nexport type StorefrontStore = z.infer<typeof StorefrontStoreSchema>;\nexport type StorefrontCmsSettings = z.infer<typeof StorefrontCmsSettingsSchema>;\nexport type StorefrontCmsPage = z.infer<typeof StorefrontCmsPageSchema>;\n\n/** Nodo `store` del payload público (cookies, auth, moneda). */\nexport function storefrontStoreRecord(\n settings: StorefrontSettings | null | undefined,\n): StorefrontStore | null {\n return settings?.store ?? null;\n}\n\n/** Favicon: CMS branding, luego logo/icono de tienda. */\nexport function storefrontFaviconUrl(\n settings: StorefrontSettings | null | undefined,\n): string | null {\n const b = settings?.cms?.settings?.branding;\n return (\n b?.faviconUrl ?? settings?.store?.logo ?? settings?.store?.icon ?? null\n );\n}\n\n/** Imagen social / OG: branding, luego logo de tienda. */\nexport function storefrontOgImageUrl(\n settings: StorefrontSettings | null | undefined,\n): string | null {\n const b = settings?.cms?.settings?.branding;\n return b?.socialImageUrl ?? settings?.store?.logo ?? null;\n}\n"]}
@@ -1,177 +0,0 @@
1
- import { STOREFRONT_API_PATH_PREFIX } from './chunk-S7CPZ4UE.js';
2
- import { STOREFRONT_HEADERS } from './chunk-Q4U5OEUT.js';
3
-
4
- // src/core/constants/storefront-ecomiq-oauth-cookie.ts
5
- var STOREFRONT_ECOMIQ_OAUTH_COOKIE_NAME = "ecomiq_sf_oauth_at";
6
- var STOREFRONT_ECOMIQ_OAUTH_COOKIE_PATH = "/api/store";
7
-
8
- // src/core/server/store-proxy-handler.ts
9
- var DEFAULT_API_BASE_URL = "https://storefront.ecomiq.pe";
10
- function jsonError(status, message, error) {
11
- return Response.json({ error, message, status }, { status });
12
- }
13
- async function readStoreContext(request) {
14
- const xStoreId = request.headers.get(STOREFRONT_HEADERS.storeIdLower)?.trim();
15
- const xStoreDomain = request.headers.get(STOREFRONT_HEADERS.storeDomainLower)?.trim();
16
- if (xStoreDomain) {
17
- return {
18
- ok: true,
19
- storeId: xStoreId || "",
20
- storeDomain: xStoreDomain || null
21
- };
22
- }
23
- if (!xStoreId) {
24
- return {
25
- ok: false,
26
- response: jsonError(
27
- 400,
28
- `${STOREFRONT_HEADERS.storeId} is required`,
29
- "Store context required"
30
- )
31
- };
32
- }
33
- return {
34
- ok: true,
35
- storeId: xStoreId || "",
36
- storeDomain: xStoreDomain || null
37
- };
38
- }
39
- var SKIP_FORWARD_HEADERS = /* @__PURE__ */ new Set([
40
- "host",
41
- "connection",
42
- "content-length",
43
- "transfer-encoding",
44
- STOREFRONT_HEADERS.storeIdLower,
45
- STOREFRONT_HEADERS.storeDomainLower,
46
- "authorization",
47
- "cookie",
48
- "cookie2",
49
- "set-cookie",
50
- "x-forwarded-for",
51
- "x-forwarded-proto",
52
- "x-forwarded-host",
53
- "x-real-ip",
54
- "forwarded",
55
- "cf-connecting-ip",
56
- "cf-connecting-ipv6",
57
- "true-client-ip",
58
- "cf-ipcountry",
59
- "cf-ray",
60
- "cf-visitor"
61
- ]);
62
- function getClientIp(request) {
63
- const candidates = [
64
- request.headers.get("cf-connecting-ip"),
65
- request.headers.get("true-client-ip"),
66
- request.headers.get("x-real-ip")
67
- ];
68
- for (const value of candidates) {
69
- const trimmed = value?.trim();
70
- if (trimmed) return trimmed;
71
- }
72
- const xff = request.headers.get("x-forwarded-for");
73
- if (xff?.trim()) {
74
- const first = xff.split(",")[0]?.trim();
75
- if (first) return first;
76
- }
77
- return null;
78
- }
79
- function getCookieValue(request, name) {
80
- const cookieHeader = request.headers.get("cookie");
81
- if (!cookieHeader) return void 0;
82
- for (const part of cookieHeader.split(";")) {
83
- const [rawKey, ...rest] = part.trim().split("=");
84
- if (rawKey?.trim() === name) {
85
- return decodeURIComponent(rest.join("="));
86
- }
87
- }
88
- return void 0;
89
- }
90
- function buildUpstreamRequest(request, pathSegments, config, storeId, storeDomain) {
91
- const requestUrl = new URL(request.url);
92
- const base = (config.apiBaseUrl ?? DEFAULT_API_BASE_URL).replace(/\/$/, "");
93
- const userPath = pathSegments.length ? pathSegments.join("/") : "";
94
- const path = userPath ? `${STOREFRONT_API_PATH_PREFIX}/${userPath}` : STOREFRONT_API_PATH_PREFIX;
95
- const search = requestUrl.searchParams.toString();
96
- const url = search ? `${base}/${path}?${search}` : `${base}/${path}`;
97
- const headers = new Headers();
98
- request.headers.forEach((value, key) => {
99
- const lower = key.toLowerCase();
100
- if (!SKIP_FORWARD_HEADERS.has(lower)) {
101
- headers.set(key, value);
102
- }
103
- });
104
- headers.set(STOREFRONT_HEADERS.storeId, storeId);
105
- if (storeDomain) {
106
- headers.set(STOREFRONT_HEADERS.storeDomain, storeDomain);
107
- }
108
- const clientIp = getClientIp(request);
109
- if (clientIp) {
110
- headers.set("X-Forwarded-For", clientIp);
111
- }
112
- const forwardedProto = request.headers.get("cf-visitor")?.match(/"scheme":"(https?)"/)?.[1] ?? requestUrl.protocol.replace(":", "") ?? "https";
113
- headers.set("X-Forwarded-Proto", forwardedProto);
114
- const forwardedHost = request.headers.get("host") ?? requestUrl.host;
115
- if (forwardedHost) {
116
- headers.set("X-Forwarded-Host", forwardedHost);
117
- }
118
- const incomingAuth = request.headers.get("authorization")?.trim();
119
- const storefrontOAuth = getCookieValue(request, STOREFRONT_ECOMIQ_OAUTH_COOKIE_NAME)?.trim();
120
- if (incomingAuth && /^Bearer\s+\S+/i.test(incomingAuth)) {
121
- headers.set("Authorization", incomingAuth);
122
- } else if (storefrontOAuth) {
123
- headers.set("Authorization", `Bearer ${storefrontOAuth}`);
124
- }
125
- const init = {
126
- method: request.method,
127
- headers,
128
- cache: "no-store"
129
- };
130
- const bodyMethods = ["POST", "PUT", "PATCH"];
131
- if (bodyMethods.includes(request.method) && request.body) {
132
- init.body = request.body;
133
- init.duplex = "half";
134
- }
135
- return { url, init };
136
- }
137
- function isResponseBodyForbidden(status) {
138
- return status === 204 || status === 205 || status === 304;
139
- }
140
- async function handleStoreProxyRequest(request, pathSegments, config = {}) {
141
- const storeContext = await readStoreContext(request);
142
- if (!storeContext.ok) {
143
- return storeContext.response;
144
- }
145
- const { storeId, storeDomain } = storeContext;
146
- const { url, init } = buildUpstreamRequest(
147
- request,
148
- pathSegments,
149
- config,
150
- storeId,
151
- storeDomain
152
- );
153
- const upstream = await fetch(url, init);
154
- const responseHeaders = new Headers(upstream.headers);
155
- responseHeaders.delete("content-encoding");
156
- responseHeaders.delete("content-length");
157
- const status = upstream.status;
158
- if (isResponseBodyForbidden(status)) {
159
- responseHeaders.delete("content-length");
160
- responseHeaders.delete("content-type");
161
- return new Response(null, {
162
- status,
163
- statusText: upstream.statusText,
164
- headers: responseHeaders
165
- });
166
- }
167
- const body = await upstream.text();
168
- return new Response(body, {
169
- status,
170
- statusText: upstream.statusText,
171
- headers: responseHeaders
172
- });
173
- }
174
-
175
- export { STOREFRONT_ECOMIQ_OAUTH_COOKIE_NAME, STOREFRONT_ECOMIQ_OAUTH_COOKIE_PATH, handleStoreProxyRequest };
176
- //# sourceMappingURL=chunk-AKD5IDEB.js.map
177
- //# sourceMappingURL=chunk-AKD5IDEB.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/constants/storefront-ecomiq-oauth-cookie.ts","../src/core/server/store-proxy-handler.ts"],"names":[],"mappings":"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","file":"chunk-AKD5IDEB.js","sourcesContent":["/** 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_HEADERS } from \"../constants/currency\";\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 readStoreContext(request: Request): Promise<StoreContextResult> {\n const xStoreId = request.headers.get(STOREFRONT_HEADERS.storeIdLower)?.trim();\n const xStoreDomain = request.headers.get(STOREFRONT_HEADERS.storeDomainLower)?.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 `${STOREFRONT_HEADERS.storeId} 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 STOREFRONT_HEADERS.storeIdLower,\n STOREFRONT_HEADERS.storeDomainLower,\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(STOREFRONT_HEADERS.storeId, storeId);\n if (storeDomain) {\n headers.set(STOREFRONT_HEADERS.storeDomain, 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\n const init: RequestInit & { duplex?: \"half\" } = {\n method: request.method,\n headers,\n cache: \"no-store\",\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 readStoreContext(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 // El runtime descomprime el body (lo leemos como texto), pero `upstream.headers`\n // conserva content-encoding/content-length del payload comprimido: hay que\n // quitarlos o el cliente recibiría headers inconsistentes con el body.\n responseHeaders.delete(\"content-encoding\");\n responseHeaders.delete(\"content-length\");\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"]}