@ecomiq/storefront 2.1.3 → 2.1.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/README.md CHANGED
@@ -72,16 +72,14 @@ Ver el monorepo [ecomiq-storefront](https://github.com/ecomiq/ecomiq-storefront)
72
72
 
73
73
  ## Storefront declarativo
74
74
 
75
- `StorefrontDefinition v1` permite construir y versionar una tienda sin generar
76
- código React arbitrario. El contrato valida tema, navegación, footer y ocho
77
- tipos de sección: `hero`, `product-grid`, `collection-grid`, `promo-banner`,
78
- `image-text`, `rich-text`, `testimonials` y `newsletter`.
75
+ El contrato y el renderer viven fuera de este package:
76
+
77
+ - `@ecomiq/storefront-definition` — schema Zod, patches, migraciones
78
+ - `@ecomiq/storefront-definition/react` — `DefinitionRenderer`, loaders y hooks
79
79
 
80
80
  ```tsx
81
- import {
82
- StorefrontDefinitionRenderer,
83
- createDefaultStorefrontDefinition,
84
- } from '@ecomiq/storefront'
81
+ import { createDefaultStorefrontDefinition } from '@ecomiq/storefront-definition'
82
+ import { DefinitionRenderer } from '@ecomiq/storefront-definition/react'
85
83
 
86
84
  const definition = createDefaultStorefrontDefinition({
87
85
  storeName: 'Casa Lumbre',
@@ -90,7 +88,7 @@ const definition = createDefaultStorefrontDefinition({
90
88
 
91
89
  export function Home() {
92
90
  return (
93
- <StorefrontDefinitionRenderer
91
+ <DefinitionRenderer
94
92
  definition={definition}
95
93
  locale="es-PE"
96
94
  currency="PEN"
@@ -107,27 +105,9 @@ export function Home() {
107
105
  }
108
106
  ```
109
107
 
110
- Los sistemas que solo necesitan validar o modificar el contrato pueden importar
111
- el subpath sin cargar el renderer:
112
-
113
108
  ```ts
114
109
  import {
115
110
  StorefrontDefinitionSchema,
116
- StorefrontDefinitionPatchSchema,
117
111
  applyStorefrontDefinitionPatch,
118
- type StorefrontDefinitionInput,
119
- type StorefrontDefinitionPatchInput,
120
- } from '@ecomiq/storefront/definition'
112
+ } from '@ecomiq/storefront-definition'
121
113
  ```
122
-
123
- Cada definición lleva `version` y `revision`. Los patches son puros, exigen
124
- `expectedRevision` y conservan el ID de una sección al reemplazarla. Soportan
125
- `section.add`, `section.replace`, `section.remove`, `section.reorder`,
126
- `theme.replace`, `navigation.replace` y `footer.replace`.
127
-
128
- El template productivo consulta server-side
129
- `GET /v1/runtime/storefronts/:storeSlug`, revalida la publicación mediante
130
- ETag y resuelve los `product-grid.source` y `collection-grid.source` contra el
131
- API storefront. La publicación declarativa reemplaza solo el contenido de la
132
- home; el layout comercial y las rutas de catálogo, producto, carrito, checkout
133
- y cuenta siguen siendo las del framework.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ecomiq/storefront",
3
- "version": "2.1.3",
3
+ "version": "2.1.4",
4
4
  "description": "Micro framework SSR de Ecomiq para storefronts. Páginas, datos y deploy sin configurar nada.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -32,14 +32,10 @@
32
32
  "default": "./src/config.mjs"
33
33
  },
34
34
  "./ui": "./src/ui/index.ts",
35
- "./definition": "./src/storefront-definition/contract.ts",
36
- "./definition/react": "./src/storefront-definition/index.ts",
37
35
  "./styles.css": "./src/styles.css",
38
36
  "./internal/page": "./src/runtime/page.tsx",
39
37
  "./internal/context": "./src/runtime/context.ts",
40
38
  "./internal/server-config": "./src/server-config-store.ts",
41
- "./internal/runtime": "./src/storefront-runtime.ts",
42
- "./internal/definition-data": "./src/storefront-definition/data.ts",
43
39
  "./internal/health": "./src/health.ts",
44
40
  "./internal/head": "./src/runtime/head.ts",
45
41
  "./internal/default-layout": "./src/runtime/default-layout.tsx",
@@ -86,8 +82,7 @@
86
82
  "vite": "^8.1.0",
87
83
  "wrangler": "^4.100.0",
88
84
  "zod": "^3.25.0",
89
- "@ecomiq/core": "^0.1.9",
90
- "@ecomiq/storefront-definition": "^1.0.0"
85
+ "@ecomiq/core": "^0.1.9"
91
86
  },
92
87
  "peerDependencies": {
93
88
  "react": "^19.0.0",
package/src/codegen.mjs CHANGED
@@ -198,10 +198,22 @@ export async function generateApp({ cwd, appDir, frameworkRoot, config }) {
198
198
 
199
199
  // ── 5. styles.css: tokens del framework + fuentes de contenido del usuario ──
200
200
  const themeOverrides = buildThemeOverrides(config)
201
+ const projectPkgPath = resolve(cwd, 'package.json')
202
+ const projectPkg = existsSync(projectPkgPath)
203
+ ? JSON.parse(readFileSync(projectPkgPath, 'utf8'))
204
+ : {}
205
+ const hasStorefrontDefinition = Boolean(
206
+ projectPkg.dependencies?.['@ecomiq/storefront-definition'] ||
207
+ projectPkg.devDependencies?.['@ecomiq/storefront-definition'],
208
+ )
201
209
  writeGeneratedFile(
202
210
  join(srcDir, 'styles.css'),
203
211
  HEADER.replace('/*', '/*!') +
204
212
  `@import '@ecomiq/storefront/styles.css';\n` +
213
+ (hasStorefrontDefinition
214
+ ? `@import '@ecomiq/storefront-definition/react/styles.css';\n` +
215
+ `@source '../../../node_modules/@ecomiq/storefront-definition/src/react';\n`
216
+ : '') +
205
217
  `@source '../../pages';\n` +
206
218
  `@source '../../components';\n` +
207
219
  `@source '../../lib';\n` +
package/src/index.ts CHANGED
@@ -246,11 +246,6 @@ export {
246
246
  type HeroProps,
247
247
  type HeroSlide,
248
248
  } from './components/hero'
249
- export * from './storefront-definition'
250
- export {
251
- definitionForRoute,
252
- useDefinition,
253
- } from './storefront-layout'
254
249
  export { z } from 'zod'
255
250
 
256
251
  /**
@@ -1,12 +1,9 @@
1
1
  /**
2
- * Página de contenido (`/pages/$pageSlug`).
3
- * La Definition es la dueña de estas rutas; el CMS queda solo como fallback
4
- * de lectura para tiendas que aún no migraron sus páginas.
2
+ * Página de contenido CMS (`/pages/$pageSlug`).
3
+ * Las páginas Definition las sirve el template (`$.tsx`).
5
4
  */
6
5
  import type { CmsPageDetailsDto } from '@ecomiq/core'
7
- import type { ActiveStorefrontPage } from '../storefront-runtime'
8
6
  import {
9
- DefinitionSections,
10
7
  definePage,
11
8
  sanitizeHtml,
12
9
  serverApi,
@@ -24,51 +21,30 @@ const ContentPageSettingsSchema = z.object({
24
21
  }).optional(),
25
22
  }).passthrough()
26
23
 
27
- type ContentPageData =
28
- | Extract<ActiveStorefrontPage, { kind: 'definition' }>
29
- | {
30
- kind: 'cms'
31
- page: CmsPageDetailsDto
32
- content: z.infer<typeof ContentPageSettingsSchema>
33
- }
24
+ type ContentPageData = {
25
+ page: CmsPageDetailsDto
26
+ content: z.infer<typeof ContentPageSettingsSchema>
27
+ }
34
28
 
35
29
  export default definePage<ContentPageData, { pageSlug: string }>({
36
30
  loader: async ({ params }) => {
37
- const resolved = await serverApi.getActiveStorefrontPage(
38
- `/pages/${params.pageSlug}`,
39
- )
40
- if (resolved.kind === 'definition') return resolved
41
-
42
31
  const page = await serverApi.getPageBySlug(params.pageSlug)
43
32
  if (page.status !== 'published') throw new Error('Página no publicada')
44
33
 
45
34
  return {
46
- kind: 'cms' as const,
47
35
  page,
48
36
  content: ContentPageSettingsSchema.parse(page.settings ?? {}),
49
37
  }
50
38
  },
51
39
 
52
- meta: ({ data, settings }) => {
53
- if (data.kind === 'definition') {
54
- const { page } = data
55
- return {
56
- title: page.seo.title ?? page.title ?? settings?.store.name ?? '',
57
- ...(page.seo.description === undefined
58
- ? {}
59
- : { description: page.seo.description }),
60
- ...(page.seo.noindex ? { noIndex: true } : {}),
61
- }
62
- }
63
- return {
64
- title: data.content.seo?.title ?? data.content.title ?? data.page.name,
65
- description: data.content.seo?.description ?? (
66
- data.content.html
67
- ? stripHtml(data.content.html).slice(0, 155)
68
- : undefined
69
- ),
70
- }
71
- },
40
+ meta: ({ data }) => ({
41
+ title: data.content.seo?.title ?? data.content.title ?? data.page.name,
42
+ description: data.content.seo?.description ?? (
43
+ data.content.html
44
+ ? stripHtml(data.content.html).slice(0, 155)
45
+ : undefined
46
+ ),
47
+ }),
72
48
 
73
49
  error: () => (
74
50
  <StorefrontError
@@ -77,35 +53,22 @@ export default definePage<ContentPageData, { pageSlug: string }>({
77
53
  />
78
54
  ),
79
55
 
80
- component: ({ data, settings }) => {
81
- if (data.kind === 'definition') {
82
- return (
83
- <DefinitionSections
84
- definition={data.definition}
85
- pageId={data.page.id}
86
- data={data.data}
87
- locale={settings.store.language}
88
- currency={settings.store.currency}
89
- />
90
- )
91
- }
92
- return (
93
- <article className="mx-auto w-full max-w-4xl px-4 py-10 sm:py-14">
94
- <header className="mb-8 border-b pb-8">
95
- <h1 className="text-balance text-3xl font-semibold tracking-[-0.02em] md:text-4xl">
96
- {data.content.title ?? data.page.name}
97
- </h1>
98
- </header>
56
+ component: ({ data }) => (
57
+ <article className="mx-auto w-full max-w-4xl px-4 py-10 sm:py-14">
58
+ <header className="mb-8 border-b pb-8">
59
+ <h1 className="text-balance text-3xl font-semibold tracking-[-0.02em] md:text-4xl">
60
+ {data.content.title ?? data.page.name}
61
+ </h1>
62
+ </header>
99
63
 
100
- {data.content.html ? (
101
- <div
102
- className="prose prose-neutral max-w-none text-foreground prose-headings:font-semibold prose-a:text-primary"
103
- dangerouslySetInnerHTML={{ __html: sanitizeHtml(data.content.html) }}
104
- />
105
- ) : (
106
- <p className="text-muted-foreground">Contenido no disponible.</p>
107
- )}
108
- </article>
109
- )
110
- },
64
+ {data.content.html ? (
65
+ <div
66
+ className="prose prose-neutral max-w-none text-foreground prose-headings:font-semibold prose-a:text-primary"
67
+ dangerouslySetInnerHTML={{ __html: sanitizeHtml(data.content.html) }}
68
+ />
69
+ ) : (
70
+ <p className="text-muted-foreground">Contenido no disponible.</p>
71
+ )}
72
+ </article>
73
+ ),
111
74
  })
package/src/server.ts CHANGED
@@ -71,23 +71,11 @@ import {
71
71
  type AddProductToCartInput,
72
72
  } from './cart-session'
73
73
  import { submitProductReview } from './review-submission'
74
- import {
75
- loadActiveStorefrontHome,
76
- loadActiveStorefrontPage,
77
- } from './storefront-runtime'
78
74
 
79
75
  const getSettingsFn = createServerFn({ method: 'GET' }).handler(() =>
80
76
  getStorefrontClient().getSettings(),
81
77
  )
82
78
 
83
- const getActiveStorefrontHomeFn = createServerFn({ method: 'GET' }).handler(
84
- () => loadActiveStorefrontHome(),
85
- )
86
-
87
- const getActiveStorefrontPageFn = createServerFn({ method: 'GET' })
88
- .validator(z.object({ pathname: z.string().min(1).max(2_048) }))
89
- .handler(({ data }) => loadActiveStorefrontPage(data.pathname))
90
-
91
79
  const getStoreIdFn = createServerFn({ method: 'GET' }).handler(() =>
92
80
  getStorefrontClient().getStoreId(),
93
81
  )
@@ -234,9 +222,6 @@ const getDistrictsFn = createServerFn({ method: 'GET' })
234
222
  */
235
223
  export const serverApi = {
236
224
  getSettings: () => getSettingsFn(),
237
- getActiveStorefrontHome: () => getActiveStorefrontHomeFn(),
238
- getActiveStorefrontPage: (pathname: string) =>
239
- getActiveStorefrontPageFn({ data: { pathname } }),
240
225
  getStoreId: () => getStoreIdFn(),
241
226
  getCollections: () => getCollectionsFn(),
242
227
  getCollectionBySlug: (slug: string) => getCollectionBySlugFn({ data: { slug } }),
package/src/styles.css CHANGED
@@ -5,7 +5,6 @@
5
5
  /* Escanear los componentes UI del propio framework */
6
6
  @source './ui';
7
7
  @source './components';
8
- @source './storefront-definition';
9
8
  @source './runtime';
10
9
  @source './pages';
11
10
  @source '../templates';
@@ -75,23 +74,3 @@
75
74
  transition-duration: 0.01ms !important;
76
75
  }
77
76
  }
78
-
79
- .storefront-definition {
80
- font-family: var(--storefront-font-body);
81
- --storefront-content-width: 72rem;
82
- }
83
-
84
- .storefront-definition :where(h1, h2, h3, h4, h5, h6) {
85
- font-family: var(--storefront-font-heading);
86
- }
87
-
88
- .storefront-definition-section {
89
- padding-block: var(
90
- --storefront-section-padding-top,
91
- var(--storefront-section-padding)
92
- )
93
- var(
94
- --storefront-section-padding-bottom,
95
- var(--storefront-section-padding)
96
- );
97
- }