Skip to content

Commit f003798

Browse files
committed
chord: changing integration strategy
1 parent 2a92d6d commit f003798

File tree

22 files changed

+301
-207
lines changed

22 files changed

+301
-207
lines changed

src/add-ons.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,26 +35,10 @@ export type AddOn = {
3535
description: string
3636
link: string
3737
templates: Array<string>
38-
main?: Array<{
39-
imports: Array<string>
40-
initialize: Array<string>
41-
providers: Array<{
42-
open: string
43-
close: string
44-
}>
45-
}>
46-
layout?: {
47-
imports: Array<string>
48-
jsx: string
49-
}
5038
routes: Array<{
5139
url: string
5240
name: string
5341
}>
54-
userUi?: {
55-
import: string
56-
jsx: string
57-
}
5842
directory: string
5943
packageAdditions: {
6044
dependencies?: Record<string, string>

src/create-app.ts

Lines changed: 105 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ function createCopyFiles(targetDir: string) {
4141
}
4242
}
4343

44+
function jsSafeName(name: string) {
45+
return name
46+
.split(/[^a-zA-Z0-9]/)
47+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
48+
.join('')
49+
}
50+
4451
function createTemplateFile(
4552
projectName: string,
4653
options: Required<Options>,
@@ -73,7 +80,14 @@ function createTemplateFile(
7380
}
7481

7582
const template = await readFile(resolve(templateDir, file), 'utf-8')
76-
let content = render(template, templateValues)
83+
let content = ''
84+
try {
85+
content = render(template, templateValues)
86+
} catch (error) {
87+
console.error(chalk.red(`EJS error in file ${file}`))
88+
console.error(error)
89+
process.exit(1)
90+
}
7791
const target = targetFileName ?? file.replace('.ejs', '')
7892

7993
if (target.endsWith('.ts') || target.endsWith('.tsx')) {
@@ -300,33 +314,6 @@ export async function createApp(options: Required<Options>) {
300314

301315
copyFiles(templateDirBase, ['./src/logo.svg'])
302316

303-
// Setup the app component. There are four variations, typescript/javascript and tailwind/non-tailwind.
304-
if (options.mode === FILE_ROUTER) {
305-
await templateFile(
306-
templateDirRouter,
307-
'./src/routes/__root.tsx.ejs',
308-
'./src/routes/__root.tsx',
309-
)
310-
await templateFile(
311-
templateDirBase,
312-
'./src/App.tsx.ejs',
313-
'./src/routes/index.tsx',
314-
)
315-
} else {
316-
await templateFile(
317-
templateDirBase,
318-
'./src/App.tsx.ejs',
319-
options.typescript ? undefined : './src/App.jsx',
320-
)
321-
if (options.framework === 'react') {
322-
await templateFile(
323-
templateDirBase,
324-
'./src/App.test.tsx.ejs',
325-
options.typescript ? undefined : './src/App.test.jsx',
326-
)
327-
}
328-
}
329-
330317
// Setup the main, reportWebVitals and index.html files
331318
if (!isAddOnEnabled('start') && options.framework === 'react') {
332319
if (options.typescript) {
@@ -410,19 +397,70 @@ export async function createApp(options: Required<Options>) {
410397
}
411398
}
412399

400+
const integrations: Array<{
401+
type: 'layout' | 'provider' | 'header-user'
402+
name: string
403+
path: string
404+
}> = []
405+
if (existsSync(resolve(targetDir, 'src/integrations'))) {
406+
for (const integration of readdirSync(
407+
resolve(targetDir, 'src/integrations'),
408+
)) {
409+
const integrationName = jsSafeName(integration)
410+
if (
411+
existsSync(
412+
resolve(targetDir, 'src/integrations', integration, 'layout.tsx'),
413+
)
414+
) {
415+
integrations.push({
416+
type: 'layout',
417+
name: `${integrationName}Layout`,
418+
path: `integrations/${integration}/layout`,
419+
})
420+
}
421+
if (
422+
existsSync(
423+
resolve(targetDir, 'src/integrations', integration, 'provider.tsx'),
424+
)
425+
) {
426+
integrations.push({
427+
type: 'provider',
428+
name: `${integrationName}Provider`,
429+
path: `integrations/${integration}/provider`,
430+
})
431+
}
432+
if (
433+
existsSync(
434+
resolve(
435+
targetDir,
436+
'src/integrations',
437+
integration,
438+
'header-user.tsx',
439+
),
440+
)
441+
) {
442+
integrations.push({
443+
type: 'header-user',
444+
name: `${integrationName}Header`,
445+
path: `integrations/${integration}/header-user`,
446+
})
447+
}
448+
}
449+
}
450+
451+
console.log(integrations)
452+
413453
const routes: Array<{
414454
path: string
415455
name: string
416456
}> = []
417457
if (existsSync(resolve(targetDir, 'src/routes'))) {
418458
for (const file of readdirSync(resolve(targetDir, 'src/routes'))) {
419459
const name = file.replace(/\.tsx?|\.jsx?/, '')
460+
const safeRouteName = jsSafeName(name)
420461
routes.push({
421462
path: `./routes/${name}`,
422-
name: name
423-
.split('.')
424-
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
425-
.join(''),
463+
name: safeRouteName,
426464
})
427465
}
428466
}
@@ -436,6 +474,7 @@ export async function createApp(options: Required<Options>) {
436474
'./src/main.tsx',
437475
{
438476
routes,
477+
integrations,
439478
},
440479
)
441480
} else {
@@ -445,16 +484,50 @@ export async function createApp(options: Required<Options>) {
445484
'./src/main.jsx',
446485
{
447486
routes,
487+
integrations,
448488
},
449489
)
450490
}
451491
}
452492

493+
// Setup the app component. There are four variations, typescript/javascript and tailwind/non-tailwind.
494+
if (options.mode === FILE_ROUTER) {
495+
await templateFile(
496+
templateDirRouter,
497+
'./src/routes/__root.tsx.ejs',
498+
'./src/routes/__root.tsx',
499+
{
500+
integrations,
501+
},
502+
)
503+
await templateFile(
504+
templateDirBase,
505+
'./src/App.tsx.ejs',
506+
'./src/routes/index.tsx',
507+
)
508+
} else {
509+
await templateFile(
510+
templateDirBase,
511+
'./src/App.tsx.ejs',
512+
options.typescript ? undefined : './src/App.jsx',
513+
)
514+
if (options.framework === 'react') {
515+
await templateFile(
516+
templateDirBase,
517+
'./src/App.test.tsx.ejs',
518+
options.typescript ? undefined : './src/App.test.jsx',
519+
)
520+
}
521+
}
522+
453523
if (routes.length > 0) {
454524
await templateFile(
455525
templateDirBase,
456526
'./src/components/Header.tsx.ejs',
457527
'./src/components/Header.tsx',
528+
{
529+
integrations,
530+
},
458531
)
459532
}
460533

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import {
2+
SignedIn,
3+
SignInButton,
4+
SignedOut,
5+
UserButton,
6+
} from '@clerk/clerk-react'
7+
8+
export default function HeaderUser() {
9+
return (
10+
<>
11+
<SignedIn>
12+
<UserButton />
13+
</SignedIn>
14+
<SignedOut>
15+
<SignInButton />
16+
</SignedOut>
17+
</>
18+
)
19+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { ClerkProvider } from '@clerk/clerk-react'
2+
3+
const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY
4+
if (!PUBLISHABLE_KEY) {
5+
throw new Error('Add your Clerk Publishable Key to the .env.local file')
6+
}
7+
8+
export default function AppClerkProvider({
9+
children,
10+
}: {
11+
children: React.ReactNode
12+
}) {
13+
return (
14+
<ClerkProvider publishableKey={PUBLISHABLE_KEY} afterSignOutUrl="/">
15+
{children}
16+
</ClerkProvider>
17+
)
18+
}

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

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,6 @@
44
"phase": "add-on",
55
"templates": ["file-router"],
66
"link": "https://clerk.com",
7-
"main": {
8-
"imports": ["import { ClerkProvider } from '@clerk/clerk-react'"],
9-
"initialize": [
10-
"const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY\nif (!PUBLISHABLE_KEY) {\n throw new Error('Add your Clerk Publishable Key to the .env.local file');\n}"
11-
],
12-
"providers": [
13-
{
14-
"open": "<ClerkProvider publishableKey={PUBLISHABLE_KEY} afterSignOutUrl=\"/\">",
15-
"close": "</ClerkProvider>"
16-
}
17-
]
18-
},
19-
"userUi": {
20-
"import": "import { SignedIn, SignInButton, SignedOut, UserButton } from '@clerk/clerk-react'",
21-
"jsx": "<SignedIn><UserButton /></SignedIn><SignedOut><SignInButton /></SignedOut>"
22-
},
237
"routes": [
248
{
259
"url": "/demo/clerk",
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { ConvexProvider } from 'convex/react'
2+
import { ConvexQueryClient } from '@convex-dev/react-query'
3+
4+
const CONVEX_URL = (import.meta as any).env.VITE_CONVEX_URL
5+
if (!CONVEX_URL) {
6+
console.error('missing envar CONVEX_URL')
7+
}
8+
const convexQueryClient = new ConvexQueryClient(CONVEX_URL)
9+
10+
export default function AppConvexProvider({
11+
children,
12+
}: {
13+
children: React.ReactNode
14+
}) {
15+
return (
16+
<ConvexProvider client={convexQueryClient.convexClient}>
17+
{children}
18+
</ConvexProvider>
19+
)
20+
}

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

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,6 @@
44
"link": "https://convex.dev",
55
"phase": "add-on",
66
"templates": ["file-router"],
7-
"main": {
8-
"imports": [
9-
"import { ConvexProvider } from 'convex/react'",
10-
"import { ConvexQueryClient } from '@convex-dev/react-query'"
11-
],
12-
"initialize": [
13-
"const CONVEX_URL = (import.meta as any).env.VITE_CONVEX_URL!\nif (!CONVEX_URL) {\n console.error(\"missing envar CONVEX_URL\");\n}\nconst convexQueryClient = new ConvexQueryClient(CONVEX_URL);"
14-
],
15-
"providers": [
16-
{
17-
"open": "<ConvexProvider client={convexQueryClient.convexClient}>",
18-
"close": "</ConvexProvider>"
19-
}
20-
]
21-
},
227
"routes": [
238
{
249
"url": "/demo/convex",

templates/react/add-on/store/assets/src/routes/demo.store.page1.tsx.ejs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { useStore } from '@tanstack/react-store'
33

44
import { store } from '../lib/demo-store'
55
<% if (codeRouter) { %>
6-
import type { RootRoute } from '@tanstack/react-router'
6+
import type { RootRoute } from '@tanstack/react-router'
77
<% } else { %>
88
export const Route = createFileRoute('/demo/store/page1')({
99
component: StorePage1,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
2+
3+
export default function LayoutAddition() {
4+
return <ReactQueryDevtools buttonPosition="bottom-right" />
5+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
2+
3+
const queryClient = new QueryClient()
4+
5+
export default function Provider({ children }: { children: React.ReactNode }) {
6+
return (
7+
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
8+
)
9+
}

0 commit comments

Comments
 (0)