@tanstack/create 0.60.0 → 0.61.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/CHANGELOG.md +12 -0
- package/dist/create-app.js +7 -5
- package/dist/file-helpers.js +13 -1
- package/dist/frameworks/react/add-ons/ai/info.json +0 -5
- package/dist/frameworks/react/add-ons/ai/package.json +0 -1
- package/dist/frameworks/{solid/add-ons/better-auth/README.md → react/add-ons/better-auth/README.md.ejs} +2 -2
- package/dist/frameworks/react/add-ons/better-auth/assets/_dot_env.local.append.ejs +3 -0
- package/dist/frameworks/react/add-ons/better-auth/assets/src/integrations/better-auth/header-user.tsx +3 -1
- package/dist/frameworks/react/add-ons/better-auth/assets/src/routes/demo/better-auth.tsx +3 -1
- package/dist/frameworks/react/add-ons/convex/README.md.ejs +4 -0
- package/dist/frameworks/react/add-ons/drizzle/assets/src/routes/demo/{drizzle.tsx → drizzle.tsx.ejs} +3 -3
- package/dist/frameworks/react/add-ons/neon/assets/_dot_env.example.append +2 -2
- package/dist/frameworks/react/add-ons/neon/assets/neon-vite-plugin.ts +1 -1
- package/dist/frameworks/react/add-ons/neon/assets/src/db.ts +2 -2
- package/dist/frameworks/react/add-ons/posthog/README.md +9 -0
- package/dist/frameworks/react/add-ons/posthog/assets/_dot_env.local.append +4 -0
- package/dist/frameworks/react/add-ons/posthog/assets/src/integrations/posthog/provider.tsx +20 -0
- package/dist/frameworks/react/add-ons/posthog/assets/src/routes/demo/posthog.tsx +93 -0
- package/dist/frameworks/react/add-ons/posthog/files.json +5 -0
- package/dist/frameworks/react/add-ons/posthog/info.json +28 -0
- package/dist/frameworks/react/add-ons/posthog/package.json +6 -0
- package/dist/frameworks/react/add-ons/prisma/assets/src/routes/demo/{prisma.tsx → prisma.tsx.ejs} +3 -3
- package/dist/frameworks/react/add-ons/prisma/package.json.ejs +1 -1
- package/dist/frameworks/react/add-ons/sentry/package.json +1 -1
- package/dist/frameworks/react/add-ons/tanstack-query/info.json +1 -1
- package/dist/frameworks/react/hosts/nitro/info.json +1 -1
- package/dist/frameworks/react/hosts/railway/info.json +1 -1
- package/dist/frameworks/react/project/base/README.md.ejs +1 -1
- package/dist/frameworks/react/project/base/package.json +1 -1
- package/dist/frameworks/react/project/base/vite.config.ts.ejs +1 -1
- package/dist/frameworks/{react/add-ons/better-auth/README.md → solid/add-ons/better-auth/README.md.ejs} +2 -2
- package/dist/frameworks/solid/add-ons/better-auth/assets/_dot_env.local.append.ejs +3 -0
- package/dist/frameworks/solid/add-ons/better-auth/assets/src/integrations/better-auth/header-user.tsx +3 -1
- package/dist/frameworks/solid/add-ons/better-auth/assets/src/routes/demo.better-auth.tsx +3 -1
- package/dist/frameworks/solid/add-ons/convex/README.md.ejs +4 -0
- package/{src/frameworks/solid/add-ons/solid-ui/README.md → dist/frameworks/solid/add-ons/solid-ui/README.md.ejs} +1 -1
- package/dist/frameworks/solid/add-ons/solid-ui/info.json +1 -5
- package/dist/frameworks/solid/project/base/README.md.ejs +1 -1
- package/dist/frameworks.js +6 -0
- package/dist/package-manager.js +29 -0
- package/dist/template-file.js +8 -1
- package/dist/types/custom-add-ons/add-on.d.ts +2 -1
- package/dist/types/package-manager.d.ts +7 -0
- package/dist/types/types.d.ts +21 -15
- package/dist/types/utils.d.ts +2 -0
- package/dist/types.js +2 -0
- package/dist/utils.js +6 -0
- package/package.json +1 -1
- package/src/create-app.ts +9 -6
- package/src/file-helpers.ts +12 -1
- package/src/frameworks/react/add-ons/ai/info.json +0 -5
- package/src/frameworks/react/add-ons/ai/package.json +0 -1
- package/src/frameworks/react/add-ons/better-auth/{README.md → README.md.ejs} +2 -2
- package/src/frameworks/react/add-ons/better-auth/assets/_dot_env.local.append.ejs +3 -0
- package/src/frameworks/react/add-ons/better-auth/assets/src/integrations/better-auth/header-user.tsx +3 -1
- package/src/frameworks/react/add-ons/better-auth/assets/src/routes/demo/better-auth.tsx +3 -1
- package/src/frameworks/react/add-ons/convex/README.md.ejs +4 -0
- package/src/frameworks/react/add-ons/drizzle/assets/src/routes/demo/{drizzle.tsx → drizzle.tsx.ejs} +3 -3
- package/src/frameworks/react/add-ons/neon/assets/_dot_env.example.append +2 -2
- package/src/frameworks/react/add-ons/neon/assets/neon-vite-plugin.ts +1 -1
- package/src/frameworks/react/add-ons/neon/assets/src/db.ts +2 -2
- package/src/frameworks/react/add-ons/posthog/README.md +9 -0
- package/src/frameworks/react/add-ons/posthog/assets/_dot_env.local.append +4 -0
- package/src/frameworks/react/add-ons/posthog/assets/src/integrations/posthog/provider.tsx +20 -0
- package/src/frameworks/react/add-ons/posthog/assets/src/routes/demo/posthog.tsx +93 -0
- package/src/frameworks/react/add-ons/posthog/files.json +5 -0
- package/src/frameworks/react/add-ons/posthog/info.json +28 -0
- package/src/frameworks/react/add-ons/posthog/package.json +6 -0
- package/src/frameworks/react/add-ons/prisma/assets/src/routes/demo/{prisma.tsx → prisma.tsx.ejs} +3 -3
- package/src/frameworks/react/add-ons/prisma/package.json.ejs +1 -1
- package/src/frameworks/react/add-ons/sentry/package.json +1 -1
- package/src/frameworks/react/add-ons/tanstack-query/info.json +1 -1
- package/src/frameworks/react/hosts/nitro/info.json +1 -1
- package/src/frameworks/react/hosts/railway/info.json +1 -1
- package/src/frameworks/react/project/base/README.md.ejs +1 -1
- package/src/frameworks/react/project/base/package.json +1 -1
- package/src/frameworks/react/project/base/vite.config.ts.ejs +1 -1
- package/src/frameworks/solid/add-ons/better-auth/{README.md → README.md.ejs} +2 -2
- package/src/frameworks/solid/add-ons/better-auth/assets/_dot_env.local.append.ejs +3 -0
- package/src/frameworks/solid/add-ons/better-auth/assets/src/integrations/better-auth/header-user.tsx +3 -1
- package/src/frameworks/solid/add-ons/better-auth/assets/src/routes/demo.better-auth.tsx +3 -1
- package/src/frameworks/solid/add-ons/convex/README.md.ejs +4 -0
- package/{dist/frameworks/solid/add-ons/solid-ui/README.md → src/frameworks/solid/add-ons/solid-ui/README.md.ejs} +1 -1
- package/src/frameworks/solid/add-ons/solid-ui/info.json +1 -5
- package/src/frameworks/solid/project/base/README.md.ejs +1 -1
- package/src/frameworks.ts +8 -0
- package/src/package-manager.ts +37 -0
- package/src/template-file.ts +14 -0
- package/src/types.ts +2 -0
- package/src/utils.ts +8 -0
- package/tests/file-helper.test.ts +6 -0
- package/tests/package-manager.test.ts +159 -0
- package/tests/template-file.test.ts +13 -0
- package/dist/frameworks/react/add-ons/ai/assets/src/lib/ai-devtools.tsx +0 -3
- package/dist/frameworks/react/add-ons/better-auth/assets/_dot_env.local.append +0 -3
- package/dist/frameworks/react/add-ons/convex/README.md +0 -4
- package/dist/frameworks/solid/add-ons/better-auth/assets/_dot_env.local.append +0 -3
- package/dist/frameworks/solid/add-ons/convex/README.md +0 -4
- package/src/frameworks/react/add-ons/ai/assets/src/lib/ai-devtools.tsx +0 -3
- package/src/frameworks/react/add-ons/better-auth/assets/_dot_env.local.append +0 -3
- package/src/frameworks/react/add-ons/convex/README.md +0 -4
- package/src/frameworks/solid/add-ons/better-auth/assets/_dot_env.local.append +0 -3
- package/src/frameworks/solid/add-ons/convex/README.md +0 -4
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { createFileRoute, Link } from '@tanstack/react-router'
|
|
2
|
+
import { usePostHog } from '@posthog/react'
|
|
3
|
+
import { useState } from 'react'
|
|
4
|
+
|
|
5
|
+
export const Route = createFileRoute('/demo/posthog')({
|
|
6
|
+
component: PostHogDemo,
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
function PostHogDemo() {
|
|
10
|
+
const posthog = usePostHog()
|
|
11
|
+
const [eventCount, setEventCount] = useState(0)
|
|
12
|
+
const posthogKey = import.meta.env.VITE_POSTHOG_KEY
|
|
13
|
+
const isConfigured = Boolean(posthogKey) && posthogKey !== 'phc_xxx'
|
|
14
|
+
|
|
15
|
+
const trackEvent = (
|
|
16
|
+
eventName: string,
|
|
17
|
+
properties?: Record<string, unknown>,
|
|
18
|
+
) => {
|
|
19
|
+
posthog.capture(eventName, properties)
|
|
20
|
+
setEventCount((c) => c + 1)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<div className="min-h-screen bg-gray-900 text-white p-8">
|
|
25
|
+
<div className="max-w-md mx-auto">
|
|
26
|
+
<h1 className="text-3xl font-bold mb-6">PostHog Demo</h1>
|
|
27
|
+
|
|
28
|
+
{!isConfigured && (
|
|
29
|
+
<div className="mb-4 p-4 bg-yellow-900/50 border border-yellow-600 rounded-lg">
|
|
30
|
+
<p className="text-yellow-200 text-sm">
|
|
31
|
+
<strong>Warning:</strong> VITE_POSTHOG_KEY is not configured.
|
|
32
|
+
Events won't be sent to PostHog. Add it to your{' '}
|
|
33
|
+
<code className="bg-yellow-900 px-1 rounded">.env</code> file.
|
|
34
|
+
</p>
|
|
35
|
+
</div>
|
|
36
|
+
)}
|
|
37
|
+
|
|
38
|
+
<div className="bg-gray-800 rounded-lg p-6">
|
|
39
|
+
<p className="text-gray-400 mb-4">
|
|
40
|
+
Click the button below to send events to PostHog. Check your PostHog
|
|
41
|
+
dashboard to see them appear in real-time.
|
|
42
|
+
</p>
|
|
43
|
+
|
|
44
|
+
<button
|
|
45
|
+
onClick={() => trackEvent('button_clicked', { button: 'demo' })}
|
|
46
|
+
className="w-full bg-cyan-600 hover:bg-cyan-700 px-4 py-3 rounded font-medium"
|
|
47
|
+
>
|
|
48
|
+
Track Click
|
|
49
|
+
</button>
|
|
50
|
+
|
|
51
|
+
{isConfigured && (
|
|
52
|
+
<div className="mt-6 p-4 bg-gray-700 rounded">
|
|
53
|
+
<p className="text-sm text-gray-400">Events sent this session:</p>
|
|
54
|
+
<p className="text-4xl font-bold text-cyan-400">{eventCount}</p>
|
|
55
|
+
</div>
|
|
56
|
+
)}
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<p className="mt-4 text-sm text-gray-400">
|
|
60
|
+
Open your{' '}
|
|
61
|
+
<a
|
|
62
|
+
href="https://app.posthog.com/events"
|
|
63
|
+
target="_blank"
|
|
64
|
+
rel="noopener noreferrer"
|
|
65
|
+
className="text-cyan-400 hover:text-cyan-300 underline"
|
|
66
|
+
>
|
|
67
|
+
PostHog Events
|
|
68
|
+
</a>{' '}
|
|
69
|
+
page to see these events appear.
|
|
70
|
+
</p>
|
|
71
|
+
|
|
72
|
+
<p className="mt-2 text-sm text-gray-400">
|
|
73
|
+
Learn more in the{' '}
|
|
74
|
+
<a
|
|
75
|
+
href="https://posthog.com/docs/libraries/react"
|
|
76
|
+
target="_blank"
|
|
77
|
+
rel="noopener noreferrer"
|
|
78
|
+
className="text-cyan-400 hover:text-cyan-300 underline"
|
|
79
|
+
>
|
|
80
|
+
PostHog React docs
|
|
81
|
+
</a>
|
|
82
|
+
.
|
|
83
|
+
</p>
|
|
84
|
+
|
|
85
|
+
<div className="mt-8">
|
|
86
|
+
<Link to="/" className="text-cyan-400 hover:text-cyan-300">
|
|
87
|
+
← Back to Home
|
|
88
|
+
</Link>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
)
|
|
93
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "PostHog",
|
|
3
|
+
"description": "Product analytics, session replay, and feature flags",
|
|
4
|
+
"phase": "add-on",
|
|
5
|
+
"modes": ["file-router"],
|
|
6
|
+
"type": "add-on",
|
|
7
|
+
"category": "analytics",
|
|
8
|
+
"color": "#1D4AFF",
|
|
9
|
+
"priority": 20,
|
|
10
|
+
"link": "https://posthog.com",
|
|
11
|
+
"tailwind": true,
|
|
12
|
+
"routes": [
|
|
13
|
+
{
|
|
14
|
+
"icon": "BarChart",
|
|
15
|
+
"url": "/demo/posthog",
|
|
16
|
+
"name": "PostHog",
|
|
17
|
+
"path": "src/routes/demo/posthog.tsx",
|
|
18
|
+
"jsName": "PostHogDemo"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"integrations": [
|
|
22
|
+
{
|
|
23
|
+
"type": "provider",
|
|
24
|
+
"jsName": "PostHogProvider",
|
|
25
|
+
"path": "src/integrations/posthog/provider.tsx"
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
package/src/frameworks/react/add-ons/prisma/assets/src/routes/demo/{prisma.tsx → prisma.tsx.ejs}
RENAMED
|
@@ -162,19 +162,19 @@ function DemoPrisma() {
|
|
|
162
162
|
<li>
|
|
163
163
|
Run:{' '}
|
|
164
164
|
<code className="px-2 py-1 rounded bg-black/30 text-purple-300">
|
|
165
|
-
|
|
165
|
+
<%- getPackageManagerExecuteScript('prisma', ['generate']) %>
|
|
166
166
|
</code>
|
|
167
167
|
</li>
|
|
168
168
|
<li>
|
|
169
169
|
Run:{' '}
|
|
170
170
|
<code className="px-2 py-1 rounded bg-black/30 text-purple-300">
|
|
171
|
-
|
|
171
|
+
<%- getPackageManagerExecuteScript('prisma', ['db', 'push']) %>
|
|
172
172
|
</code>
|
|
173
173
|
</li>
|
|
174
174
|
<li>
|
|
175
175
|
Optional:{' '}
|
|
176
176
|
<code className="px-2 py-1 rounded bg-black/30 text-purple-300">
|
|
177
|
-
|
|
177
|
+
<%- getPackageManagerExecuteScript('prisma', ['studio']) %>
|
|
178
178
|
</code>
|
|
179
179
|
</li>
|
|
180
180
|
</ol>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"tsx": "^4.20.6"
|
|
12
12
|
},
|
|
13
13
|
"scripts": {<% if (addOnOption.prisma.database === 'postgres') { %>
|
|
14
|
-
"post-cta-init": "
|
|
14
|
+
"post-cta-init": "<%- getPackageManagerExecuteScript('create-db@latest', ['--user-agent', 'tanstack/tsrouter']) %>",<% } %>
|
|
15
15
|
"db:generate": "dotenv -e .env.local -- prisma generate",
|
|
16
16
|
"db:push": "dotenv -e .env.local -- prisma db push",
|
|
17
17
|
"db:migrate": "dotenv -e .env.local -- prisma migrate dev",
|
|
@@ -52,7 +52,7 @@ This project uses [eslint](https://eslint.org/) and [prettier](https://prettier.
|
|
|
52
52
|
```
|
|
53
53
|
<% } %>
|
|
54
54
|
<% for(const addon of addOns.filter(addon => addon.readme)) { %>
|
|
55
|
-
<%- addon.readme %>
|
|
55
|
+
<%- addon.readmeIsEjs ? renderTemplate(addon.readme) : addon.readme %>
|
|
56
56
|
<% } %>
|
|
57
57
|
|
|
58
58
|
## Routing
|
|
@@ -6,7 +6,7 @@ import { paraglideVitePlugin } from "@inlang/paraglide-js"
|
|
|
6
6
|
import { tanstackStart } from '@tanstack/react-start/plugin/vite';
|
|
7
7
|
import viteReact from '@vitejs/plugin-react'
|
|
8
8
|
import viteTsConfigPaths from 'vite-tsconfig-paths'
|
|
9
|
-
import { fileURLToPath, URL } from 'url'
|
|
9
|
+
import { fileURLToPath, URL } from 'node:url'
|
|
10
10
|
import tailwindcss from "@tailwindcss/vite"
|
|
11
11
|
<% for(const integration of integrations.filter(i => i.type === 'vite-plugin')) { %><%- integrationImportContent(integration) %>
|
|
12
12
|
<% } %>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
1. Generate and set the `BETTER_AUTH_SECRET` environment variable in your `.env.local`:
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
|
|
6
|
+
<%- getPackageManagerExecuteScript('@better-auth/cli', ['secret']) %>
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
2. Visit the [Better Auth documentation](https://www.better-auth.com) to unlock the full potential of authentication in your app.
|
|
@@ -28,5 +28,5 @@ export const auth = betterAuth({
|
|
|
28
28
|
Then run migrations:
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
|
|
31
|
+
<%- getPackageManagerExecuteScript('@better-auth/cli', ['migrate']) %>
|
|
32
32
|
```
|
package/src/frameworks/solid/add-ons/better-auth/assets/src/integrations/better-auth/header-user.tsx
CHANGED
|
@@ -38,7 +38,9 @@ export default function BetterAuthHeader() {
|
|
|
38
38
|
{(image) => <img src={image()} alt="" class="h-8 w-8" />}
|
|
39
39
|
</Show>
|
|
40
40
|
<button
|
|
41
|
-
onClick={() =>
|
|
41
|
+
onClick={() => {
|
|
42
|
+
void authClient.signOut();
|
|
43
|
+
}}
|
|
42
44
|
class="flex-1 h-9 px-4 text-sm font-medium bg-white dark:bg-neutral-900 text-neutral-900 dark:text-neutral-50 border border-neutral-300 dark:border-neutral-700 hover:bg-neutral-50 dark:hover:bg-neutral-800 transition-colors"
|
|
43
45
|
>
|
|
44
46
|
Sign out
|
|
@@ -210,7 +210,9 @@ function BetterAuthDemo() {
|
|
|
210
210
|
</div>
|
|
211
211
|
|
|
212
212
|
<button
|
|
213
|
-
onClick={() =>
|
|
213
|
+
onClick={() => {
|
|
214
|
+
void authClient.signOut();
|
|
215
|
+
}}
|
|
214
216
|
class="w-full h-9 px-4 text-sm font-medium border border-neutral-300 dark:border-neutral-700 hover:bg-neutral-100 dark:hover:bg-neutral-800 transition-colors"
|
|
215
217
|
>
|
|
216
218
|
Sign out
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
## Setting up Convex
|
|
2
|
+
|
|
3
|
+
- Set the `VITE_CONVEX_URL` and `CONVEX_DEPLOYMENT` environment variables in your `.env.local`. (Or run `<%- getPackageManagerExecuteScript('convex', ['init']) %>` to set them automatically.)
|
|
4
|
+
- Run `<%- getPackageManagerExecuteScript('convex', ['dev']) %>` to start the Convex server.
|
|
@@ -5,5 +5,5 @@ This installation of Solid-UI follows the manual instructions but was modified t
|
|
|
5
5
|
To install the components, run the following command (this install button):
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
8
|
+
<%- getPackageManagerExecuteScript('solidui-cli@latest', ['add', 'button']) %>
|
|
9
9
|
```
|
|
@@ -31,7 +31,7 @@ If you prefer not to use Tailwind CSS:
|
|
|
31
31
|
4. Uninstall the packages: `<%= getPackageManagerAddScript('@tailwindcss/vite tailwindcss', true) %>`
|
|
32
32
|
|
|
33
33
|
<% for(const addon of addOns.filter(addon => addon.readme)) { %>
|
|
34
|
-
<%- addon.readme %>
|
|
34
|
+
<%- addon.readmeIsEjs ? renderTemplate(addon.readme) : addon.readme %>
|
|
35
35
|
<% } %>
|
|
36
36
|
|
|
37
37
|
## Routing
|
package/src/frameworks.ts
CHANGED
|
@@ -72,8 +72,15 @@ export function scanAddOnDirectories(addOnsDirectories: Array<string>) {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
let readme: string | undefined
|
|
75
|
+
let readmeIsEjs = false
|
|
75
76
|
if (existsSync(resolve(addOnsBase, dir, 'README.md'))) {
|
|
76
77
|
readme = readFileSync(resolve(addOnsBase, dir, 'README.md'), 'utf-8')
|
|
78
|
+
} else if (existsSync(resolve(addOnsBase, dir, 'README.md.ejs'))) {
|
|
79
|
+
readme = readFileSync(
|
|
80
|
+
resolve(addOnsBase, dir, 'README.md.ejs'),
|
|
81
|
+
'utf-8',
|
|
82
|
+
)
|
|
83
|
+
readmeIsEjs = true
|
|
77
84
|
}
|
|
78
85
|
|
|
79
86
|
let smallLogo: string | undefined
|
|
@@ -107,6 +114,7 @@ export function scanAddOnDirectories(addOnsDirectories: Array<string>) {
|
|
|
107
114
|
packageAdditions,
|
|
108
115
|
packageTemplate,
|
|
109
116
|
readme,
|
|
117
|
+
readmeIsEjs,
|
|
110
118
|
files,
|
|
111
119
|
smallLogo,
|
|
112
120
|
getFiles,
|
package/src/package-manager.ts
CHANGED
|
@@ -101,6 +101,43 @@ export function packageManagerInstall(
|
|
|
101
101
|
return environment.execute(command, commandArgs, cwd)
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
export function translateExecuteCommand(
|
|
105
|
+
packageManager: PackageManager,
|
|
106
|
+
command: { command: string; args?: Array<string> },
|
|
107
|
+
): { command: string; args: Array<string> } {
|
|
108
|
+
const args = command.args || []
|
|
109
|
+
const parsed = parseExecuteCommand(command.command, args)
|
|
110
|
+
if (parsed) {
|
|
111
|
+
return getPackageManagerExecuteCommand(packageManager, parsed.pkg, parsed.args)
|
|
112
|
+
}
|
|
113
|
+
return { command: command.command, args }
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function parseExecuteCommand(
|
|
117
|
+
command: string,
|
|
118
|
+
args: Array<string>,
|
|
119
|
+
): { pkg: string; args: Array<string> } | null {
|
|
120
|
+
if (command === 'npx') {
|
|
121
|
+
const filtered = args[0] === '-y' ? args.slice(1) : args
|
|
122
|
+
const [pkg, ...rest] = filtered
|
|
123
|
+
return pkg ? { pkg, args: rest } : null
|
|
124
|
+
}
|
|
125
|
+
if (command === 'pnpx' || command === 'bunx') {
|
|
126
|
+
const filtered = command === 'bunx' && args[0] === '--bun' ? args.slice(1) : args
|
|
127
|
+
const [pkg, ...rest] = filtered
|
|
128
|
+
return pkg ? { pkg, args: rest } : null
|
|
129
|
+
}
|
|
130
|
+
if ((command === 'pnpm' || command === 'yarn') && args[0] === 'dlx') {
|
|
131
|
+
const [, pkg, ...rest] = args
|
|
132
|
+
return pkg ? { pkg, args: rest } : null
|
|
133
|
+
}
|
|
134
|
+
if (command === 'deno' && args[0] === 'run' && args[1]?.startsWith('npm:')) {
|
|
135
|
+
const pkg = args[1].slice(4)
|
|
136
|
+
return pkg ? { pkg, args: args.slice(2) } : null
|
|
137
|
+
}
|
|
138
|
+
return null
|
|
139
|
+
}
|
|
140
|
+
|
|
104
141
|
export function packageManagerExecute(
|
|
105
142
|
environment: Environment,
|
|
106
143
|
cwd: string,
|
package/src/template-file.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { format } from 'prettier'
|
|
|
4
4
|
|
|
5
5
|
import { formatCommand } from './utils.js'
|
|
6
6
|
import {
|
|
7
|
+
getPackageManagerExecuteCommand,
|
|
7
8
|
getPackageManagerInstallCommand,
|
|
8
9
|
getPackageManagerScriptCommand,
|
|
9
10
|
} from './package-manager.js'
|
|
@@ -70,6 +71,14 @@ export function createTemplateFile(environment: Environment, options: Options) {
|
|
|
70
71
|
]),
|
|
71
72
|
)
|
|
72
73
|
}
|
|
74
|
+
function getPackageManagerExecuteScript(
|
|
75
|
+
pkg: string,
|
|
76
|
+
args: Array<string> = [],
|
|
77
|
+
) {
|
|
78
|
+
return formatCommand(
|
|
79
|
+
getPackageManagerExecuteCommand(options.packageManager, pkg, args),
|
|
80
|
+
)
|
|
81
|
+
}
|
|
73
82
|
|
|
74
83
|
class IgnoreFileError extends Error {
|
|
75
84
|
constructor() {
|
|
@@ -135,6 +144,7 @@ export function createTemplateFile(environment: Environment, options: Options) {
|
|
|
135
144
|
|
|
136
145
|
getPackageManagerAddScript,
|
|
137
146
|
getPackageManagerRunScript,
|
|
147
|
+
getPackageManagerExecuteScript,
|
|
138
148
|
|
|
139
149
|
relativePath: (path: string, stripExtension: boolean = false) =>
|
|
140
150
|
relativePath(file, path, stripExtension),
|
|
@@ -142,6 +152,10 @@ export function createTemplateFile(environment: Environment, options: Options) {
|
|
|
142
152
|
integrationImportContent,
|
|
143
153
|
integrationImportCode,
|
|
144
154
|
|
|
155
|
+
renderTemplate: (content: string) => {
|
|
156
|
+
return render(content, templateValues)
|
|
157
|
+
},
|
|
158
|
+
|
|
145
159
|
ignoreFile: () => {
|
|
146
160
|
throw new IgnoreFileError()
|
|
147
161
|
},
|
package/src/types.ts
CHANGED
|
@@ -50,6 +50,7 @@ export const AddOnBaseSchema = z.object({
|
|
|
50
50
|
'monitoring',
|
|
51
51
|
'cms',
|
|
52
52
|
'api',
|
|
53
|
+
'analytics',
|
|
53
54
|
'i18n',
|
|
54
55
|
'tooling',
|
|
55
56
|
'other',
|
|
@@ -119,6 +120,7 @@ export const AddOnInfoSchema = AddOnBaseSchema.extend({
|
|
|
119
120
|
integrations: z.array(IntegrationSchema).optional(),
|
|
120
121
|
phase: z.enum(['setup', 'add-on']),
|
|
121
122
|
readme: z.string().optional(),
|
|
123
|
+
readmeIsEjs: z.boolean().optional(),
|
|
122
124
|
})
|
|
123
125
|
|
|
124
126
|
export const AddOnCompiledSchema = AddOnInfoSchema.extend({
|
package/src/utils.ts
CHANGED
|
@@ -44,6 +44,12 @@ describe('toCleanPath', () => {
|
|
|
44
44
|
toCleanPath('C:\\Projects\\my-app\\src\\file.ts', 'C:/Projects/my-app'),
|
|
45
45
|
).toBe('src/file.ts')
|
|
46
46
|
})
|
|
47
|
+
|
|
48
|
+
it('should handle missing drive letter in path against Windows base', () => {
|
|
49
|
+
expect(
|
|
50
|
+
toCleanPath('/Users/me/my-app/src/file.ts', 'C:\\Users\\me\\my-app'),
|
|
51
|
+
).toBe('src/file.ts')
|
|
52
|
+
})
|
|
47
53
|
})
|
|
48
54
|
|
|
49
55
|
describe('relativePath', () => {
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
getPackageManagerExecuteCommand,
|
|
5
5
|
getPackageManagerInstallCommand,
|
|
6
6
|
getPackageManagerScriptCommand,
|
|
7
|
+
translateExecuteCommand,
|
|
7
8
|
} from '../src/package-manager.js'
|
|
8
9
|
import { formatCommand } from '../src/utils.js'
|
|
9
10
|
|
|
@@ -152,3 +153,161 @@ describe('getPackageManagerInstallCommand', () => {
|
|
|
152
153
|
).toBe('npm install vitest -D')
|
|
153
154
|
})
|
|
154
155
|
})
|
|
156
|
+
|
|
157
|
+
describe('translateExecuteCommand', () => {
|
|
158
|
+
it('should translate npx to bunx for bun', () => {
|
|
159
|
+
expect(
|
|
160
|
+
formatCommand(
|
|
161
|
+
translateExecuteCommand('bun', {
|
|
162
|
+
command: 'npx',
|
|
163
|
+
args: ['shadcn', 'add', 'button'],
|
|
164
|
+
}),
|
|
165
|
+
),
|
|
166
|
+
).toBe('bunx --bun shadcn add button')
|
|
167
|
+
})
|
|
168
|
+
it('should translate npx to pnpm dlx for pnpm', () => {
|
|
169
|
+
expect(
|
|
170
|
+
formatCommand(
|
|
171
|
+
translateExecuteCommand('pnpm', {
|
|
172
|
+
command: 'npx',
|
|
173
|
+
args: ['shadcn', 'add', 'button'],
|
|
174
|
+
}),
|
|
175
|
+
),
|
|
176
|
+
).toBe('pnpm dlx shadcn add button')
|
|
177
|
+
})
|
|
178
|
+
it('should translate npx to yarn dlx for yarn', () => {
|
|
179
|
+
expect(
|
|
180
|
+
formatCommand(
|
|
181
|
+
translateExecuteCommand('yarn', {
|
|
182
|
+
command: 'npx',
|
|
183
|
+
args: ['shadcn', 'add', 'button'],
|
|
184
|
+
}),
|
|
185
|
+
),
|
|
186
|
+
).toBe('yarn dlx shadcn add button')
|
|
187
|
+
})
|
|
188
|
+
it('should translate npx to deno run for deno', () => {
|
|
189
|
+
expect(
|
|
190
|
+
formatCommand(
|
|
191
|
+
translateExecuteCommand('deno', {
|
|
192
|
+
command: 'npx',
|
|
193
|
+
args: ['shadcn', 'add', 'button'],
|
|
194
|
+
}),
|
|
195
|
+
),
|
|
196
|
+
).toBe('deno run npm:shadcn add button')
|
|
197
|
+
})
|
|
198
|
+
it('should keep npx -y for npm', () => {
|
|
199
|
+
expect(
|
|
200
|
+
formatCommand(
|
|
201
|
+
translateExecuteCommand('npm', {
|
|
202
|
+
command: 'npx',
|
|
203
|
+
args: ['shadcn', 'add', 'button'],
|
|
204
|
+
}),
|
|
205
|
+
),
|
|
206
|
+
).toBe('npx -y shadcn add button')
|
|
207
|
+
})
|
|
208
|
+
it('should pass through non-npx commands unchanged', () => {
|
|
209
|
+
expect(
|
|
210
|
+
formatCommand(
|
|
211
|
+
translateExecuteCommand('bun', {
|
|
212
|
+
command: 'node',
|
|
213
|
+
args: ['script.js'],
|
|
214
|
+
}),
|
|
215
|
+
),
|
|
216
|
+
).toBe('node script.js')
|
|
217
|
+
})
|
|
218
|
+
it('should handle missing args gracefully', () => {
|
|
219
|
+
expect(
|
|
220
|
+
formatCommand(translateExecuteCommand('bun', { command: 'npx' })),
|
|
221
|
+
).toBe('npx')
|
|
222
|
+
})
|
|
223
|
+
it('should strip -y flag from npx input', () => {
|
|
224
|
+
expect(
|
|
225
|
+
formatCommand(
|
|
226
|
+
translateExecuteCommand('pnpm', {
|
|
227
|
+
command: 'npx',
|
|
228
|
+
args: ['-y', 'shadcn', 'add', 'button'],
|
|
229
|
+
}),
|
|
230
|
+
),
|
|
231
|
+
).toBe('pnpm dlx shadcn add button')
|
|
232
|
+
})
|
|
233
|
+
it('should translate bunx to target package manager', () => {
|
|
234
|
+
expect(
|
|
235
|
+
formatCommand(
|
|
236
|
+
translateExecuteCommand('pnpm', {
|
|
237
|
+
command: 'bunx',
|
|
238
|
+
args: ['shadcn', 'add', 'button'],
|
|
239
|
+
}),
|
|
240
|
+
),
|
|
241
|
+
).toBe('pnpm dlx shadcn add button')
|
|
242
|
+
})
|
|
243
|
+
it('should strip --bun flag from bunx input', () => {
|
|
244
|
+
expect(
|
|
245
|
+
formatCommand(
|
|
246
|
+
translateExecuteCommand('pnpm', {
|
|
247
|
+
command: 'bunx',
|
|
248
|
+
args: ['--bun', 'shadcn', 'add', 'button'],
|
|
249
|
+
}),
|
|
250
|
+
),
|
|
251
|
+
).toBe('pnpm dlx shadcn add button')
|
|
252
|
+
})
|
|
253
|
+
it('should translate pnpx to target package manager', () => {
|
|
254
|
+
expect(
|
|
255
|
+
formatCommand(
|
|
256
|
+
translateExecuteCommand('yarn', {
|
|
257
|
+
command: 'pnpx',
|
|
258
|
+
args: ['shadcn', 'add', 'button'],
|
|
259
|
+
}),
|
|
260
|
+
),
|
|
261
|
+
).toBe('yarn dlx shadcn add button')
|
|
262
|
+
})
|
|
263
|
+
it('should translate pnpm dlx to target package manager', () => {
|
|
264
|
+
expect(
|
|
265
|
+
formatCommand(
|
|
266
|
+
translateExecuteCommand('bun', {
|
|
267
|
+
command: 'pnpm',
|
|
268
|
+
args: ['dlx', 'shadcn', 'add', 'button'],
|
|
269
|
+
}),
|
|
270
|
+
),
|
|
271
|
+
).toBe('bunx --bun shadcn add button')
|
|
272
|
+
})
|
|
273
|
+
it('should translate yarn dlx to target package manager', () => {
|
|
274
|
+
expect(
|
|
275
|
+
formatCommand(
|
|
276
|
+
translateExecuteCommand('npm', {
|
|
277
|
+
command: 'yarn',
|
|
278
|
+
args: ['dlx', 'shadcn', 'add', 'button'],
|
|
279
|
+
}),
|
|
280
|
+
),
|
|
281
|
+
).toBe('npx -y shadcn add button')
|
|
282
|
+
})
|
|
283
|
+
it('should translate deno run npm: to target package manager', () => {
|
|
284
|
+
expect(
|
|
285
|
+
formatCommand(
|
|
286
|
+
translateExecuteCommand('pnpm', {
|
|
287
|
+
command: 'deno',
|
|
288
|
+
args: ['run', 'npm:shadcn', 'add', 'button'],
|
|
289
|
+
}),
|
|
290
|
+
),
|
|
291
|
+
).toBe('pnpm dlx shadcn add button')
|
|
292
|
+
})
|
|
293
|
+
it('should pass through non-execute pnpm commands unchanged', () => {
|
|
294
|
+
expect(
|
|
295
|
+
formatCommand(
|
|
296
|
+
translateExecuteCommand('bun', {
|
|
297
|
+
command: 'pnpm',
|
|
298
|
+
args: ['install'],
|
|
299
|
+
}),
|
|
300
|
+
),
|
|
301
|
+
).toBe('pnpm install')
|
|
302
|
+
})
|
|
303
|
+
it('should pass through non-execute deno commands unchanged', () => {
|
|
304
|
+
expect(
|
|
305
|
+
formatCommand(
|
|
306
|
+
translateExecuteCommand('npm', {
|
|
307
|
+
command: 'deno',
|
|
308
|
+
args: ['task', 'dev'],
|
|
309
|
+
}),
|
|
310
|
+
),
|
|
311
|
+
).toBe('deno task dev')
|
|
312
|
+
})
|
|
313
|
+
})
|