@ecomiq/storefront 2.0.2 → 2.0.5
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 +10 -0
- package/bin/ecomiq.mjs +18 -5
- package/package.json +1 -1
- package/src/config.d.ts +2 -0
- package/src/config.mjs +6 -0
- package/src/vite-inline.mjs +68 -43
package/README.md
CHANGED
|
@@ -54,4 +54,14 @@ npx ecomiq clean
|
|
|
54
54
|
npx ecomiq dev
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
### Runtime de desarrollo
|
|
58
|
+
|
|
59
|
+
`ecomiq dev` usa **Node** por defecto. Para emular Workers en local:
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
dev: { port: 3000, runtime: 'workerd' },
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`ecomiq build` / `deploy` siempre empaquetan para Cloudflare Workers.
|
|
66
|
+
|
|
57
67
|
Ver el monorepo [ecomiq-storefront](https://github.com/ecomiq/ecomiq-storefront) para la app de referencia y más documentación.
|
package/bin/ecomiq.mjs
CHANGED
|
@@ -16,7 +16,7 @@ import { resolve, dirname } from 'node:path'
|
|
|
16
16
|
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
17
17
|
import { generateApp, watchPages } from '../src/codegen.mjs'
|
|
18
18
|
import { parseConfig } from '../src/config.mjs'
|
|
19
|
-
import { createViteConfig } from '../src/vite-inline.mjs'
|
|
19
|
+
import { createViteConfig, resolveDevRuntime } from '../src/vite-inline.mjs'
|
|
20
20
|
|
|
21
21
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
22
22
|
const cwd = process.cwd()
|
|
@@ -80,9 +80,18 @@ export async function runCli(command = process.argv[2] ?? 'help') {
|
|
|
80
80
|
case 'dev': {
|
|
81
81
|
const config = await prepare()
|
|
82
82
|
const port = config.dev?.port ?? 3000
|
|
83
|
-
|
|
83
|
+
const runtime = resolveDevRuntime({ config })
|
|
84
84
|
const { createServer } = await import('vite')
|
|
85
|
-
const viteConfig = createViteConfig({
|
|
85
|
+
const viteConfig = createViteConfig({
|
|
86
|
+
appDir,
|
|
87
|
+
config,
|
|
88
|
+
projectRoot: cwd,
|
|
89
|
+
runtime,
|
|
90
|
+
})
|
|
91
|
+
banner(
|
|
92
|
+
`dev · ${config.name ?? 'tienda'} ${c.dim('http://localhost:' + port)}` +
|
|
93
|
+
(runtime === 'workerd' ? c.dim(' · runtime workerd') : ''),
|
|
94
|
+
)
|
|
86
95
|
const server = await createServer({
|
|
87
96
|
...viteConfig,
|
|
88
97
|
server: {
|
|
@@ -115,7 +124,9 @@ export async function runCli(command = process.argv[2] ?? 'help') {
|
|
|
115
124
|
const config = await prepare()
|
|
116
125
|
banner(`build · Cloudflare Workers`)
|
|
117
126
|
const { createBuilder } = await import('vite')
|
|
118
|
-
const builder = await createBuilder(
|
|
127
|
+
const builder = await createBuilder(
|
|
128
|
+
createViteConfig({ appDir, config, projectRoot: cwd, runtime: 'workerd' }),
|
|
129
|
+
)
|
|
119
130
|
await builder.buildApp()
|
|
120
131
|
console.log(c.green('\n ✔ Build listo en .ecomiq/dist\n'))
|
|
121
132
|
break
|
|
@@ -124,7 +135,9 @@ export async function runCli(command = process.argv[2] ?? 'help') {
|
|
|
124
135
|
const config = await prepare()
|
|
125
136
|
banner(`deploy · Cloudflare Workers`)
|
|
126
137
|
const { createBuilder } = await import('vite')
|
|
127
|
-
const builder = await createBuilder(
|
|
138
|
+
const builder = await createBuilder(
|
|
139
|
+
createViteConfig({ appDir, config, projectRoot: cwd, runtime: 'workerd' }),
|
|
140
|
+
)
|
|
128
141
|
await builder.buildApp()
|
|
129
142
|
// @cloudflare/vite-plugin emite la config final del Worker junto al build
|
|
130
143
|
const built = resolve(appDir, 'dist', 'server', 'wrangler.json')
|
package/package.json
CHANGED
package/src/config.d.ts
CHANGED
package/src/config.mjs
CHANGED
|
@@ -124,6 +124,12 @@ const configSchema = z.object({
|
|
|
124
124
|
.object({
|
|
125
125
|
port: z.number().int().default(3000),
|
|
126
126
|
apiBaseUrl: z.string().url(),
|
|
127
|
+
/**
|
|
128
|
+
* Runtime SSR en `ecomiq dev`. Default: `node`.
|
|
129
|
+
* Usa `workerd` para emular Cloudflare Workers en local.
|
|
130
|
+
* `ecomiq build` / `deploy` siempre usan workerd.
|
|
131
|
+
*/
|
|
132
|
+
runtime: z.enum(['workerd', 'node']),
|
|
127
133
|
})
|
|
128
134
|
.partial()
|
|
129
135
|
.optional(),
|
package/src/vite-inline.mjs
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
* No existe vite.config.ts en el proyecto del usuario ni en .ecomiq:
|
|
4
4
|
* los plugins se importan aquí (contexto del framework) y se pasan como
|
|
5
5
|
* instancias, así la resolución de módulos nunca depende del proyecto.
|
|
6
|
+
*
|
|
7
|
+
* Alineado con el ejemplo oficial TanStack Start + Cloudflare:
|
|
8
|
+
* https://github.com/TanStack/router/tree/main/examples/react/start-basic-cloudflare
|
|
6
9
|
*/
|
|
7
10
|
import { dirname, resolve } from 'node:path'
|
|
8
11
|
import { fileURLToPath } from 'node:url'
|
|
@@ -52,7 +55,39 @@ function sanitizeHtmlClientBoundary() {
|
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
57
|
|
|
55
|
-
|
|
58
|
+
/**
|
|
59
|
+
* TanStack Start marca `@tanstack/react-router` como `resolve.external` fuera de
|
|
60
|
+
* su monorepo. Cloudflare Vite plugin no lo tolera y workerd acaba ejecutando
|
|
61
|
+
* CJS con `require` → "require is not defined".
|
|
62
|
+
* @see https://github.com/TanStack/router/issues/5291
|
|
63
|
+
*/
|
|
64
|
+
function clearSsrExternal() {
|
|
65
|
+
return {
|
|
66
|
+
name: 'ecomiq:clear-ssr-external',
|
|
67
|
+
configResolved(config) {
|
|
68
|
+
const ssr = config.environments?.ssr
|
|
69
|
+
if (ssr?.resolve) {
|
|
70
|
+
ssr.resolve.external = []
|
|
71
|
+
ssr.resolve.noExternal = true
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @param {{ appDir: string, config?: object, projectRoot?: string, runtime?: 'workerd' | 'node' }} opts
|
|
79
|
+
*/
|
|
80
|
+
export function resolveDevRuntime({ config, runtime } = {}) {
|
|
81
|
+
// Default: Node (compatible con npm/CodeSandbox). Opt-in a workerd con
|
|
82
|
+
// `dev.runtime: 'workerd'` (p. ej. monorepo local). build/deploy siempre
|
|
83
|
+
// fuerza workerd desde la CLI.
|
|
84
|
+
return runtime ?? config?.dev?.runtime ?? 'node'
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @param {{ appDir: string, config?: object, projectRoot?: string, runtime?: 'workerd' | 'node' }} opts
|
|
89
|
+
*/
|
|
90
|
+
export function createViteConfig({ appDir, config, projectRoot, runtime }) {
|
|
56
91
|
const root = projectRoot ?? resolve(appDir, '..')
|
|
57
92
|
const allow = [
|
|
58
93
|
'..',
|
|
@@ -62,6 +97,36 @@ export function createViteConfig({ appDir, config, projectRoot }) {
|
|
|
62
97
|
resolve(root, 'node_modules'),
|
|
63
98
|
]
|
|
64
99
|
|
|
100
|
+
const resolvedRuntime = resolveDevRuntime({ config, runtime })
|
|
101
|
+
|
|
102
|
+
const plugins = [
|
|
103
|
+
clearSsrExternal(),
|
|
104
|
+
tailwindcss(),
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
// workerd emula Cloudflare Workers (opt-in en `ecomiq dev`).
|
|
108
|
+
// Default es Node; build/deploy siempre usan workerd.
|
|
109
|
+
if (resolvedRuntime === 'workerd') {
|
|
110
|
+
plugins.push(
|
|
111
|
+
cloudflare({
|
|
112
|
+
configPath: resolve(appDir, 'wrangler.jsonc'),
|
|
113
|
+
viteEnvironment: { name: 'ssr' },
|
|
114
|
+
}),
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
plugins.push(
|
|
119
|
+
tanstackStart({
|
|
120
|
+
srcDirectory: 'src',
|
|
121
|
+
router: {
|
|
122
|
+
routesDirectory: 'routes',
|
|
123
|
+
generatedRouteTree: 'routeTree.gen.ts',
|
|
124
|
+
},
|
|
125
|
+
}),
|
|
126
|
+
sanitizeHtmlClientBoundary(),
|
|
127
|
+
viteReact(),
|
|
128
|
+
)
|
|
129
|
+
|
|
65
130
|
return {
|
|
66
131
|
root: appDir,
|
|
67
132
|
configFile: false,
|
|
@@ -75,45 +140,8 @@ export function createViteConfig({ appDir, config, projectRoot }) {
|
|
|
75
140
|
'@tanstack/react-query',
|
|
76
141
|
],
|
|
77
142
|
},
|
|
78
|
-
|
|
79
|
-
ssr: {
|
|
80
|
-
noExternal: [
|
|
81
|
-
'@tanstack/react-start',
|
|
82
|
-
'@tanstack/react-router',
|
|
83
|
-
'@tanstack/react-query',
|
|
84
|
-
'@tanstack/router-core',
|
|
85
|
-
'@tanstack/history',
|
|
86
|
-
'@tanstack/react-store',
|
|
87
|
-
'@ecomiq/storefront',
|
|
88
|
-
'@ecomiq/core',
|
|
89
|
-
],
|
|
90
|
-
},
|
|
91
|
-
optimizeDeps: {
|
|
92
|
-
include: [
|
|
93
|
-
'@tanstack/react-start',
|
|
94
|
-
'@tanstack/react-router',
|
|
95
|
-
'@tanstack/react-query',
|
|
96
|
-
],
|
|
97
|
-
},
|
|
98
|
-
plugins: [
|
|
99
|
-
tailwindcss(),
|
|
100
|
-
// Emula el runtime de Workers en dev y empaqueta para Cloudflare en build.
|
|
101
|
-
cloudflare({
|
|
102
|
-
configPath: resolve(appDir, 'wrangler.jsonc'),
|
|
103
|
-
viteEnvironment: { name: 'ssr' },
|
|
104
|
-
}),
|
|
105
|
-
tanstackStart({
|
|
106
|
-
srcDirectory: 'src',
|
|
107
|
-
router: {
|
|
108
|
-
routesDirectory: 'routes',
|
|
109
|
-
generatedRouteTree: 'routeTree.gen.ts',
|
|
110
|
-
},
|
|
111
|
-
}),
|
|
112
|
-
sanitizeHtmlClientBoundary(),
|
|
113
|
-
viteReact(),
|
|
114
|
-
],
|
|
143
|
+
plugins,
|
|
115
144
|
build: {
|
|
116
|
-
// Un solo CSS; nombre estable → SSR y client apuntan al mismo asset en Workers.
|
|
117
145
|
cssCodeSplit: false,
|
|
118
146
|
rollupOptions: {
|
|
119
147
|
output: {
|
|
@@ -126,10 +154,7 @@ export function createViteConfig({ appDir, config, projectRoot }) {
|
|
|
126
154
|
},
|
|
127
155
|
},
|
|
128
156
|
server: {
|
|
129
|
-
fs: {
|
|
130
|
-
// pages/, lib/ y public/ del usuario viven un nivel arriba de .ecomiq
|
|
131
|
-
allow,
|
|
132
|
-
},
|
|
157
|
+
fs: { allow },
|
|
133
158
|
},
|
|
134
159
|
}
|
|
135
160
|
}
|