@decocms/start 0.19.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/.cursor/skills/deco-api-call-dedup/SKILL.md +443 -0
- package/.cursor/skills/deco-apps-architecture/SKILL.md +255 -0
- package/.cursor/skills/deco-apps-architecture/app-pattern.md +288 -0
- package/.cursor/skills/deco-apps-architecture/commerce-types.md +239 -0
- package/.cursor/skills/deco-apps-architecture/new-app-guide.md +268 -0
- package/.cursor/skills/deco-apps-architecture/scripts-codegen.md +148 -0
- package/.cursor/skills/deco-apps-architecture/shared-utils.md +181 -0
- package/.cursor/skills/deco-apps-architecture/vtex-deep-structure.md +253 -0
- package/.cursor/skills/deco-apps-architecture/website-app.md +169 -0
- package/.cursor/skills/deco-apps-vtex-porting/SKILL.md +189 -0
- package/.cursor/skills/deco-apps-vtex-porting/adaptation-patterns.md +335 -0
- package/.cursor/skills/deco-apps-vtex-porting/commerce-porting.md +155 -0
- package/.cursor/skills/deco-apps-vtex-porting/cookie-auth-patterns.md +148 -0
- package/.cursor/skills/deco-apps-vtex-porting/structure-map.md +234 -0
- package/.cursor/skills/deco-apps-vtex-porting/transform-mapping.md +99 -0
- package/.cursor/skills/deco-apps-vtex-porting/website-porting.md +194 -0
- package/.cursor/skills/deco-apps-vtex-review/SKILL.md +234 -0
- package/.cursor/skills/deco-async-rendering-architecture/SKILL.md +270 -0
- package/.cursor/skills/deco-async-rendering-site-guide/SKILL.md +417 -0
- package/.cursor/skills/deco-cms-layout-caching/SKILL.md +293 -0
- package/.cursor/skills/deco-cms-route-config/SKILL.md +388 -0
- package/.cursor/skills/deco-core-architecture/SKILL.md +185 -0
- package/.cursor/skills/deco-core-architecture/blocks.md +196 -0
- package/.cursor/skills/deco-core-architecture/deco-vs-deco-start.md +191 -0
- package/.cursor/skills/deco-core-architecture/engine.md +220 -0
- package/.cursor/skills/deco-core-architecture/hooks-components.md +157 -0
- package/.cursor/skills/deco-core-architecture/plugins-clients.md +136 -0
- package/.cursor/skills/deco-core-architecture/runtime.md +116 -0
- package/.cursor/skills/deco-core-architecture/site-usage.md +165 -0
- package/.cursor/skills/deco-e2e-testing/SKILL.md +372 -0
- package/.cursor/skills/deco-e2e-testing/discovery.md +337 -0
- package/.cursor/skills/deco-e2e-testing/scripts/scaffold.sh +81 -0
- package/.cursor/skills/deco-e2e-testing/selectors.md +175 -0
- package/.cursor/skills/deco-e2e-testing/templates/package.json +18 -0
- package/.cursor/skills/deco-e2e-testing/templates/playwright.config.ts +65 -0
- package/.cursor/skills/deco-e2e-testing/templates/scripts/baseline.ts +279 -0
- package/.cursor/skills/deco-e2e-testing/templates/scripts/run-e2e.ts +194 -0
- package/.cursor/skills/deco-e2e-testing/templates/specs/ecommerce-flow.spec.ts +612 -0
- package/.cursor/skills/deco-e2e-testing/templates/tsconfig.json +12 -0
- package/.cursor/skills/deco-e2e-testing/templates/utils/metrics-collector.ts +918 -0
- package/.cursor/skills/deco-e2e-testing/troubleshooting.md +602 -0
- package/.cursor/skills/deco-edge-caching/SKILL.md +316 -0
- package/.cursor/skills/deco-full-analysis/SKILL.md +898 -0
- package/.cursor/skills/deco-full-analysis/checklists/asset-optimization.md +251 -0
- package/.cursor/skills/deco-full-analysis/checklists/bug-fix.md +189 -0
- package/.cursor/skills/deco-full-analysis/checklists/cache-strategy.md +144 -0
- package/.cursor/skills/deco-full-analysis/checklists/dependency-update.md +150 -0
- package/.cursor/skills/deco-full-analysis/checklists/hydration-fix.md +191 -0
- package/.cursor/skills/deco-full-analysis/checklists/image-optimization.md +180 -0
- package/.cursor/skills/deco-full-analysis/checklists/loader-optimization.md +165 -0
- package/.cursor/skills/deco-full-analysis/checklists/seo-fix.md +183 -0
- package/.cursor/skills/deco-full-analysis/checklists/site-cleanup.md +281 -0
- package/.cursor/skills/deco-full-analysis/discovery.md +548 -0
- package/.cursor/skills/deco-incident-debugging/SKILL.md +378 -0
- package/.cursor/skills/deco-incident-debugging/headless-mode.md +510 -0
- package/.cursor/skills/deco-incident-debugging/learnings-index.md +227 -0
- package/.cursor/skills/deco-incident-debugging/triage-workflow.md +312 -0
- package/.cursor/skills/deco-islands-migration/SKILL.md +251 -0
- package/.cursor/skills/deco-loader-n-plus-1-detector/SKILL.md +275 -0
- package/.cursor/skills/deco-performance-audit/SKILL.md +530 -0
- package/.cursor/skills/deco-performance-audit/tools-reference.md +428 -0
- package/.cursor/skills/deco-performance-audit/workflow.md +457 -0
- package/.cursor/skills/deco-server-functions-invoke/SKILL.md +92 -0
- package/.cursor/skills/deco-server-functions-invoke/architecture.md +166 -0
- package/.cursor/skills/deco-server-functions-invoke/generator.md +122 -0
- package/.cursor/skills/deco-server-functions-invoke/problem.md +98 -0
- package/.cursor/skills/deco-server-functions-invoke/troubleshooting.md +110 -0
- package/.cursor/skills/deco-site-deployment/SKILL.md +396 -0
- package/.cursor/skills/deco-site-memory-debugging/SKILL.md +121 -0
- package/.cursor/skills/deco-site-memory-debugging/cdp-connection.md +222 -0
- package/.cursor/skills/deco-site-memory-debugging/memory-analysis.md +362 -0
- package/.cursor/skills/deco-site-patterns/SKILL.md +124 -0
- package/.cursor/skills/deco-site-patterns/app-composition.md +337 -0
- package/.cursor/skills/deco-site-patterns/client-patterns.md +341 -0
- package/.cursor/skills/deco-site-patterns/cms-wiring.md +230 -0
- package/.cursor/skills/deco-site-patterns/section-patterns.md +340 -0
- package/.cursor/skills/deco-site-scaling-tuning/SKILL.md +240 -0
- package/.cursor/skills/deco-site-scaling-tuning/analysis-scripts.md +267 -0
- package/.cursor/skills/deco-start-architecture/SKILL.md +218 -0
- package/.cursor/skills/deco-start-architecture/admin-protocol.md +156 -0
- package/.cursor/skills/deco-start-architecture/cms-resolution.md +201 -0
- package/.cursor/skills/deco-start-architecture/code-quality.md +158 -0
- package/.cursor/skills/deco-start-architecture/gap-analysis.md +129 -0
- package/.cursor/skills/deco-start-architecture/sdk-utilities.md +197 -0
- package/.cursor/skills/deco-start-architecture/worker-entry-caching.md +154 -0
- package/.cursor/skills/deco-startup-analysis/SKILL.md +248 -0
- package/.cursor/skills/deco-storefront-test-checklist/SKILL.md +369 -0
- package/.cursor/skills/deco-tanstack-hydration-fixes/SKILL.md +468 -0
- package/.cursor/skills/deco-tanstack-navigation/SKILL.md +681 -0
- package/.cursor/skills/deco-tanstack-search/SKILL.md +411 -0
- package/.cursor/skills/deco-tanstack-storefront-patterns/SKILL.md +1013 -0
- package/.cursor/skills/deco-to-tanstack-migration/SKILL.md +518 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/codemod-commands.md +174 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/commerce/README.md +78 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/deco-framework/README.md +128 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/gotchas.md +719 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/imports/README.md +70 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/platform-hooks/README.md +154 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/signals/README.md +220 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/vite-config/README.md +78 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/package-json.md +55 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/root-route.md +110 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/router.md +96 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/setup-ts.md +167 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/vite-config.md +122 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/worker-entry.md +67 -0
- package/.cursor/skills/deco-typescript-fixes/SKILL.md +178 -0
- package/.cursor/skills/deco-typescript-fixes/common-fixes.md +330 -0
- package/.cursor/skills/deco-typescript-fixes/strategy.md +148 -0
- package/.cursor/skills/deco-variant-selection-perf/SKILL.md +272 -0
- package/.cursor/skills/deco-vtex-fetch-cache/SKILL.md +225 -0
- package/.cursor/skills/find-skills/SKILL.md +133 -0
- package/.cursor/skills/incident-report/SKILL.md +179 -0
- package/.cursor/skills/incident-report/references/5-whys.md +75 -0
- package/.cursor/skills/incident-report/templates/client-report.md +187 -0
- package/.cursor/skills/incident-report/templates/internal-report.md +206 -0
- package/.cursor/skills/template-skill/SKILL.md +38 -0
- package/.github/workflows/release.yml +32 -0
- package/.releaserc.json +25 -0
- package/CLAUDE.md +135 -0
- package/GAP_ANALYSIS.md +224 -0
- package/GAP_ANALYSIS_V2.md +1013 -0
- package/biome.json +39 -0
- package/knip.json +5 -0
- package/package.json +87 -0
- package/scripts/generate-blocks.ts +69 -0
- package/scripts/generate-invoke.ts +378 -0
- package/scripts/generate-schema.ts +657 -0
- package/src/admin/cors.ts +29 -0
- package/src/admin/decofile.ts +72 -0
- package/src/admin/index.ts +24 -0
- package/src/admin/invoke.ts +163 -0
- package/src/admin/liveControls.ts +29 -0
- package/src/admin/meta.ts +70 -0
- package/src/admin/render.ts +205 -0
- package/src/admin/schema.ts +686 -0
- package/src/admin/setup.ts +44 -0
- package/src/cms/index.ts +59 -0
- package/src/cms/loader.ts +180 -0
- package/src/cms/registry.ts +162 -0
- package/src/cms/resolve.ts +1005 -0
- package/src/cms/sectionLoaders.ts +294 -0
- package/src/hooks/DecoPageRenderer.tsx +444 -0
- package/src/hooks/LazySection.tsx +109 -0
- package/src/hooks/LiveControls.tsx +108 -0
- package/src/hooks/SectionErrorFallback.tsx +85 -0
- package/src/hooks/index.ts +8 -0
- package/src/index.ts +5 -0
- package/src/matchers/builtins.ts +184 -0
- package/src/matchers/posthog.ts +154 -0
- package/src/middleware/decoState.ts +55 -0
- package/src/middleware/healthMetrics.ts +131 -0
- package/src/middleware/index.ts +80 -0
- package/src/middleware/liveness.ts +21 -0
- package/src/middleware/observability.ts +205 -0
- package/src/routes/adminRoutes.ts +83 -0
- package/src/routes/cmsRoute.ts +302 -0
- package/src/routes/components.tsx +34 -0
- package/src/routes/index.ts +15 -0
- package/src/sdk/analytics.ts +72 -0
- package/src/sdk/cacheHeaders.ts +268 -0
- package/src/sdk/cachedLoader.ts +206 -0
- package/src/sdk/clx.ts +3 -0
- package/src/sdk/cookie.ts +39 -0
- package/src/sdk/createInvoke.ts +57 -0
- package/src/sdk/csp.ts +59 -0
- package/src/sdk/env.ts +27 -0
- package/src/sdk/index.ts +63 -0
- package/src/sdk/instrumentedFetch.ts +137 -0
- package/src/sdk/invoke.ts +133 -0
- package/src/sdk/mergeCacheControl.ts +150 -0
- package/src/sdk/redirects.ts +217 -0
- package/src/sdk/requestContext.ts +184 -0
- package/src/sdk/serverTimings.ts +68 -0
- package/src/sdk/signal.ts +41 -0
- package/src/sdk/sitemap.ts +143 -0
- package/src/sdk/urlUtils.ts +117 -0
- package/src/sdk/useDevice.ts +82 -0
- package/src/sdk/useId.ts +7 -0
- package/src/sdk/useScript.ts +101 -0
- package/src/sdk/workerEntry.ts +703 -0
- package/src/sdk/wrapCaughtErrors.ts +107 -0
- package/src/types/index.ts +39 -0
- package/src/types/widgets.ts +13 -0
- package/tsconfig.json +13 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# router.tsx Template
|
|
2
|
+
|
|
3
|
+
```typescript
|
|
4
|
+
import { createRouter as createTanStackRouter } from "@tanstack/react-router";
|
|
5
|
+
import { routeTree } from "./routeTree.gen";
|
|
6
|
+
|
|
7
|
+
export function createRouter() {
|
|
8
|
+
const router = createTanStackRouter({
|
|
9
|
+
routeTree,
|
|
10
|
+
scrollRestoration: true,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
// Scroll to top on forward navigation (PUSH/REPLACE), skip on back/forward (GO)
|
|
14
|
+
router.subscribe("onResolved", (evt) => {
|
|
15
|
+
if (evt.type === "GO") return;
|
|
16
|
+
window.scrollTo({ top: 0 });
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
return router;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
declare module "@tanstack/react-router" {
|
|
23
|
+
interface Register {
|
|
24
|
+
router: ReturnType<typeof createRouter>;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Route Files
|
|
30
|
+
|
|
31
|
+
### src/routes/index.tsx (Homepage)
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
35
|
+
import { cmsHomeRouteConfig } from "@decocms/start/routes";
|
|
36
|
+
import { DecoPageRenderer } from "@decocms/start/hooks";
|
|
37
|
+
import { loadDeferredSection } from "@decocms/start/routes/cmsRoute";
|
|
38
|
+
|
|
39
|
+
const { loader, head } = cmsHomeRouteConfig({
|
|
40
|
+
defaultTitle: "My Store",
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export const Route = createFileRoute("/")({
|
|
44
|
+
loader,
|
|
45
|
+
head,
|
|
46
|
+
component: HomePage,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
function HomePage() {
|
|
50
|
+
const { resolvedSections, deferredSections, pagePath } = Route.useLoaderData();
|
|
51
|
+
return (
|
|
52
|
+
<DecoPageRenderer
|
|
53
|
+
sections={resolvedSections}
|
|
54
|
+
deferredSections={deferredSections}
|
|
55
|
+
pagePath={pagePath}
|
|
56
|
+
loadDeferredSectionFn={loadDeferredSection}
|
|
57
|
+
/>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### src/routes/$.tsx (Catch-All CMS Route)
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { createFileRoute, notFound } from "@tanstack/react-router";
|
|
66
|
+
import { cmsRouteConfig } from "@decocms/start/routes";
|
|
67
|
+
import { DecoPageRenderer } from "@decocms/start/hooks";
|
|
68
|
+
import { loadDeferredSection } from "@decocms/start/routes/cmsRoute";
|
|
69
|
+
|
|
70
|
+
const { loader, head } = cmsRouteConfig({
|
|
71
|
+
siteName: "My Store",
|
|
72
|
+
ignoreSearchParams: ["skuId"],
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
export const Route = createFileRoute("/$")({
|
|
76
|
+
loader: async (ctx) => {
|
|
77
|
+
const data = await loader(ctx);
|
|
78
|
+
if (!data) throw notFound();
|
|
79
|
+
return data;
|
|
80
|
+
},
|
|
81
|
+
head,
|
|
82
|
+
component: CmsPage,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
function CmsPage() {
|
|
86
|
+
const { resolvedSections, deferredSections, pagePath } = Route.useLoaderData();
|
|
87
|
+
return (
|
|
88
|
+
<DecoPageRenderer
|
|
89
|
+
sections={resolvedSections}
|
|
90
|
+
deferredSections={deferredSections}
|
|
91
|
+
pagePath={pagePath}
|
|
92
|
+
loadDeferredSectionFn={loadDeferredSection}
|
|
93
|
+
/>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
```
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# setup.ts Template
|
|
2
|
+
|
|
3
|
+
Annotated template based on espacosmart-storefront (100+ sections, VTEX, async rendering).
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
// ==========================================================================
|
|
7
|
+
// 1. CMS BLOCKS & META
|
|
8
|
+
// ==========================================================================
|
|
9
|
+
|
|
10
|
+
import blocksJson from "./server/cms/blocks.gen.ts";
|
|
11
|
+
import metaData from "./server/admin/meta.gen.json";
|
|
12
|
+
import { setBlocks } from "@decocms/start/cms/loader";
|
|
13
|
+
import { setMetaData, setInvokeLoaders, setRenderShell } from "@decocms/start/admin";
|
|
14
|
+
import { registerSections, registerSectionsSync, setResolvedComponent } from "@decocms/start/cms/registry";
|
|
15
|
+
import { registerSectionLoaders, registerLayoutSections } from "@decocms/start/cms/sectionLoaders";
|
|
16
|
+
import { registerCommerceLoaders, setAsyncRenderingConfig, onBeforeResolve } from "@decocms/start/cms/resolve";
|
|
17
|
+
import { createCachedLoader } from "@decocms/start/sdk/cachedLoader";
|
|
18
|
+
import appCss from "./styles/app.css?url";
|
|
19
|
+
|
|
20
|
+
// Load CMS blocks (pages, sections, configs) from generated JSON
|
|
21
|
+
setBlocks(blocksJson);
|
|
22
|
+
|
|
23
|
+
// Set admin schema for /live/_meta endpoint
|
|
24
|
+
setMetaData(metaData);
|
|
25
|
+
|
|
26
|
+
// Configure admin preview HTML shell
|
|
27
|
+
setRenderShell({
|
|
28
|
+
css: appCss,
|
|
29
|
+
fonts: ["https://fonts.googleapis.com/css2?family=YourFont:wght@400;500;600;700&display=swap"],
|
|
30
|
+
theme: "light", // data-theme="light" on <html> for DaisyUI
|
|
31
|
+
bodyClass: "bg-base-100 text-base-content",
|
|
32
|
+
lang: "pt-BR",
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// ==========================================================================
|
|
36
|
+
// 2. SECTION REGISTRATION
|
|
37
|
+
// ==========================================================================
|
|
38
|
+
|
|
39
|
+
// Critical sections — above-the-fold, bundled synchronously
|
|
40
|
+
import HeaderSection from "./components/header/Header";
|
|
41
|
+
import FooterSection from "./sections/Footer/Footer";
|
|
42
|
+
|
|
43
|
+
const criticalSections: Record<string, any> = {
|
|
44
|
+
"site/sections/Header/Header.tsx": HeaderSection,
|
|
45
|
+
"site/sections/Footer/Footer.tsx": FooterSection,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// Register sync components for instant SSR (no Suspense boundary)
|
|
49
|
+
for (const [key, mod] of Object.entries(criticalSections)) {
|
|
50
|
+
setResolvedComponent(key, mod.default || mod);
|
|
51
|
+
}
|
|
52
|
+
registerSectionsSync(criticalSections);
|
|
53
|
+
|
|
54
|
+
// All sections — lazy-loaded via dynamic import
|
|
55
|
+
registerSections({
|
|
56
|
+
"site/sections/Header/Header.tsx": () => import("./sections/Header/Header"),
|
|
57
|
+
"site/sections/Footer/Footer.tsx": () => import("./sections/Footer/Footer"),
|
|
58
|
+
"site/sections/Theme/Theme.tsx": () => import("./sections/Theme/Theme"),
|
|
59
|
+
// ... register ALL sections from src/sections/ here
|
|
60
|
+
// Pattern: "site/sections/Path/Name.tsx": () => import("./sections/Path/Name")
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// ==========================================================================
|
|
64
|
+
// 3. LAYOUT SECTIONS
|
|
65
|
+
// ==========================================================================
|
|
66
|
+
|
|
67
|
+
// Layout sections are always rendered eagerly (never lazy/deferred),
|
|
68
|
+
// even if wrapped in Lazy.tsx in the CMS.
|
|
69
|
+
registerLayoutSections([
|
|
70
|
+
"site/sections/Header/Header.tsx",
|
|
71
|
+
"site/sections/Footer/Footer.tsx",
|
|
72
|
+
"site/sections/Theme/Theme.tsx",
|
|
73
|
+
"site/sections/Social/WhatsApp.tsx",
|
|
74
|
+
]);
|
|
75
|
+
|
|
76
|
+
// ==========================================================================
|
|
77
|
+
// 4. SECTION LOADERS
|
|
78
|
+
// ==========================================================================
|
|
79
|
+
|
|
80
|
+
// Section loaders enrich CMS props with server-side data (e.g., VTEX API calls).
|
|
81
|
+
// Only needed for sections that export `const loader`.
|
|
82
|
+
registerSectionLoaders({
|
|
83
|
+
"site/sections/Product/ProductShelf.tsx": (props: any, req: Request) =>
|
|
84
|
+
import("./components/product/ProductShelf").then((m) => m.loader(props, req)),
|
|
85
|
+
"site/sections/Product/SearchResult.tsx": (props: any, req: Request) =>
|
|
86
|
+
import("./components/search/SearchResult").then((m) => m.loader(props, req)),
|
|
87
|
+
// ... add for each section that has `export const loader`
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// ==========================================================================
|
|
91
|
+
// 5. COMMERCE LOADERS (VTEX)
|
|
92
|
+
// ==========================================================================
|
|
93
|
+
|
|
94
|
+
import { vtexProductList } from "@decocms/apps/vtex/loaders/productList";
|
|
95
|
+
import { vtexProductDetailsPage } from "@decocms/apps/vtex/loaders/productDetailsPage";
|
|
96
|
+
import { vtexProductListingPage } from "@decocms/apps/vtex/loaders/productListingPage";
|
|
97
|
+
import { vtexSuggestions } from "@decocms/apps/vtex/loaders/suggestions";
|
|
98
|
+
import { initVtexFromBlocks } from "@decocms/apps/vtex/setup";
|
|
99
|
+
|
|
100
|
+
// SWR-cached commerce loaders — avoids re-fetching on every page navigation
|
|
101
|
+
const cachedProductList = createCachedLoader("vtex/productList", vtexProductList, {
|
|
102
|
+
policy: "stale-while-revalidate", maxAge: 60_000,
|
|
103
|
+
});
|
|
104
|
+
const cachedPDP = createCachedLoader("vtex/pdp", vtexProductDetailsPage, {
|
|
105
|
+
policy: "stale-while-revalidate", maxAge: 30_000,
|
|
106
|
+
});
|
|
107
|
+
const cachedPLP = createCachedLoader("vtex/plp", vtexProductListingPage, {
|
|
108
|
+
policy: "stale-while-revalidate", maxAge: 60_000,
|
|
109
|
+
});
|
|
110
|
+
const cachedSuggestions = createCachedLoader("vtex/suggestions", vtexSuggestions, {
|
|
111
|
+
policy: "stale-while-revalidate", maxAge: 120_000,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Map CMS __resolveType strings to actual loader functions
|
|
115
|
+
registerCommerceLoaders({
|
|
116
|
+
"vtex/loaders/intelligentSearch/productList.ts": cachedProductList,
|
|
117
|
+
"vtex/loaders/intelligentSearch/productListingPage.ts": cachedPLP,
|
|
118
|
+
"vtex/loaders/intelligentSearch/productDetailsPage.ts": cachedPDP,
|
|
119
|
+
"vtex/loaders/intelligentSearch/suggestions.ts": cachedSuggestions,
|
|
120
|
+
// Add passthrough loaders for types that don't need caching:
|
|
121
|
+
// "vtex/loaders/config.ts": (props) => props,
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// ==========================================================================
|
|
125
|
+
// 6. VTEX INITIALIZATION
|
|
126
|
+
// ==========================================================================
|
|
127
|
+
|
|
128
|
+
// onBeforeResolve runs once before the first CMS page resolution.
|
|
129
|
+
// initVtexFromBlocks reads VTEX config (account, publicUrl) from CMS blocks.
|
|
130
|
+
onBeforeResolve(() => {
|
|
131
|
+
initVtexFromBlocks();
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// ==========================================================================
|
|
135
|
+
// 7. ASYNC RENDERING
|
|
136
|
+
// ==========================================================================
|
|
137
|
+
|
|
138
|
+
// Enable deferred section loading (scroll-triggered).
|
|
139
|
+
// Respects CMS Lazy wrappers. Layout sections and alwaysEager are never deferred.
|
|
140
|
+
setAsyncRenderingConfig({
|
|
141
|
+
alwaysEager: [
|
|
142
|
+
"site/sections/Header/Header.tsx",
|
|
143
|
+
"site/sections/Footer/Footer.tsx",
|
|
144
|
+
"site/sections/Theme/Theme.tsx",
|
|
145
|
+
"site/sections/Images/Carousel.tsx",
|
|
146
|
+
// Add above-the-fold sections here
|
|
147
|
+
],
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// ==========================================================================
|
|
151
|
+
// 8. INVOKE LOADERS (for /deco/invoke endpoint)
|
|
152
|
+
// ==========================================================================
|
|
153
|
+
|
|
154
|
+
setInvokeLoaders({
|
|
155
|
+
"vtex/loaders/intelligentSearch/productList.ts": cachedProductList,
|
|
156
|
+
"vtex/loaders/intelligentSearch/suggestions.ts": cachedSuggestions,
|
|
157
|
+
// Used by the admin to preview loader results
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Key Patterns
|
|
162
|
+
|
|
163
|
+
1. **Order matters**: blocks → meta → sections → loaders → commerce → async config
|
|
164
|
+
2. **Critical sections**: Import synchronously for instant SSR, also register as lazy for client code-splitting
|
|
165
|
+
3. **SWR caching**: `createCachedLoader` wraps commerce loaders with stale-while-revalidate
|
|
166
|
+
4. **onBeforeResolve**: Deferred initialization — VTEX config is read from CMS blocks at first request
|
|
167
|
+
5. **alwaysEager**: Sections that must render on first paint (no deferred loading)
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# vite.config.ts Template
|
|
2
|
+
|
|
3
|
+
Battle-tested configuration from espacosmart-storefront.
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
import { cloudflare } from "@cloudflare/vite-plugin";
|
|
7
|
+
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
|
|
8
|
+
import react from "@vitejs/plugin-react";
|
|
9
|
+
import tailwindcss from "@tailwindcss/vite";
|
|
10
|
+
import { defineConfig } from "vite";
|
|
11
|
+
import path from "path";
|
|
12
|
+
|
|
13
|
+
const srcDir = path.resolve(__dirname, "src");
|
|
14
|
+
|
|
15
|
+
export default defineConfig({
|
|
16
|
+
plugins: [
|
|
17
|
+
cloudflare({ viteEnvironment: { name: "ssr" } }),
|
|
18
|
+
tanstackStart({ server: { entry: "server" } }),
|
|
19
|
+
react({
|
|
20
|
+
babel: {
|
|
21
|
+
plugins: [
|
|
22
|
+
["babel-plugin-react-compiler", { target: "19" }],
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
}),
|
|
26
|
+
tailwindcss(),
|
|
27
|
+
// CRITICAL: Stubs for client bundles that transitively import server modules.
|
|
28
|
+
// Without this, client build crashes on node:async_hooks, react-dom/server, etc.
|
|
29
|
+
{
|
|
30
|
+
name: "deco-server-only-stubs",
|
|
31
|
+
enforce: "pre" as const,
|
|
32
|
+
resolveId(id, _importer, options) {
|
|
33
|
+
if (options?.ssr) return undefined;
|
|
34
|
+
const CLIENT_STUBS: Record<string, string> = {
|
|
35
|
+
"react-dom/server": "\0stub:react-dom-server",
|
|
36
|
+
"react-dom/server.browser": "\0stub:react-dom-server",
|
|
37
|
+
"node:stream": "\0stub:node-stream",
|
|
38
|
+
"node:stream/web": "\0stub:node-stream-web",
|
|
39
|
+
"node:async_hooks": "\0stub:node-async-hooks",
|
|
40
|
+
"tanstack-start-injected-head-scripts:v": "\0stub:tanstack-head-scripts",
|
|
41
|
+
};
|
|
42
|
+
return CLIENT_STUBS[id];
|
|
43
|
+
},
|
|
44
|
+
configEnvironment(name: string, env: any) {
|
|
45
|
+
if (name === "ssr" || name === "client") {
|
|
46
|
+
env.optimizeDeps = env.optimizeDeps || {};
|
|
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;";
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
// Inject site name at build time (not runtime)
|
|
87
|
+
define: {
|
|
88
|
+
"process.env.DECO_SITE_NAME": JSON.stringify(
|
|
89
|
+
process.env.DECO_SITE_NAME || "my-store"
|
|
90
|
+
),
|
|
91
|
+
},
|
|
92
|
+
esbuild: {
|
|
93
|
+
jsx: "automatic",
|
|
94
|
+
jsxImportSource: "react",
|
|
95
|
+
},
|
|
96
|
+
resolve: {
|
|
97
|
+
// CRITICAL: Without dedupe, multiple React/TanStack instances cause hook errors
|
|
98
|
+
dedupe: [
|
|
99
|
+
"@tanstack/react-start",
|
|
100
|
+
"@tanstack/react-router",
|
|
101
|
+
"@tanstack/react-start-server",
|
|
102
|
+
"@tanstack/start-server-core",
|
|
103
|
+
"@tanstack/start-client-core",
|
|
104
|
+
"@tanstack/start-plugin-core",
|
|
105
|
+
"@tanstack/start-storage-context",
|
|
106
|
+
"react",
|
|
107
|
+
"react-dom",
|
|
108
|
+
],
|
|
109
|
+
alias: {
|
|
110
|
+
"~": srcDir,
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Key Points
|
|
117
|
+
|
|
118
|
+
1. **deco-server-only-stubs plugin** — Required. Client bundles transitively import `node:async_hooks`, `react-dom/server`, etc. Without stubs, build crashes.
|
|
119
|
+
2. **resolve.dedupe** — Required. Without it, multiple React instances cause "Invalid hook call" errors.
|
|
120
|
+
3. **process.env.DECO_SITE_NAME via define** — Must be injected at build time, not read at runtime.
|
|
121
|
+
4. **React Compiler** — `babel-plugin-react-compiler` with target 19 for automatic memoization.
|
|
122
|
+
5. **esbuild.jsx** — Must be `"automatic"` with `jsxImportSource: "react"` for proper JSX transform.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Worker Entry Templates
|
|
2
|
+
|
|
3
|
+
## src/server.ts
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
// CRITICAL: import "./setup" MUST be the first import.
|
|
7
|
+
// Without it, server functions in Vite split modules have empty state
|
|
8
|
+
// (blocks, registry, commerce loaders) causing 404 on client-side navigation.
|
|
9
|
+
import "./setup";
|
|
10
|
+
import { createStartHandler, defaultStreamHandler } from "@tanstack/react-start/server";
|
|
11
|
+
|
|
12
|
+
export default createStartHandler(defaultStreamHandler);
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## src/worker-entry.ts
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
// CRITICAL: import "./setup" MUST be the first import.
|
|
19
|
+
import "./setup";
|
|
20
|
+
import handler, { createServerEntry } from "@tanstack/react-start/server-entry";
|
|
21
|
+
import { createDecoWorkerEntry } from "@decocms/start/sdk/workerEntry";
|
|
22
|
+
import {
|
|
23
|
+
handleMeta,
|
|
24
|
+
handleDecofileRead,
|
|
25
|
+
handleDecofileReload,
|
|
26
|
+
handleRender,
|
|
27
|
+
corsHeaders,
|
|
28
|
+
} from "@decocms/start/admin";
|
|
29
|
+
// Only if using VTEX:
|
|
30
|
+
import { shouldProxyToVtex, proxyToVtex } from "@decocms/apps/vtex/utils/proxy";
|
|
31
|
+
|
|
32
|
+
const serverEntry = createServerEntry({
|
|
33
|
+
async fetch(request) {
|
|
34
|
+
return await handler.fetch(request);
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export default createDecoWorkerEntry(serverEntry, {
|
|
39
|
+
admin: {
|
|
40
|
+
handleMeta,
|
|
41
|
+
handleDecofileRead,
|
|
42
|
+
handleDecofileReload,
|
|
43
|
+
handleRender,
|
|
44
|
+
corsHeaders,
|
|
45
|
+
},
|
|
46
|
+
// VTEX proxy — routes like /api/*, /checkout/*, /arquivos/* go to VTEX
|
|
47
|
+
proxyHandler: (request, url) => {
|
|
48
|
+
if (shouldProxyToVtex(url.pathname)) {
|
|
49
|
+
return proxyToVtex(request);
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Key Rules
|
|
57
|
+
|
|
58
|
+
1. **`import "./setup"` is ALWAYS the first line** — both files. This registers sections, loaders, blocks, and commerce config before any server function executes.
|
|
59
|
+
2. **Admin handlers go in `createDecoWorkerEntry`** — NOT inside `createServerEntry`. TanStack Start's build strips custom fetch logic from `createServerEntry` in production.
|
|
60
|
+
3. **Proxy handler** — Optional. Only needed for platforms (VTEX, Shopify) that require server-side proxying.
|
|
61
|
+
4. **Request flow**: `createDecoWorkerEntry` → admin routes (first) → cache check → proxy check → `serverEntry.fetch()` (TanStack Start).
|
|
62
|
+
|
|
63
|
+
## Why `import "./setup"` Must Be First
|
|
64
|
+
|
|
65
|
+
TanStack Start compiles `createServerFn()` calls into "split modules" — separate Vite module instances. Module-level state (blockData, commerceLoaders, sectionRegistry) initialized in `setup.ts` only exists in the original module instance. Without importing setup first, these split modules execute with empty state.
|
|
66
|
+
|
|
67
|
+
The fix in `@decocms/start` uses `globalThis.__deco` to share state across all module instances. But `setup.ts` must run BEFORE any server function is called — which means it must be imported before `createStartHandler` or `createServerEntry`.
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deco-typescript-fixes
|
|
3
|
+
description: Strategies and patterns for fixing TypeScript errors in deco.cx storefronts, especially after migrations or dependency updates.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Deco TypeScript Fixes
|
|
7
|
+
|
|
8
|
+
This skill provides strategies for systematically fixing TypeScript errors in deco.cx storefronts. It's especially useful after:
|
|
9
|
+
- Migrating from forked apps to official `deco-cx/apps`
|
|
10
|
+
- Updating `@deco/deco` or `@deco/dev` versions
|
|
11
|
+
- Adding stricter TypeScript settings
|
|
12
|
+
|
|
13
|
+
## When to Use This Skill
|
|
14
|
+
|
|
15
|
+
- User asks to "fix all type errors" or "make deno check pass"
|
|
16
|
+
- After a migration that introduces many TypeScript errors
|
|
17
|
+
- When enabling stricter type checking in a deco project
|
|
18
|
+
|
|
19
|
+
## Critical: Use Fast Type Checker
|
|
20
|
+
|
|
21
|
+
Standard `deno check` takes 30-60+ seconds. With 200+ errors, iterating is painful.
|
|
22
|
+
|
|
23
|
+
**Always use the fast TSGo checker (Deno 2.1+, ideally 2.6+):**
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# FAST (~3-5s) - ALWAYS use this
|
|
27
|
+
deno check --unstable-tsgo --allow-import main.ts
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
1. Run `deno check --unstable-tsgo --allow-import main.ts` to get the full error list
|
|
33
|
+
2. Count errors: `deno check --unstable-tsgo --allow-import main.ts 2>&1 | grep -c "error:"`
|
|
34
|
+
3. Categorize errors (see Common Error Categories below)
|
|
35
|
+
4. Fix in batches by category, committing after each batch
|
|
36
|
+
5. Repeat until zero errors
|
|
37
|
+
|
|
38
|
+
## Files in This Skill
|
|
39
|
+
|
|
40
|
+
| File | Purpose |
|
|
41
|
+
|------|---------|
|
|
42
|
+
| `SKILL.md` | This overview and quick reference |
|
|
43
|
+
| `common-fixes.md` | Detailed patterns and code examples |
|
|
44
|
+
| `strategy.md` | The incremental fixing strategy |
|
|
45
|
+
|
|
46
|
+
## Common Error Categories
|
|
47
|
+
|
|
48
|
+
### 1. Missing Props Exports (Deco Compatibility)
|
|
49
|
+
|
|
50
|
+
**Symptom**: Deco admin can't load the component/section properly
|
|
51
|
+
|
|
52
|
+
**Pattern**: All components used as deco blocks need an exported `Props` type/interface
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
// BEFORE - Props not exported
|
|
56
|
+
interface Props {
|
|
57
|
+
title: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// AFTER - Export the Props
|
|
61
|
+
export interface Props {
|
|
62
|
+
title: string;
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 2. Global Type Declarations (Third-Party Scripts)
|
|
67
|
+
|
|
68
|
+
**Symptom**: `Cannot find name 'AnalyticsQueue'` or similar for injected globals
|
|
69
|
+
|
|
70
|
+
**Pattern**: Declare globals in `types/global.d.ts`
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// types/global.d.ts
|
|
74
|
+
declare global {
|
|
75
|
+
// deno-lint-ignore no-var
|
|
76
|
+
var AnalyticsQueue: AnalyticsCommand[];
|
|
77
|
+
// deno-lint-ignore no-var
|
|
78
|
+
var dataLayer: unknown[];
|
|
79
|
+
// deno-lint-ignore no-var
|
|
80
|
+
var thirdPartyTracker: TrackerFn;
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 3. Possibly Undefined Values
|
|
85
|
+
|
|
86
|
+
**Symptom**: `Object is possibly 'undefined'`
|
|
87
|
+
|
|
88
|
+
**Pattern**: Use optional chaining or nullish coalescing
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
// BEFORE
|
|
92
|
+
const name = product.name.toLowerCase();
|
|
93
|
+
|
|
94
|
+
// AFTER - optional chaining + fallback
|
|
95
|
+
const name = product?.name?.toLowerCase() ?? "";
|
|
96
|
+
|
|
97
|
+
// AFTER - nullish coalescing for defaults
|
|
98
|
+
const quantity = item.quantity ?? 1;
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 4. External API Type Mismatches
|
|
102
|
+
|
|
103
|
+
**Symptom**: VTEX/external API returns different shape than expected types
|
|
104
|
+
|
|
105
|
+
**Pattern**: Create custom types for API responses, use type assertions with comments
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
// Create specific types for GraphQL responses
|
|
109
|
+
// types/myorders.ts
|
|
110
|
+
export interface LogisticsInfo {
|
|
111
|
+
deliveryChannel?: string;
|
|
112
|
+
shippingEstimateDate?: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Use type assertion when SDK types don't match reality
|
|
116
|
+
const order = data as unknown as VtexOrderData;
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### 5. Platform Import Cleanup
|
|
120
|
+
|
|
121
|
+
**Symptom**: Imports from removed platforms (Linx, Wake, etc.) fail
|
|
122
|
+
|
|
123
|
+
**Pattern**: Search and remove unused platform code entirely
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# Find all platform-specific files
|
|
127
|
+
find . -name "*linx*" -o -name "*wake*" -o -name "*vnda*"
|
|
128
|
+
|
|
129
|
+
# Remove them if not using those platforms
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### 6. Optional Props Without Defaults
|
|
133
|
+
|
|
134
|
+
**Symptom**: `Type 'undefined' is not assignable to type 'string'`
|
|
135
|
+
|
|
136
|
+
**Pattern**: Make props explicitly optional or provide defaults
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
// BEFORE
|
|
140
|
+
interface Props {
|
|
141
|
+
href: string;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// AFTER - make optional with fallback in usage
|
|
145
|
+
export interface Props {
|
|
146
|
+
href?: string;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// In component:
|
|
150
|
+
const link = href ?? "#";
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Strategy Summary
|
|
154
|
+
|
|
155
|
+
1. **Batch by category** - Fix all "possibly undefined" errors together, all "Props exports" together
|
|
156
|
+
2. **Commit frequently** - Small commits let you track progress and rollback if needed
|
|
157
|
+
3. **Document type assertions** - When using `as unknown as X`, add a comment explaining why
|
|
158
|
+
4. **Create custom types** - Better to have explicit custom types than to silence errors
|
|
159
|
+
5. **Check deco admin** - After fixes, verify blocks still load in the deco admin
|
|
160
|
+
|
|
161
|
+
## Related Commands
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
# Fast type check (use this for iteration)
|
|
165
|
+
deno check --unstable-tsgo --allow-import main.ts
|
|
166
|
+
|
|
167
|
+
# Count errors
|
|
168
|
+
deno check --unstable-tsgo --allow-import main.ts 2>&1 | grep -c "error:"
|
|
169
|
+
|
|
170
|
+
# Find errors by category
|
|
171
|
+
deno check --unstable-tsgo --allow-import main.ts 2>&1 | grep "possibly 'undefined'"
|
|
172
|
+
deno check --unstable-tsgo --allow-import main.ts 2>&1 | grep "Cannot find name"
|
|
173
|
+
deno check --unstable-tsgo --allow-import main.ts 2>&1 | grep "not assignable"
|
|
174
|
+
|
|
175
|
+
# Find files with most errors
|
|
176
|
+
deno check --unstable-tsgo --allow-import main.ts 2>&1 | grep "error:" | \
|
|
177
|
+
sed 's/:.*//g' | sort | uniq -c | sort -rn | head -20
|
|
178
|
+
```
|