Skip to content

Commit 4acd8c0

Browse files
committed
feat: module federation, new ai example
1 parent 5f29228 commit 4acd8c0

33 files changed

+154
-136
lines changed

src/add-ons.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export type AddOn = {
3434
name: string
3535
description: string
3636
link: string
37+
templates: Array<string>
3738
main?: Array<{
3839
imports: Array<string>
3940
initialize: Array<string>
@@ -78,6 +79,7 @@ function isDirectory(path: string): boolean {
7879

7980
export async function getAllAddOns(
8081
framework: Framework,
82+
template: string,
8183
): Promise<Array<AddOn>> {
8284
const addOns: Array<AddOn> = []
8385

@@ -95,6 +97,11 @@ export async function getAllAddOns(
9597
)) {
9698
const filePath = resolve(addOnsBase, dir, 'info.json')
9799
const fileContent = await readFile(filePath, 'utf-8')
100+
const info = JSON.parse(fileContent)
101+
102+
if (!info.templates.includes(template)) {
103+
continue
104+
}
98105

99106
let packageAdditions: Record<string, string> = {}
100107
if (existsSync(resolve(addOnsBase, dir, 'package.json'))) {
@@ -109,9 +116,9 @@ export async function getAllAddOns(
109116
}
110117

111118
addOns.push({
119+
...info,
112120
id: dir,
113121
type,
114-
...JSON.parse(fileContent),
115122
directory: resolve(addOnsBase, dir),
116123
packageAdditions,
117124
readme,
@@ -125,11 +132,12 @@ export async function getAllAddOns(
125132
// Turn the list of chosen add-on IDs into a final list of add-ons by resolving dependencies
126133
export async function finalizeAddOns(
127134
framework: Framework,
135+
template: string,
128136
chosenAddOnIDs: Array<string>,
129137
): Promise<Array<AddOn>> {
130138
const finalAddOnIDs = new Set(chosenAddOnIDs)
131139

132-
const addOns = await getAllAddOns(framework)
140+
const addOns = await getAllAddOns(framework, template)
133141

134142
for (const addOnID of finalAddOnIDs) {
135143
const addOn = addOns.find((a) => a.id === addOnID)

src/options.ts

+10-13
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,10 @@ export async function promptForOptions(
203203
}
204204

205205
// Select any add-ons
206-
const allAddOns = await getAllAddOns(options.framework)
206+
const allAddOns = await getAllAddOns(options.framework, options.mode)
207207
const addOns = allAddOns.filter((addOn) => addOn.type === 'add-on')
208208
let selectedAddOns: Array<string> = []
209-
if (options.mode === FILE_ROUTER && cliOptions.addOns && addOns.length > 0) {
209+
if (options.typescript && cliOptions.addOns && addOns.length > 0) {
210210
const value = await multiselect({
211211
message: 'What add-ons would you like for your project:',
212212
options: addOns.map((addOn) => ({
@@ -217,21 +217,17 @@ export async function promptForOptions(
217217
required: false,
218218
})
219219

220-
if (isCancel(selectedAddOns)) {
220+
if (isCancel(value)) {
221221
cancel('Operation cancelled.')
222222
process.exit(0)
223223
}
224-
selectedAddOns = value as Array<string>
224+
selectedAddOns = value
225225
}
226226

227227
// Select any examples
228228
const examples = allAddOns.filter((addOn) => addOn.type === 'example')
229229
let selectedExamples: Array<string> = []
230-
if (
231-
options.mode === FILE_ROUTER &&
232-
cliOptions.addOns &&
233-
examples.length > 0
234-
) {
230+
if (options.typescript && cliOptions.addOns && examples.length > 0) {
235231
const value = await multiselect({
236232
message: 'Would you like any examples?',
237233
options: examples.map((addOn) => ({
@@ -250,10 +246,11 @@ export async function promptForOptions(
250246
}
251247

252248
if (selectedAddOns.length > 0 || selectedExamples.length > 0) {
253-
options.chosenAddOns = await finalizeAddOns(options.framework, [
254-
...selectedAddOns,
255-
...selectedExamples,
256-
])
249+
options.chosenAddOns = await finalizeAddOns(
250+
options.framework,
251+
options.mode,
252+
[...selectedAddOns, ...selectedExamples],
253+
)
257254
options.tailwind = true
258255
} else {
259256
options.chosenAddOns = []

templates/react/add-on/clerk/info.json

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"name": "Clerk",
33
"description": "Add Clerk authentication to your application.",
44
"phase": "add-on",
5+
"templates": ["file-router"],
56
"link": "https://clerk.com",
67
"main": {
78
"imports": ["import { ClerkProvider } from '@clerk/clerk-react'"],

templates/react/add-on/convex/info.json

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"description": "Add the Convex database to your application.",
44
"link": "https://convex.dev",
55
"phase": "add-on",
6+
"templates": ["file-router"],
67
"main": {
78
"imports": [
89
"import { ConvexProvider } from 'convex/react'",

templates/react/add-on/form/info.json

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"name": "Form",
33
"description": "TansStack Form",
44
"phase": "add-on",
5+
"templates": ["file-router"],
56
"link": "https://tanstack.com/form/latest",
67
"routes": [
78
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import packageJSON from './package.json'
2+
3+
function remoteConfig(name, url) {
4+
return {
5+
type: 'module',
6+
name,
7+
entry: url,
8+
entryGlobalName: 'remote',
9+
shareScope: 'default',
10+
}
11+
}
12+
13+
export default {
14+
filename: 'remoteEntry.js',
15+
name: '<%= projectName %>',
16+
exposes: {
17+
'./DemoMfComponent': './src/demo-mf-component.tsx',
18+
'./DemoMfSelfContained': './src/demo-mf-self-contained.tsx',
19+
},
20+
remotes: {},
21+
shared: {
22+
react: {
23+
singleton: true,
24+
requiredVersion: packageJSON.dependencies.react,
25+
},
26+
'react-dom': {
27+
singleton: true,
28+
requiredVersion: packageJSON.dependencies['react-dom'],
29+
},
30+
},
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function DemoMfComponent() {
2+
return <div>Demo Mf Component</div>
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React from 'react'
2+
import ReactDOM from 'react-dom/client'
3+
4+
function App() {
5+
return <div>Hello from self-contained module federation</div>
6+
}
7+
8+
export function DemoMfSelfContained(rootElement: HTMLElement) {
9+
const root = ReactDOM.createRoot(rootElement)
10+
root.render(<App />)
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "Module Federation",
3+
"description": "Module Federation",
4+
"phase": "add-on",
5+
"templates": ["code-router"],
6+
"link": "https://module-federation.io/"
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"dependencies": {
3+
"@module-federation/vite": "^1.1.9"
4+
}
5+
}

templates/react/add-on/netlify/info.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
"name": "Netlify",
33
"description": "Netlify deployment setup",
44
"link": "https://docs.netlify.com",
5-
"phase": "add-on"
5+
"phase": "add-on",
6+
"templates": ["file-router", "code-router"]
67
}

templates/react/add-on/sentry/info.json

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"phase": "setup",
44
"description": "Add Sentry for error monitoring and crash reporting (requires Start).",
55
"link": "https://sentry.com/",
6+
"templates": ["file-router"],
67
"routes": [
78
{
89
"url": "/demo/sentry/bad-server-func",

templates/react/add-on/shadcn/info.json

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"name": "Shadcn",
33
"description": "Add Shadcn UI to your application.",
44
"phase": "add-on",
5+
"templates": ["file-router", "code-router"],
56
"link": "https://ui.shadcn.com/",
67
"command": {
78
"command": "npx",

templates/react/add-on/start/info.json

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"phase": "setup",
44
"description": "Add TanStack Start for SSR, API endpoints, and more.",
55
"link": "https://tanstack.com/start/latest",
6+
"templates": ["file-router"],
67
"warning": "TanStack Start is not yet at 1.0 and may change significantly or not be compatible with other add-ons.",
78
"routes": [
89
{

templates/react/add-on/store/info.json

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"description": "Add TanStack Store to your application.",
44
"phase": "add-on",
55
"link": "https://tanstack.com/store/latest",
6+
"templates": ["file-router"],
67
"routes": [
78
{
89
"url": "/demo/store/page1",

templates/react/add-on/tanstack-query/info.json

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"name": "TanStack Query",
33
"description": "Integrate TanStack Query into your application.",
44
"phase": "add-on",
5+
"templates": ["file-router"],
56
"link": "https://tanstack.com/query/latest",
67
"main": {
78
"imports": [

templates/react/base/vite.config.js.ejs

+5-4
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ import { defineConfig } from "vite";
22
import viteReact from "@vitejs/plugin-react";<% if (tailwind) { %>
33
import tailwindcss from "@tailwindcss/vite";
44
<% } %><%if (fileRouter) { %>
5-
import { TanStackRouterVite } from "@tanstack/router-plugin/vite";
6-
<% } %><% if (addOnEnabled.shadcn) { %>
7-
import { resolve } from "path";
5+
import { TanStackRouterVite } from "@tanstack/router-plugin/vite";<% } %><% if (addOnEnabled['module-federation']) { %>
6+
import {federation} from "@module-federation/vite";<% } %><% if (addOnEnabled.shadcn) { %>
7+
import { resolve } from "path";<% } %><% if (addOnEnabled['module-federation']) { %>
8+
import federationConfig from "./module-federation.config.js";
89
<% } %>
910

1011
// https://vitejs.dev/config/
1112
export default defineConfig({
12-
plugins: [<% if(fileRouter) { %>TanStackRouterVite(), <% } %>viteReact()<% if (tailwind) { %>, tailwindcss()<% } %>],
13+
plugins: [<% if(fileRouter) { %>TanStackRouterVite(), <% } %>viteReact()<% if (tailwind) { %>, tailwindcss()<% } %><% if (addOnEnabled['module-federation']) { %>, federation(federationConfig)<% } %>],
1314
test: {
1415
globals: true,
1516
environment: "jsdom",

templates/react/example/ai-chat/assets/.env.local.append

-2
This file was deleted.

templates/react/example/ai-chat/assets/src/routes/example.ai-chat.tsx.ejs

-81
This file was deleted.

templates/react/example/ai-chat/info.json

-27
This file was deleted.

templates/react/example/ai-chat/package.json

-1
This file was deleted.

templates/react/example/tanchat/info.json

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"name": "TanStack Chat",
33
"description": "A chat example that uses TanStack Start and TanStack Store. Features chat with Antrhopic Sonnet, chat history and custom prompts.",
44
"phase": "example",
5+
"templates": ["file-router"],
56
"link": "",
67
"routes": [
78
{

templates/solid/add-on/form/info.json

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"description": "TansStack Form",
44
"phase": "add-on",
55
"link": "https://tanstack.com/form/latest",
6+
"templates": ["file-router"],
67
"routes": [
78
{
89
"url": "/demo/form",

0 commit comments

Comments
 (0)