@decocms/start 2.4.2 → 2.5.0
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/.agents/skills/deco-to-tanstack-migration/SKILL.md +1 -0
- package/.agents/skills/deco-to-tanstack-migration/references/post-migration-cleanup.md +163 -0
- package/.agents/skills/deco-to-tanstack-migration/references/vite-config/README.md +27 -2
- package/.agents/skills/deco-to-tanstack-migration/templates/vite-config.md +143 -68
- package/.cursor/skills/deco-to-tanstack-migration/SKILL.md +1 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/post-migration-cleanup.md +163 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/vite-config/README.md +27 -2
- package/.cursor/skills/deco-to-tanstack-migration/templates/vite-config.md +143 -68
- package/package.json +1 -1
- package/scripts/deco-migrate-cli.ts +1 -1
- package/scripts/migrate/analyzers/island-classifier.ts +2 -2
- package/scripts/migrate/analyzers/loader-inventory.ts +2 -2
- package/scripts/migrate/analyzers/section-metadata.ts +2 -2
- package/scripts/migrate/analyzers/theme-extractor.ts +2 -2
- package/scripts/migrate/phase-analyze.ts +6 -6
- package/scripts/migrate/phase-cleanup.ts +31 -35
- package/scripts/migrate/phase-report.ts +2 -2
- package/scripts/migrate/phase-scaffold.ts +20 -20
- package/scripts/migrate/phase-transform.ts +9 -9
- package/scripts/migrate/phase-verify.ts +2 -2
- package/scripts/migrate/templates/app-css.ts +2 -2
- package/scripts/migrate/templates/cache-config.ts +1 -1
- package/scripts/migrate/templates/commerce-loaders.ts +1 -1
- package/scripts/migrate/templates/hooks.ts +1 -1
- package/scripts/migrate/templates/lib-utils.ts +1 -1
- package/scripts/migrate/templates/package-json.ts +1 -1
- package/scripts/migrate/templates/routes.ts +1 -1
- package/scripts/migrate/templates/sdk-gen.ts +1 -1
- package/scripts/migrate/templates/section-loaders.ts +1 -1
- package/scripts/migrate/templates/server-entry.ts +1 -1
- package/scripts/migrate/templates/setup.ts +1 -1
- package/scripts/migrate/templates/types-gen.ts +1 -1
- package/scripts/migrate/templates/ui-components.ts +1 -1
- package/scripts/migrate/templates/vite-config.ts +1 -1
- package/scripts/migrate/templates/wrangler.ts +1 -1
- package/scripts/migrate/transforms/dead-code.ts +1 -1
- package/scripts/migrate/transforms/deno-isms.ts +1 -1
- package/scripts/migrate/transforms/fresh-apis.ts +1 -1
- package/scripts/migrate/transforms/imports.ts +1 -1
- package/scripts/migrate/transforms/jsx.ts +1 -1
- package/scripts/migrate/transforms/section-conventions.ts +1 -1
- package/scripts/migrate/transforms/tailwind.ts +1 -1
- package/scripts/migrate.ts +8 -8
- package/src/cms/sectionLoaders.test.ts +4 -1
- package/src/vite/plugin.js +47 -10
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
# Vite Configuration
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
For the canonical battle-tested template (with VTEX dev proxy, CSP headers,
|
|
4
|
+
React Compiler, dedupe, framework plugin, and rollup chunk strategy) see
|
|
5
|
+
[`../../templates/vite-config.md`](../../templates/vite-config.md).
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
This page covers the post-migration **minimum viable config** if you've
|
|
8
|
+
stripped everything optional. Real sites should use the full template.
|
|
9
|
+
|
|
10
|
+
## Minimum Viable Config
|
|
6
11
|
|
|
7
12
|
```typescript
|
|
8
13
|
import { cloudflare } from "@cloudflare/vite-plugin";
|
|
9
14
|
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
|
|
15
|
+
import { decoVitePlugin } from "@decocms/start/vite";
|
|
10
16
|
import react from "@vitejs/plugin-react";
|
|
11
17
|
import tailwindcss from "@tailwindcss/vite";
|
|
12
18
|
import { defineConfig } from "vite";
|
|
@@ -24,8 +30,23 @@ export default defineConfig({
|
|
|
24
30
|
},
|
|
25
31
|
}),
|
|
26
32
|
tailwindcss(),
|
|
33
|
+
// Required — server-only stubs, blocks.gen.ts fast-path, meta.gen
|
|
34
|
+
// client stub, daemon/tunnel for dev mode. Without this, client
|
|
35
|
+
// bundle crashes on node:async_hooks / react-dom/server transitively
|
|
36
|
+
// imported by @decocms/start.
|
|
37
|
+
decoVitePlugin(),
|
|
27
38
|
],
|
|
28
39
|
resolve: {
|
|
40
|
+
// Required — dedupe React/TanStack/Deco packages so there's only one
|
|
41
|
+
// instance of each. Without this you get "Invalid hook call" errors.
|
|
42
|
+
dedupe: [
|
|
43
|
+
"@decocms/start",
|
|
44
|
+
"@decocms/apps",
|
|
45
|
+
"@tanstack/react-start",
|
|
46
|
+
"@tanstack/react-router",
|
|
47
|
+
"react",
|
|
48
|
+
"react-dom",
|
|
49
|
+
],
|
|
29
50
|
alias: {
|
|
30
51
|
"~": srcDir,
|
|
31
52
|
},
|
|
@@ -35,6 +56,10 @@ export default defineConfig({
|
|
|
35
56
|
|
|
36
57
|
**One alias only**: `~` -> `src/`. Nothing else.
|
|
37
58
|
|
|
59
|
+
The `decoVitePlugin()` call is **mandatory** — the older skill examples
|
|
60
|
+
that omitted it (or inlined the stub logic) reflect the pre-2.x state of
|
|
61
|
+
`@decocms/start` and will produce build/runtime failures on current versions.
|
|
62
|
+
|
|
38
63
|
## tsconfig.json
|
|
39
64
|
|
|
40
65
|
Must mirror the Vite alias:
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
# vite.config.ts Template
|
|
2
2
|
|
|
3
|
-
Battle-tested configuration
|
|
3
|
+
Battle-tested configuration. Uses the framework's `decoVitePlugin()` for the
|
|
4
|
+
server-only stub layer (rather than re-implementing it inline like older
|
|
5
|
+
sites did).
|
|
4
6
|
|
|
5
7
|
```typescript
|
|
6
8
|
import { cloudflare } from "@cloudflare/vite-plugin";
|
|
7
9
|
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
|
|
10
|
+
import { decoVitePlugin } from "@decocms/start/vite";
|
|
8
11
|
import react from "@vitejs/plugin-react";
|
|
9
12
|
import tailwindcss from "@tailwindcss/vite";
|
|
10
13
|
import { defineConfig } from "vite";
|
|
@@ -12,90 +15,86 @@ import path from "path";
|
|
|
12
15
|
|
|
13
16
|
const srcDir = path.resolve(__dirname, "src");
|
|
14
17
|
|
|
18
|
+
// VTEX dev proxy — adjust to your account / commerce backend.
|
|
19
|
+
const VTEX_ACCOUNT = process.env.VTEX_ACCOUNT || "mystore";
|
|
20
|
+
const VTEX_ORIGIN = `https://${VTEX_ACCOUNT}.vtexcommercestable.com.br`;
|
|
21
|
+
|
|
15
22
|
export default defineConfig({
|
|
23
|
+
server: {
|
|
24
|
+
port: parseInt(process.env.PORT ?? "5173", 10),
|
|
25
|
+
// When the deco daemon injects PORT, bind to all interfaces so Deno's
|
|
26
|
+
// TCP connect (127.0.0.1) can reach Vite regardless of IPv4/IPv6.
|
|
27
|
+
host: process.env.PORT ? "0.0.0.0" : undefined,
|
|
28
|
+
headers: {
|
|
29
|
+
// Allow embedding in iframes from trusted admin origins.
|
|
30
|
+
"Content-Security-Policy":
|
|
31
|
+
"frame-ancestors 'self' https://*.deco.studio http://localhost:* https://localhost:* https://admin.deco.cx https://studio.decocms.com",
|
|
32
|
+
},
|
|
33
|
+
proxy: {
|
|
34
|
+
"/api/": {
|
|
35
|
+
target: VTEX_ORIGIN,
|
|
36
|
+
changeOrigin: true,
|
|
37
|
+
cookieDomainRewrite: { "*": "" },
|
|
38
|
+
},
|
|
39
|
+
"/checkout": {
|
|
40
|
+
target: VTEX_ORIGIN,
|
|
41
|
+
changeOrigin: true,
|
|
42
|
+
cookieDomainRewrite: { "*": "" },
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
16
46
|
plugins: [
|
|
17
47
|
cloudflare({ viteEnvironment: { name: "ssr" } }),
|
|
18
48
|
tanstackStart({ server: { entry: "server" } }),
|
|
19
49
|
react({
|
|
20
50
|
babel: {
|
|
21
|
-
plugins: [
|
|
22
|
-
["babel-plugin-react-compiler", { target: "19" }],
|
|
23
|
-
],
|
|
51
|
+
plugins: [["babel-plugin-react-compiler", { target: "19" }]],
|
|
24
52
|
},
|
|
25
53
|
}),
|
|
26
54
|
tailwindcss(),
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
env.optimizeDeps.esbuildOptions = env.optimizeDeps.esbuildOptions || {};
|
|
48
|
-
env.optimizeDeps.esbuildOptions.jsx = "automatic";
|
|
49
|
-
env.optimizeDeps.esbuildOptions.jsxImportSource = "react";
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
load(id) {
|
|
53
|
-
if (id === "\0stub:react-dom-server") {
|
|
54
|
-
return [
|
|
55
|
-
"const noop = () => '';",
|
|
56
|
-
"export const renderToString = noop;",
|
|
57
|
-
"export const renderToStaticMarkup = noop;",
|
|
58
|
-
"export const renderToReadableStream = noop;",
|
|
59
|
-
"export const resume = noop;",
|
|
60
|
-
"export const version = '19.0.0';",
|
|
61
|
-
"export default { renderToString: noop, renderToStaticMarkup: noop, renderToReadableStream: noop, resume: noop, version: '19.0.0' };",
|
|
62
|
-
].join("\n");
|
|
63
|
-
}
|
|
64
|
-
if (id === "\0stub:node-stream") {
|
|
65
|
-
return "export class PassThrough {}; export class Readable {}; export class Writable {}; export default { PassThrough, Readable, Writable };";
|
|
66
|
-
}
|
|
67
|
-
if (id === "\0stub:node-stream-web") {
|
|
68
|
-
return "export const ReadableStream = globalThis.ReadableStream; export const WritableStream = globalThis.WritableStream; export const TransformStream = globalThis.TransformStream; export default { ReadableStream, WritableStream, TransformStream };";
|
|
69
|
-
}
|
|
70
|
-
if (id === "\0stub:node-async-hooks") {
|
|
71
|
-
return [
|
|
72
|
-
"class _ALS { getStore() { return undefined; } run(_store, fn, ...args) { return fn(...args); } enterWith() {} disable() {} }",
|
|
73
|
-
"export const AsyncLocalStorage = _ALS;",
|
|
74
|
-
"export const AsyncResource = class {};",
|
|
75
|
-
"export function executionAsyncId() { return 0; }",
|
|
76
|
-
"export function createHook() { return { enable() {}, disable() {} }; }",
|
|
77
|
-
"export default { AsyncLocalStorage: _ALS, AsyncResource, executionAsyncId, createHook };",
|
|
78
|
-
].join("\n");
|
|
79
|
-
}
|
|
80
|
-
if (id === "\0stub:tanstack-head-scripts") {
|
|
81
|
-
return "export const injectedHeadScripts = undefined;";
|
|
55
|
+
// Framework plugin — provides server-only stubs (react-dom/server,
|
|
56
|
+
// node:async_hooks, etc.), blocks.gen.ts JSON-fast-path, meta.gen
|
|
57
|
+
// client stub, daemon/tunnel for dev mode, and correct manualChunks
|
|
58
|
+
// (NOT splitting @decocms/start / @decocms/apps which have circular
|
|
59
|
+
// re-exports). Replaces ~80 lines of boilerplate that older sites
|
|
60
|
+
// had inline.
|
|
61
|
+
decoVitePlugin(),
|
|
62
|
+
],
|
|
63
|
+
build: {
|
|
64
|
+
sourcemap: "hidden",
|
|
65
|
+
rollupOptions: {
|
|
66
|
+
onLog(level, log, handler) {
|
|
67
|
+
// Silence harmless "dynamic import will not move module" warning
|
|
68
|
+
// emitted when a module is imported both statically and dynamically.
|
|
69
|
+
if (
|
|
70
|
+
log.code === "PLUGIN_WARNING" &&
|
|
71
|
+
log.plugin === "vite:reporter" &&
|
|
72
|
+
log.message?.includes("dynamic import will not move module")
|
|
73
|
+
) {
|
|
74
|
+
return;
|
|
82
75
|
}
|
|
76
|
+
handler(level, log);
|
|
83
77
|
},
|
|
84
78
|
},
|
|
85
|
-
|
|
86
|
-
// Inject site name at build time (not runtime)
|
|
79
|
+
},
|
|
87
80
|
define: {
|
|
81
|
+
// Inject site name at build time, not read at runtime.
|
|
88
82
|
"process.env.DECO_SITE_NAME": JSON.stringify(
|
|
89
|
-
process.env.DECO_SITE_NAME || "my-store"
|
|
83
|
+
process.env.DECO_SITE_NAME || "my-store",
|
|
90
84
|
),
|
|
91
85
|
},
|
|
92
86
|
esbuild: {
|
|
93
87
|
jsx: "automatic",
|
|
94
88
|
jsxImportSource: "react",
|
|
89
|
+
// Strip console.log in production; keep .warn / .error for debugging.
|
|
90
|
+
pure: ["console.log"],
|
|
95
91
|
},
|
|
96
92
|
resolve: {
|
|
97
|
-
// CRITICAL:
|
|
93
|
+
// CRITICAL: without dedupe, multiple React/TanStack instances cause
|
|
94
|
+
// "Invalid hook call" errors at runtime.
|
|
98
95
|
dedupe: [
|
|
96
|
+
"@decocms/start",
|
|
97
|
+
"@decocms/apps",
|
|
99
98
|
"@tanstack/react-start",
|
|
100
99
|
"@tanstack/react-router",
|
|
101
100
|
"@tanstack/react-start-server",
|
|
@@ -115,8 +114,84 @@ export default defineConfig({
|
|
|
115
114
|
|
|
116
115
|
## Key Points
|
|
117
116
|
|
|
118
|
-
1.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
117
|
+
1. **`decoVitePlugin()`** — Required. Replaces ~80 lines of inline boilerplate
|
|
118
|
+
that older sites had to copy. Provides:
|
|
119
|
+
- Client stubs for server-only modules (`react-dom/server`,
|
|
120
|
+
`node:async_hooks`, `node:stream`, etc.)
|
|
121
|
+
- `blocks.gen.ts` JSON fast-path (10-100x parse speedup for large registries)
|
|
122
|
+
- `meta.gen.{json,ts}` client stub (cuts admin schema 0.5-5MB out of
|
|
123
|
+
browser bundle)
|
|
124
|
+
- Daemon/tunnel for dev mode (when `DECO_SITE_NAME` env is set)
|
|
125
|
+
- Production `manualChunks` that does NOT split `@decocms/start` or
|
|
126
|
+
`@decocms/apps` (those have circular re-exports and crash when chunked
|
|
127
|
+
separately)
|
|
128
|
+
- `allowedHosts` for tunnel domains (`.deco.host`, `.decocdn.com`,
|
|
129
|
+
`.deco.studio`)
|
|
130
|
+
- JSX automatic / react import-source defaults
|
|
131
|
+
|
|
132
|
+
2. **`resolve.dedupe`** — Required. Without it, multiple React instances
|
|
133
|
+
cause "Invalid hook call" errors. The list MUST include both
|
|
134
|
+
`@decocms/start` and `@decocms/apps` because they re-export TanStack
|
|
135
|
+
types and registry singletons.
|
|
136
|
+
|
|
137
|
+
3. **`process.env.DECO_SITE_NAME` via `define`** — Must be injected at
|
|
138
|
+
build time, not read at runtime. Workers don't have a Node-style
|
|
139
|
+
`process.env` at runtime.
|
|
140
|
+
|
|
141
|
+
4. **React Compiler** — `babel-plugin-react-compiler` with `target: "19"`
|
|
142
|
+
for automatic memoization. Requires `@vitejs/plugin-react`, not the
|
|
143
|
+
default SWC plugin.
|
|
144
|
+
|
|
145
|
+
5. **`esbuild.jsx: "automatic"` with `jsxImportSource: "react"`** — Without
|
|
146
|
+
it, JSX falls back to `React.createElement` references that may not
|
|
147
|
+
resolve.
|
|
148
|
+
|
|
149
|
+
6. **CSP `frame-ancestors`** — Required for the admin (`*.deco.studio`,
|
|
150
|
+
`admin.deco.cx`, `studio.decocms.com`) to embed previews in iframes.
|
|
151
|
+
|
|
152
|
+
7. **VTEX dev proxy** — Local `/api/`, `/checkout` requests proxied to
|
|
153
|
+
the upstream commerce backend so cookie-based session works in dev
|
|
154
|
+
without CORS gymnastics.
|
|
155
|
+
|
|
156
|
+
## What older site templates inline (and why this template doesn't)
|
|
157
|
+
|
|
158
|
+
Some older guides show two extra inline plugins:
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
// site-manual-chunks — overrides framework default chunking
|
|
162
|
+
{ name: "site-manual-chunks", config(_cfg, { command }) { ... } }
|
|
163
|
+
|
|
164
|
+
// deco-stub-meta-gen — stubs admin schema on client
|
|
165
|
+
{ name: "deco-stub-meta-gen", enforce: "pre", resolveId(...), load(...) }
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Both are obsolete after `@decocms/start` >= 2.5.0:
|
|
169
|
+
- The framework's `manualChunks` no longer splits `@decocms/start` /
|
|
170
|
+
`@decocms/apps` (the old split caused circular-dep load-order crashes —
|
|
171
|
+
every site overrode it).
|
|
172
|
+
- The framework now stubs `meta.gen.{json,ts}` on the client by default.
|
|
173
|
+
|
|
174
|
+
If you're on an older version, keep the inline plugins until you can bump.
|
|
175
|
+
|
|
176
|
+
## tsconfig.json (matches the Vite alias)
|
|
177
|
+
|
|
178
|
+
```json
|
|
179
|
+
{
|
|
180
|
+
"compilerOptions": {
|
|
181
|
+
"jsx": "react-jsx",
|
|
182
|
+
"moduleResolution": "bundler",
|
|
183
|
+
"module": "ESNext",
|
|
184
|
+
"target": "ES2022",
|
|
185
|
+
"skipLibCheck": true,
|
|
186
|
+
"strictNullChecks": true,
|
|
187
|
+
"baseUrl": ".",
|
|
188
|
+
"paths": {
|
|
189
|
+
"~/*": ["./src/*"]
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
"include": ["src/**/*", "vite.config.ts"]
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
No `$store/*`, `site/*`, `apps/*`, `preact`, `@preact/signals`,
|
|
197
|
+
`@deco/deco` paths. Those are all dead.
|
package/package.json
CHANGED
|
@@ -25,7 +25,7 @@ import * as fs from "node:fs";
|
|
|
25
25
|
import * as path from "node:path";
|
|
26
26
|
import { fileURLToPath } from "node:url";
|
|
27
27
|
import { execSync, spawnSync } from "node:child_process";
|
|
28
|
-
import { banner, stat, red, green, yellow, cyan, bold, dim, icons } from "./migrate/colors
|
|
28
|
+
import { banner, stat, red, green, yellow, cyan, bold, dim, icons } from "./migrate/colors";
|
|
29
29
|
|
|
30
30
|
const __filename = fileURLToPath(import.meta.url);
|
|
31
31
|
const __dirname = path.dirname(__filename);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import type { MigrationContext, IslandClassification } from "../types
|
|
4
|
-
import { log } from "../types
|
|
3
|
+
import type { MigrationContext, IslandClassification } from "../types";
|
|
4
|
+
import { log } from "../types";
|
|
5
5
|
|
|
6
6
|
const REEXPORT_RE = /^export\s+\{\s*default\s*\}\s+from\s+["']([^"']+)["']/m;
|
|
7
7
|
const NAMED_REEXPORT_RE = /^export\s+\{[^}]+\}\s+from\s+["']([^"']+)["']/m;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import type { MigrationContext, LoaderInfo, Platform } from "../types
|
|
4
|
-
import { log } from "../types
|
|
3
|
+
import type { MigrationContext, LoaderInfo, Platform } from "../types";
|
|
4
|
+
import { log } from "../types";
|
|
5
5
|
|
|
6
6
|
/** Well-known loaders that map directly to @decocms/apps equivalents */
|
|
7
7
|
const APPS_EQUIVALENTS: Record<string, string> = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import type { MigrationContext, SectionMeta } from "../types
|
|
4
|
-
import { log } from "../types
|
|
3
|
+
import type { MigrationContext, SectionMeta } from "../types";
|
|
4
|
+
import { log } from "../types";
|
|
5
5
|
|
|
6
6
|
const HEADER_RE = /\bheader\b/i;
|
|
7
7
|
const FOOTER_RE = /\bfooter\b/i;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import type { MigrationContext } from "../types
|
|
4
|
-
import { log } from "../types
|
|
3
|
+
import type { MigrationContext } from "../types";
|
|
4
|
+
import { log } from "../types";
|
|
5
5
|
|
|
6
6
|
export interface ExtractedTheme {
|
|
7
7
|
/** Raw CSS variable -> hex color map from DEFAULT_THEME */
|
|
@@ -5,11 +5,11 @@ import type {
|
|
|
5
5
|
FileRecord,
|
|
6
6
|
MigrationContext,
|
|
7
7
|
Platform,
|
|
8
|
-
} from "./types
|
|
9
|
-
import { log, logPhase } from "./types
|
|
10
|
-
import { extractSectionMetadata } from "./analyzers/section-metadata
|
|
11
|
-
import { classifyIslands } from "./analyzers/island-classifier
|
|
12
|
-
import { inventoryLoaders } from "./analyzers/loader-inventory
|
|
8
|
+
} from "./types";
|
|
9
|
+
import { log, logPhase } from "./types";
|
|
10
|
+
import { extractSectionMetadata } from "./analyzers/section-metadata";
|
|
11
|
+
import { classifyIslands } from "./analyzers/island-classifier";
|
|
12
|
+
import { inventoryLoaders } from "./analyzers/loader-inventory";
|
|
13
13
|
|
|
14
14
|
const PATTERN_DETECTORS: Array<[DetectedPattern, RegExp]> = [
|
|
15
15
|
["preact-hooks", /from\s+["']preact\/hooks["']/],
|
|
@@ -390,7 +390,7 @@ function scanDir(
|
|
|
390
390
|
|
|
391
391
|
let content = "";
|
|
392
392
|
let patterns: DetectedPattern[] = [];
|
|
393
|
-
let reExport
|
|
393
|
+
let reExport: { is: boolean; target?: string } = { is: false };
|
|
394
394
|
|
|
395
395
|
if (isCode) {
|
|
396
396
|
content = fs.readFileSync(fullPath, "utf-8");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import type { MigrationContext } from "./types
|
|
4
|
-
import { log, logPhase } from "./types
|
|
3
|
+
import type { MigrationContext } from "./types";
|
|
4
|
+
import { log, logPhase } from "./types";
|
|
5
5
|
|
|
6
6
|
/** Directories to remove entirely after migration */
|
|
7
7
|
const DIRS_TO_DELETE = [
|
|
@@ -1005,42 +1005,38 @@ function upgradeSectionRenderer(ctx: MigrationContext) {
|
|
|
1005
1005
|
}
|
|
1006
1006
|
|
|
1007
1007
|
/**
|
|
1008
|
-
*
|
|
1009
|
-
* to use the simplified ~/lib/ wrappers generated during scaffold.
|
|
1008
|
+
* Cleanup pass for VTEX-style transform / signature workarounds.
|
|
1010
1009
|
*
|
|
1011
|
-
*
|
|
1012
|
-
*
|
|
1013
|
-
*
|
|
1014
|
-
*
|
|
1015
|
-
*
|
|
1016
|
-
* -
|
|
1017
|
-
*
|
|
1018
|
-
*
|
|
1019
|
-
*
|
|
1010
|
+
* Historical context:
|
|
1011
|
+
* Earlier versions of this script rewrote `@decocms/apps/vtex/utils/*` imports
|
|
1012
|
+
* to local `~/lib/vtex-*` shims because those modules did not exist yet in
|
|
1013
|
+
* `@decocms/apps`. They now do (apps-start exports `./vtex/utils/*` and
|
|
1014
|
+
* `./vtex/client` directly), so any further rewrite would actively REGRESS
|
|
1015
|
+
* working direct imports back into NO-OP shims and silently break runtime
|
|
1016
|
+
* behavior on every migrated site.
|
|
1017
|
+
*
|
|
1018
|
+
* Scope kept here:
|
|
1019
|
+
* - `@decocms/apps/vtex/loaders/intelligentSearch/*` → inline stubs
|
|
1020
|
+
* (loaders moved under `inline-loaders/` in apps-start; this is still a
|
|
1021
|
+
* real path-mismatch fixup)
|
|
1022
|
+
* - `LabelledFuzzy` type + `mapLabelledFuzzyToFuzzy` helper inlined when
|
|
1023
|
+
* `intelligentSearch/productListingPage` is imported
|
|
1024
|
+
* - `createHttpClient<Type>(...)` → `createHttpClient(...)` (Proxy handles types)
|
|
1025
|
+
* - `fetcher: fetchSafe,` parameter strip (Proxy uses native fetch)
|
|
1026
|
+
* - Inline stub hoisting: when a Fresh loader declares
|
|
1027
|
+
* `const getSegmentFromBag = ... = ({})` etc, hoist them into imports from
|
|
1028
|
+
* the corresponding `~/lib/*` shim so multiple loaders stay in sync
|
|
1029
|
+
*
|
|
1030
|
+
* What was removed:
|
|
1031
|
+
* The four `@decocms/apps/vtex/utils/* → ~/lib/vtex-*` rewrites that the
|
|
1032
|
+
* first-pass `transforms/imports.ts` (lines 50-52) already produces in the
|
|
1033
|
+
* correct, direct form. See discovery notes in MIGRATION_TOOLING_PLAN.md.
|
|
1020
1034
|
*/
|
|
1021
1035
|
function rewriteVtexUtilImports(ctx: MigrationContext) {
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
desc: "vtex/utils/transform → ~/lib/vtex-transform",
|
|
1027
|
-
},
|
|
1028
|
-
{
|
|
1029
|
-
pattern: /from\s+["']@decocms\/apps\/vtex\/utils\/intelligentSearch["']/g,
|
|
1030
|
-
replacement: 'from "~/lib/vtex-intelligent-search"',
|
|
1031
|
-
desc: "vtex/utils/intelligentSearch → ~/lib/vtex-intelligent-search",
|
|
1032
|
-
},
|
|
1033
|
-
{
|
|
1034
|
-
pattern: /from\s+["']@decocms\/apps\/vtex\/utils\/segment["']/g,
|
|
1035
|
-
replacement: 'from "~/lib/vtex-segment"',
|
|
1036
|
-
desc: "vtex/utils/segment → ~/lib/vtex-segment",
|
|
1037
|
-
},
|
|
1038
|
-
{
|
|
1039
|
-
pattern: /from\s+["']@decocms\/apps\/vtex\/client["']/g,
|
|
1040
|
-
replacement: 'from "~/lib/vtex-client"',
|
|
1041
|
-
desc: "vtex/client → ~/lib/vtex-client",
|
|
1042
|
-
},
|
|
1043
|
-
];
|
|
1036
|
+
// Intentionally empty — see docstring. First-pass `transforms/imports.ts`
|
|
1037
|
+
// already maps `apps/vtex/utils/*` and `apps/vtex/client` directly to the
|
|
1038
|
+
// `@decocms/apps` equivalents; rewriting them again here would dead-shim them.
|
|
1039
|
+
const importRewrites: Array<{ pattern: RegExp; replacement: string; desc: string }> = [];
|
|
1044
1040
|
|
|
1045
1041
|
rewriteFilesRecursive(ctx, path.join(ctx.sourceDir, "src"), (content, relPath) => {
|
|
1046
1042
|
if (!relPath.endsWith(".tsx") && !relPath.endsWith(".ts")) return null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import type { MigrationContext } from "./types
|
|
4
|
-
import { logPhase } from "./types
|
|
3
|
+
import type { MigrationContext } from "./types";
|
|
4
|
+
import { logPhase } from "./types";
|
|
5
5
|
|
|
6
6
|
const FRAMEWORK_FINDINGS = [
|
|
7
7
|
"Session/analytics SDK is boilerplate duplicated across all sites — should be a single framework function",
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import type { MigrationContext } from "./types
|
|
4
|
-
import { log, logPhase } from "./types
|
|
5
|
-
import { generatePackageJson } from "./templates/package-json
|
|
6
|
-
import { generateTsconfig } from "./templates/tsconfig
|
|
7
|
-
import { generateViteConfig } from "./templates/vite-config
|
|
8
|
-
import { generateWrangler } from "./templates/wrangler
|
|
9
|
-
import { generateKnipConfig } from "./templates/knip-config
|
|
10
|
-
import { generateRoutes } from "./templates/routes
|
|
11
|
-
import { generateSetup } from "./templates/setup
|
|
12
|
-
import { generateServerEntry } from "./templates/server-entry
|
|
13
|
-
import { generateAppCss } from "./templates/app-css
|
|
14
|
-
import { generateTypeFiles } from "./templates/types-gen
|
|
15
|
-
import { generateUiComponents } from "./templates/ui-components
|
|
16
|
-
import { generateHooks } from "./templates/hooks
|
|
17
|
-
import { generateCommerceLoaders } from "./templates/commerce-loaders
|
|
18
|
-
import { generateSectionLoaders } from "./templates/section-loaders
|
|
19
|
-
import { generateCacheConfig } from "./templates/cache-config
|
|
20
|
-
import { generateSdkFiles } from "./templates/sdk-gen
|
|
21
|
-
import { generateLibUtils } from "./templates/lib-utils
|
|
22
|
-
import { extractTheme } from "./analyzers/theme-extractor
|
|
3
|
+
import type { MigrationContext } from "./types";
|
|
4
|
+
import { log, logPhase } from "./types";
|
|
5
|
+
import { generatePackageJson } from "./templates/package-json";
|
|
6
|
+
import { generateTsconfig } from "./templates/tsconfig";
|
|
7
|
+
import { generateViteConfig } from "./templates/vite-config";
|
|
8
|
+
import { generateWrangler } from "./templates/wrangler";
|
|
9
|
+
import { generateKnipConfig } from "./templates/knip-config";
|
|
10
|
+
import { generateRoutes } from "./templates/routes";
|
|
11
|
+
import { generateSetup } from "./templates/setup";
|
|
12
|
+
import { generateServerEntry } from "./templates/server-entry";
|
|
13
|
+
import { generateAppCss } from "./templates/app-css";
|
|
14
|
+
import { generateTypeFiles } from "./templates/types-gen";
|
|
15
|
+
import { generateUiComponents } from "./templates/ui-components";
|
|
16
|
+
import { generateHooks } from "./templates/hooks";
|
|
17
|
+
import { generateCommerceLoaders } from "./templates/commerce-loaders";
|
|
18
|
+
import { generateSectionLoaders } from "./templates/section-loaders";
|
|
19
|
+
import { generateCacheConfig } from "./templates/cache-config";
|
|
20
|
+
import { generateSdkFiles } from "./templates/sdk-gen";
|
|
21
|
+
import { generateLibUtils } from "./templates/lib-utils";
|
|
22
|
+
import { extractTheme } from "./analyzers/theme-extractor";
|
|
23
23
|
|
|
24
24
|
function writeFile(ctx: MigrationContext, relPath: string, content: string) {
|
|
25
25
|
const fullPath = path.join(ctx.sourceDir, relPath);
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import type { MigrationContext, TransformResult, SectionMeta } from "./types
|
|
4
|
-
import { log, logPhase } from "./types
|
|
5
|
-
import { transformImports } from "./transforms/imports
|
|
6
|
-
import { transformJsx } from "./transforms/jsx
|
|
7
|
-
import { transformFreshApis } from "./transforms/fresh-apis
|
|
8
|
-
import { transformDenoIsms } from "./transforms/deno-isms
|
|
9
|
-
import { transformTailwind } from "./transforms/tailwind
|
|
10
|
-
import { transformDeadCode } from "./transforms/dead-code
|
|
11
|
-
import { transformSectionConventions } from "./transforms/section-conventions
|
|
3
|
+
import type { MigrationContext, TransformResult, SectionMeta } from "./types";
|
|
4
|
+
import { log, logPhase } from "./types";
|
|
5
|
+
import { transformImports } from "./transforms/imports";
|
|
6
|
+
import { transformJsx } from "./transforms/jsx";
|
|
7
|
+
import { transformFreshApis } from "./transforms/fresh-apis";
|
|
8
|
+
import { transformDenoIsms } from "./transforms/deno-isms";
|
|
9
|
+
import { transformTailwind } from "./transforms/tailwind";
|
|
10
|
+
import { transformDeadCode } from "./transforms/dead-code";
|
|
11
|
+
import { transformSectionConventions } from "./transforms/section-conventions";
|
|
12
12
|
|
|
13
13
|
/** Map of section path → metadata, populated per-run */
|
|
14
14
|
let sectionMetaMap: Map<string, SectionMeta> | null = null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import type { MigrationContext } from "./types
|
|
4
|
-
import { logPhase } from "./types
|
|
3
|
+
import type { MigrationContext } from "./types";
|
|
4
|
+
import { logPhase } from "./types";
|
|
5
5
|
|
|
6
6
|
interface Check {
|
|
7
7
|
name: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import type { MigrationContext } from "../types
|
|
4
|
-
import type { ExtractedTheme } from "../analyzers/theme-extractor
|
|
3
|
+
import type { MigrationContext } from "../types";
|
|
4
|
+
import type { ExtractedTheme } from "../analyzers/theme-extractor";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Find the original site's custom CSS file.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import type { MigrationContext } from "../types
|
|
3
|
+
import type { MigrationContext } from "../types";
|
|
4
4
|
|
|
5
5
|
function discoverFonts(ctx: MigrationContext): string[] {
|
|
6
6
|
const fontsDir = path.join(ctx.sourceDir, "public", "fonts");
|