@tanstack/create 0.61.0 → 0.61.2

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 CHANGED
@@ -1,5 +1,23 @@
1
1
  # @tanstack/create
2
2
 
3
+ ## 0.61.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Improve generated app reliability and CLI compatibility. ([`791bef6`](https://github.com/TanStack/cli/commit/791bef6b5472df5b5e2bffe5c1714c4052a97ac3))
8
+
9
+ - Fix React Query provider scaffolding (including Query + tRPC combinations) so generated apps build correctly.
10
+ - Fix Prisma add-on package template rendering by exposing package-manager execute helper in `package.json.ejs` context.
11
+ - Restore `--tailwind` and `--no-tailwind` as deprecated compatibility flags that are accepted but ignored with clear warnings.
12
+ - Align CLI/docs examples with the current Tailwind-always-on behavior.
13
+ - Update Convex demo import to type-only `Id` import to avoid runtime resolution issues.
14
+
15
+ ## 0.61.1
16
+
17
+ ### Patch Changes
18
+
19
+ - add missing .js extensions to ESM imports ([#369](https://github.com/TanStack/cli/pull/369))
20
+
3
21
  ## 0.61.0
4
22
 
5
23
  ### Minor Changes
@@ -3,7 +3,7 @@ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
3
3
  import { basename, extname, resolve } from 'node:path';
4
4
  import parseGitignore from 'parse-gitignore';
5
5
  import ignore from 'ignore';
6
- import { hasDrive, stripDrive } from './utils';
6
+ import { hasDrive, stripDrive } from './utils.js';
7
7
  const BINARY_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico'];
8
8
  export function readFileHelper(path) {
9
9
  if (isBinaryFile(path)) {
@@ -4,7 +4,7 @@ import { useQuery, useMutation } from 'convex/react'
4
4
  import { Trash2, Plus, Check, Circle } from 'lucide-react'
5
5
 
6
6
  import { api } from '../../../convex/_generated/api'
7
- import { Id } from '../../../convex/_generated/dataModel'
7
+ import type { Id } from '../../../convex/_generated/dataModel'
8
8
 
9
9
  export const Route = createFileRoute('/demo/convex')({
10
10
  ssr: false,
@@ -1,10 +1,12 @@
1
1
  <% if (addOnEnabled.tRPC) { %>
2
- import { QueryClient } from "@tanstack/react-query";
2
+ import type { ReactNode } from 'react'
3
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
3
4
  import superjson from "superjson";
4
5
  import { createTRPCClient, httpBatchStreamLink } from "@trpc/client";
5
6
  import { createTRPCOptionsProxy } from "@trpc/tanstack-react-query";
6
7
 
7
8
  import type { TRPCRouter } from "@/integrations/trpc/router";
9
+ import { TRPCProvider } from '@/integrations/trpc/react'
8
10
 
9
11
  function getUrl() {
10
12
  const base = (() => {
@@ -23,7 +25,18 @@ export const trpcClient = createTRPCClient<TRPCRouter>({
23
25
  ],
24
26
  });
25
27
 
28
+ let context:
29
+ | {
30
+ queryClient: QueryClient
31
+ trpc: ReturnType<typeof createTRPCOptionsProxy<TRPCRouter>>
32
+ }
33
+ | undefined
34
+
26
35
  export function getContext() {
36
+ if (context) {
37
+ return context
38
+ }
39
+
27
40
  const queryClient = new QueryClient({
28
41
  defaultOptions: {
29
42
  dehydrate: { serializeData: superjson.serialize },
@@ -35,18 +48,64 @@ export function getContext() {
35
48
  client: trpcClient,
36
49
  queryClient: queryClient,
37
50
  });
38
- return {
51
+ context = {
39
52
  queryClient,
40
53
  trpc: serverHelpers,
41
- };
54
+ }
55
+
56
+ return context
57
+ }
58
+
59
+ export default function TanStackQueryProvider({
60
+ children,
61
+ }: {
62
+ children: ReactNode
63
+ }) {
64
+ const { queryClient } = getContext()
65
+
66
+ return (
67
+ <QueryClientProvider client={queryClient}>
68
+ <TRPCProvider trpcClient={trpcClient} queryClient={queryClient}>
69
+ {children}
70
+ </TRPCProvider>
71
+ </QueryClientProvider>
72
+ )
42
73
  }
43
74
  <% } else { %>
44
- import { QueryClient } from '@tanstack/react-query'
75
+ import type { ReactNode } from 'react'
76
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
77
+
78
+ let context:
79
+ | {
80
+ queryClient: QueryClient
81
+ }
82
+ | undefined
45
83
 
46
84
  export function getContext() {
85
+ if (context) {
86
+ return context
87
+ }
88
+
47
89
  const queryClient = new QueryClient();
48
- return {
90
+
91
+ context = {
49
92
  queryClient,
50
- };
93
+ }
94
+
95
+ return context
96
+ }
97
+
98
+ export default function TanStackQueryProvider({
99
+ children,
100
+ }: {
101
+ children: ReactNode
102
+ }) {
103
+ const { queryClient } = getContext()
104
+
105
+ return (
106
+ <QueryClientProvider client={queryClient}>
107
+ {children}
108
+ </QueryClientProvider>
109
+ )
51
110
  }
52
111
  <% } %>
@@ -0,0 +1,27 @@
1
+ import { createRouter as createTanStackRouter } from '@tanstack/react-router'
2
+ import { routeTree } from './routeTree.gen'
3
+ <% if (addOnEnabled['tanstack-query']) { %>
4
+ import { getContext } from './integrations/tanstack-query/root-provider'
5
+ <% } %>
6
+
7
+ export function getRouter() {
8
+ const router = createTanStackRouter({
9
+ routeTree,
10
+ <% if (addOnEnabled['tanstack-query']) { %>
11
+ context: getContext(),
12
+ <% } else if (addOnEnabled['apollo-client']) { %>
13
+ context: {} as any,
14
+ <% } %>
15
+ scrollRestoration: true,
16
+ defaultPreload: 'intent',
17
+ defaultPreloadStaleTime: 0,
18
+ })
19
+
20
+ return router
21
+ }
22
+
23
+ declare module '@tanstack/react-router' {
24
+ interface Register {
25
+ router: ReturnType<typeof getRouter>
26
+ }
27
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "scripts": {
3
3
  "lint": "eslint",
4
- "format": "prettier",
4
+ "format": "prettier --check .",
5
5
  "check": "prettier --write . && eslint --fix"
6
6
  },
7
7
  "devDependencies": {
@@ -0,0 +1,25 @@
1
+ import { createRouter as createTanStackRouter } from '@tanstack/solid-router'
2
+ import { routeTree } from './routeTree.gen'
3
+ <% if (addOnEnabled['tanstack-query']) { %>
4
+ import { getContext } from './integrations/tanstack-query/provider'
5
+ <% } %>
6
+
7
+ export function getRouter() {
8
+ const router = createTanStackRouter({
9
+ routeTree,
10
+ <% if (addOnEnabled['tanstack-query']) { %>
11
+ context: getContext(),
12
+ <% } %>
13
+ scrollRestoration: true,
14
+ defaultPreload: 'intent',
15
+ defaultPreloadStaleTime: 0,
16
+ })
17
+
18
+ return router
19
+ }
20
+
21
+ declare module '@tanstack/solid-router' {
22
+ interface Register {
23
+ router: ReturnType<typeof getRouter>
24
+ }
25
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "scripts": {
3
3
  "lint": "eslint",
4
- "format": "prettier",
4
+ "format": "prettier --check .",
5
5
  "check": "prettier --write . && eslint --fix"
6
6
  },
7
7
  "devDependencies": {
@@ -1,5 +1,6 @@
1
1
  import { render } from 'ejs';
2
- import { sortObject } from './utils.js';
2
+ import { formatCommand, sortObject } from './utils.js';
3
+ import { getPackageManagerExecuteCommand } from './package-manager.js';
3
4
  export function mergePackageJSON(packageJSON, overlayPackageJSON) {
4
5
  return {
5
6
  ...packageJSON,
@@ -19,6 +20,10 @@ export function mergePackageJSON(packageJSON, overlayPackageJSON) {
19
20
  };
20
21
  }
21
22
  export function createPackageJSON(options) {
23
+ const packageManager = options.packageManager;
24
+ function getPackageManagerExecuteScript(pkg, args = []) {
25
+ return formatCommand(getPackageManagerExecuteCommand(packageManager, pkg, args));
26
+ }
22
27
  let packageJSON = {
23
28
  ...JSON.parse(JSON.stringify(options.framework.basePackageJSON)),
24
29
  name: options.projectName,
@@ -50,6 +55,7 @@ export function createPackageJSON(options) {
50
55
  }, {}),
51
56
  addOnOption: options.addOnOptions,
52
57
  addOns: options.chosenAddOns,
58
+ getPackageManagerExecuteScript,
53
59
  };
54
60
  try {
55
61
  const renderedTemplate = render(addOn.packageTemplate, templateValues);
@@ -1,4 +1,4 @@
1
- import type { Environment } from './types';
1
+ import type { Environment } from './types.js';
2
2
  export declare function readFileHelper(path: string): string;
3
3
  export declare function isBinaryFile(path: string): boolean;
4
4
  export declare function convertBinaryContentsToBase64(contents: any): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/create",
3
- "version": "0.61.0",
3
+ "version": "0.61.2",
4
4
  "description": "TanStack Application Builder Engine",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -4,8 +4,8 @@ import { basename, extname, resolve } from 'node:path'
4
4
  import parseGitignore from 'parse-gitignore'
5
5
  import ignore from 'ignore'
6
6
 
7
- import { hasDrive, stripDrive } from './utils'
8
- import type { Environment } from './types'
7
+ import { hasDrive, stripDrive } from './utils.js'
8
+ import type { Environment } from './types.js'
9
9
 
10
10
  const BINARY_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico']
11
11
 
@@ -232,10 +232,10 @@ const PROJECT_FILES = ['package.json']
232
232
  export function createIgnore(path: string, includeProjectFiles = true) {
233
233
  const ignoreList = existsSync(resolve(path, '.gitignore'))
234
234
  ? (
235
- parseGitignore(
236
- readFileSync(resolve(path, '.gitignore')),
237
- ) as unknown as { patterns: Array<string> }
238
- ).patterns
235
+ parseGitignore(
236
+ readFileSync(resolve(path, '.gitignore')),
237
+ ) as unknown as { patterns: Array<string> }
238
+ ).patterns
239
239
  : []
240
240
  const ig = ignore().add(ignoreList)
241
241
  return (filePath: string) => {
@@ -4,7 +4,7 @@ import { useQuery, useMutation } from 'convex/react'
4
4
  import { Trash2, Plus, Check, Circle } from 'lucide-react'
5
5
 
6
6
  import { api } from '../../../convex/_generated/api'
7
- import { Id } from '../../../convex/_generated/dataModel'
7
+ import type { Id } from '../../../convex/_generated/dataModel'
8
8
 
9
9
  export const Route = createFileRoute('/demo/convex')({
10
10
  ssr: false,
@@ -1,10 +1,12 @@
1
1
  <% if (addOnEnabled.tRPC) { %>
2
- import { QueryClient } from "@tanstack/react-query";
2
+ import type { ReactNode } from 'react'
3
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
3
4
  import superjson from "superjson";
4
5
  import { createTRPCClient, httpBatchStreamLink } from "@trpc/client";
5
6
  import { createTRPCOptionsProxy } from "@trpc/tanstack-react-query";
6
7
 
7
8
  import type { TRPCRouter } from "@/integrations/trpc/router";
9
+ import { TRPCProvider } from '@/integrations/trpc/react'
8
10
 
9
11
  function getUrl() {
10
12
  const base = (() => {
@@ -23,7 +25,18 @@ export const trpcClient = createTRPCClient<TRPCRouter>({
23
25
  ],
24
26
  });
25
27
 
28
+ let context:
29
+ | {
30
+ queryClient: QueryClient
31
+ trpc: ReturnType<typeof createTRPCOptionsProxy<TRPCRouter>>
32
+ }
33
+ | undefined
34
+
26
35
  export function getContext() {
36
+ if (context) {
37
+ return context
38
+ }
39
+
27
40
  const queryClient = new QueryClient({
28
41
  defaultOptions: {
29
42
  dehydrate: { serializeData: superjson.serialize },
@@ -35,18 +48,64 @@ export function getContext() {
35
48
  client: trpcClient,
36
49
  queryClient: queryClient,
37
50
  });
38
- return {
51
+ context = {
39
52
  queryClient,
40
53
  trpc: serverHelpers,
41
- };
54
+ }
55
+
56
+ return context
57
+ }
58
+
59
+ export default function TanStackQueryProvider({
60
+ children,
61
+ }: {
62
+ children: ReactNode
63
+ }) {
64
+ const { queryClient } = getContext()
65
+
66
+ return (
67
+ <QueryClientProvider client={queryClient}>
68
+ <TRPCProvider trpcClient={trpcClient} queryClient={queryClient}>
69
+ {children}
70
+ </TRPCProvider>
71
+ </QueryClientProvider>
72
+ )
42
73
  }
43
74
  <% } else { %>
44
- import { QueryClient } from '@tanstack/react-query'
75
+ import type { ReactNode } from 'react'
76
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
77
+
78
+ let context:
79
+ | {
80
+ queryClient: QueryClient
81
+ }
82
+ | undefined
45
83
 
46
84
  export function getContext() {
85
+ if (context) {
86
+ return context
87
+ }
88
+
47
89
  const queryClient = new QueryClient();
48
- return {
90
+
91
+ context = {
49
92
  queryClient,
50
- };
93
+ }
94
+
95
+ return context
96
+ }
97
+
98
+ export default function TanStackQueryProvider({
99
+ children,
100
+ }: {
101
+ children: ReactNode
102
+ }) {
103
+ const { queryClient } = getContext()
104
+
105
+ return (
106
+ <QueryClientProvider client={queryClient}>
107
+ {children}
108
+ </QueryClientProvider>
109
+ )
51
110
  }
52
111
  <% } %>
@@ -0,0 +1,27 @@
1
+ import { createRouter as createTanStackRouter } from '@tanstack/react-router'
2
+ import { routeTree } from './routeTree.gen'
3
+ <% if (addOnEnabled['tanstack-query']) { %>
4
+ import { getContext } from './integrations/tanstack-query/root-provider'
5
+ <% } %>
6
+
7
+ export function getRouter() {
8
+ const router = createTanStackRouter({
9
+ routeTree,
10
+ <% if (addOnEnabled['tanstack-query']) { %>
11
+ context: getContext(),
12
+ <% } else if (addOnEnabled['apollo-client']) { %>
13
+ context: {} as any,
14
+ <% } %>
15
+ scrollRestoration: true,
16
+ defaultPreload: 'intent',
17
+ defaultPreloadStaleTime: 0,
18
+ })
19
+
20
+ return router
21
+ }
22
+
23
+ declare module '@tanstack/react-router' {
24
+ interface Register {
25
+ router: ReturnType<typeof getRouter>
26
+ }
27
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "scripts": {
3
3
  "lint": "eslint",
4
- "format": "prettier",
4
+ "format": "prettier --check .",
5
5
  "check": "prettier --write . && eslint --fix"
6
6
  },
7
7
  "devDependencies": {
@@ -0,0 +1,25 @@
1
+ import { createRouter as createTanStackRouter } from '@tanstack/solid-router'
2
+ import { routeTree } from './routeTree.gen'
3
+ <% if (addOnEnabled['tanstack-query']) { %>
4
+ import { getContext } from './integrations/tanstack-query/provider'
5
+ <% } %>
6
+
7
+ export function getRouter() {
8
+ const router = createTanStackRouter({
9
+ routeTree,
10
+ <% if (addOnEnabled['tanstack-query']) { %>
11
+ context: getContext(),
12
+ <% } %>
13
+ scrollRestoration: true,
14
+ defaultPreload: 'intent',
15
+ defaultPreloadStaleTime: 0,
16
+ })
17
+
18
+ return router
19
+ }
20
+
21
+ declare module '@tanstack/solid-router' {
22
+ interface Register {
23
+ router: ReturnType<typeof getRouter>
24
+ }
25
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "scripts": {
3
3
  "lint": "eslint",
4
- "format": "prettier",
4
+ "format": "prettier --check .",
5
5
  "check": "prettier --write . && eslint --fix"
6
6
  },
7
7
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  import { render } from 'ejs'
2
- import { sortObject } from './utils.js'
3
-
2
+ import { formatCommand, sortObject } from './utils.js'
3
+ import { getPackageManagerExecuteCommand } from './package-manager.js'
4
4
  import type { Options } from './types.js'
5
5
 
6
6
  export function mergePackageJSON(
@@ -26,6 +26,15 @@ export function mergePackageJSON(
26
26
  }
27
27
 
28
28
  export function createPackageJSON(options: Options) {
29
+ const packageManager = options.packageManager
30
+
31
+ function getPackageManagerExecuteScript(
32
+ pkg: string,
33
+ args: Array<string> = [],
34
+ ) {
35
+ return formatCommand(getPackageManagerExecuteCommand(packageManager, pkg, args))
36
+ }
37
+
29
38
  let packageJSON = {
30
39
  ...JSON.parse(JSON.stringify(options.framework.basePackageJSON)),
31
40
  name: options.projectName,
@@ -63,6 +72,7 @@ export function createPackageJSON(options: Options) {
63
72
  ),
64
73
  addOnOption: options.addOnOptions,
65
74
  addOns: options.chosenAddOns,
75
+ getPackageManagerExecuteScript,
66
76
  }
67
77
 
68
78
  try {
@@ -91,4 +91,33 @@ describe('createPackageJSON', () => {
91
91
  onlyBuiltDependencies: ['better-sqlite3'],
92
92
  })
93
93
  })
94
+
95
+ it('should provide execute command helper in package templates', () => {
96
+ const packageJSON = createPackageJSON({
97
+ chosenAddOns: [
98
+ {
99
+ packageTemplate:
100
+ '{"scripts":{"post-cta-init":"<%- getPackageManagerExecuteScript(\'create-db@latest\', [\'--user-agent\', \'tanstack/tsrouter\']) %>"}}',
101
+ },
102
+ ],
103
+ packageManager: 'npm',
104
+ addOnOptions: {},
105
+ mode: 'file-router',
106
+ typescript: true,
107
+ tailwind: true,
108
+ projectName: 'test',
109
+ framework: {
110
+ basePackageJSON: {},
111
+ optionalPackages: {
112
+ typescript: {},
113
+ tailwindcss: {},
114
+ 'file-router': {},
115
+ },
116
+ } as unknown as Framework,
117
+ } as unknown as Options)
118
+
119
+ expect(packageJSON.scripts['post-cta-init']).toBe(
120
+ 'npx -y create-db@latest --user-agent tanstack/tsrouter',
121
+ )
122
+ })
94
123
  })