@tanstack/create 0.61.3 → 0.61.5

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.
Files changed (46) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/create-app.js +64 -3
  3. package/dist/custom-add-ons/add-on.js +59 -1
  4. package/dist/custom-add-ons/starter.js +5 -1
  5. package/dist/frameworks/react/add-ons/clerk/info.json +9 -0
  6. package/dist/frameworks/react/add-ons/convex/info.json +16 -0
  7. package/dist/frameworks/react/project/base/_dot_gitignore +0 -1
  8. package/dist/frameworks/react/project/base/index.html.ejs +13 -0
  9. package/dist/frameworks/react/project/base/src/main.tsx.ejs +24 -0
  10. package/dist/frameworks/react/project/base/src/routes/__root.tsx.ejs +31 -0
  11. package/dist/frameworks/react/project/base/vite.config.ts.ejs +6 -2
  12. package/dist/frameworks/solid/project/base/_dot_gitignore +0 -1
  13. package/dist/frameworks/solid/project/base/index.html.ejs +13 -0
  14. package/dist/frameworks/solid/project/base/src/main.tsx.ejs +23 -0
  15. package/dist/frameworks/solid/project/base/src/routes/__root.tsx.ejs +20 -0
  16. package/dist/frameworks/solid/project/base/vite.config.ts.ejs +6 -2
  17. package/dist/frameworks.js +1 -0
  18. package/dist/index.js +1 -1
  19. package/dist/package-json.js +20 -0
  20. package/dist/template-file.js +1 -0
  21. package/dist/types/custom-add-ons/add-on.d.ts +9 -0
  22. package/dist/types/index.d.ts +1 -1
  23. package/dist/types/types.d.ts +193 -0
  24. package/dist/types.js +10 -0
  25. package/package.json +1 -1
  26. package/src/create-app.ts +77 -3
  27. package/src/custom-add-ons/add-on.ts +72 -1
  28. package/src/custom-add-ons/starter.ts +7 -1
  29. package/src/frameworks/react/add-ons/clerk/info.json +9 -0
  30. package/src/frameworks/react/add-ons/convex/info.json +16 -0
  31. package/src/frameworks/react/project/base/_dot_gitignore +0 -1
  32. package/src/frameworks/react/project/base/index.html.ejs +13 -0
  33. package/src/frameworks/react/project/base/src/main.tsx.ejs +24 -0
  34. package/src/frameworks/react/project/base/src/routes/__root.tsx.ejs +31 -0
  35. package/src/frameworks/react/project/base/vite.config.ts.ejs +6 -2
  36. package/src/frameworks/solid/project/base/_dot_gitignore +0 -1
  37. package/src/frameworks/solid/project/base/index.html.ejs +13 -0
  38. package/src/frameworks/solid/project/base/src/main.tsx.ejs +23 -0
  39. package/src/frameworks/solid/project/base/src/routes/__root.tsx.ejs +20 -0
  40. package/src/frameworks/solid/project/base/vite.config.ts.ejs +6 -2
  41. package/src/frameworks.ts +1 -0
  42. package/src/index.ts +1 -1
  43. package/src/package-json.ts +24 -0
  44. package/src/template-file.ts +1 -0
  45. package/src/types.ts +15 -0
  46. package/tests/custom-add-ons/starter.test.ts +29 -0
@@ -198,6 +198,28 @@ export declare const AddOnBaseSchema: z.ZodObject<{
198
198
  default: string;
199
199
  description?: string | undefined;
200
200
  }>]>>>;
201
+ envVars: z.ZodOptional<z.ZodArray<z.ZodObject<{
202
+ name: z.ZodString;
203
+ description: z.ZodOptional<z.ZodString>;
204
+ required: z.ZodOptional<z.ZodBoolean>;
205
+ default: z.ZodOptional<z.ZodString>;
206
+ secret: z.ZodOptional<z.ZodBoolean>;
207
+ file: z.ZodOptional<z.ZodEnum<[".env", ".env.local"]>>;
208
+ }, "strip", z.ZodTypeAny, {
209
+ name: string;
210
+ file?: ".env" | ".env.local" | undefined;
211
+ description?: string | undefined;
212
+ default?: string | undefined;
213
+ required?: boolean | undefined;
214
+ secret?: boolean | undefined;
215
+ }, {
216
+ name: string;
217
+ file?: ".env" | ".env.local" | undefined;
218
+ description?: string | undefined;
219
+ default?: string | undefined;
220
+ required?: boolean | undefined;
221
+ secret?: boolean | undefined;
222
+ }>, "many">>;
201
223
  default: z.ZodOptional<z.ZodBoolean>;
202
224
  }, "strip", z.ZodTypeAny, {
203
225
  type: "add-on" | "example" | "starter" | "toolchain" | "deployment";
@@ -247,6 +269,14 @@ export declare const AddOnBaseSchema: z.ZodObject<{
247
269
  addOnSpecialSteps?: string[] | undefined;
248
270
  createSpecialSteps?: string[] | undefined;
249
271
  postInitSpecialSteps?: string[] | undefined;
272
+ envVars?: {
273
+ name: string;
274
+ file?: ".env" | ".env.local" | undefined;
275
+ description?: string | undefined;
276
+ default?: string | undefined;
277
+ required?: boolean | undefined;
278
+ secret?: boolean | undefined;
279
+ }[] | undefined;
250
280
  }, {
251
281
  type: "add-on" | "example" | "starter" | "toolchain" | "deployment";
252
282
  description: string;
@@ -295,6 +325,14 @@ export declare const AddOnBaseSchema: z.ZodObject<{
295
325
  addOnSpecialSteps?: string[] | undefined;
296
326
  createSpecialSteps?: string[] | undefined;
297
327
  postInitSpecialSteps?: string[] | undefined;
328
+ envVars?: {
329
+ name: string;
330
+ file?: ".env" | ".env.local" | undefined;
331
+ description?: string | undefined;
332
+ default?: string | undefined;
333
+ required?: boolean | undefined;
334
+ secret?: boolean | undefined;
335
+ }[] | undefined;
298
336
  }>;
299
337
  export declare const StarterSchema: z.ZodObject<{
300
338
  id: z.ZodString;
@@ -391,6 +429,28 @@ export declare const StarterSchema: z.ZodObject<{
391
429
  default: string;
392
430
  description?: string | undefined;
393
431
  }>]>>>;
432
+ envVars: z.ZodOptional<z.ZodArray<z.ZodObject<{
433
+ name: z.ZodString;
434
+ description: z.ZodOptional<z.ZodString>;
435
+ required: z.ZodOptional<z.ZodBoolean>;
436
+ default: z.ZodOptional<z.ZodString>;
437
+ secret: z.ZodOptional<z.ZodBoolean>;
438
+ file: z.ZodOptional<z.ZodEnum<[".env", ".env.local"]>>;
439
+ }, "strip", z.ZodTypeAny, {
440
+ name: string;
441
+ file?: ".env" | ".env.local" | undefined;
442
+ description?: string | undefined;
443
+ default?: string | undefined;
444
+ required?: boolean | undefined;
445
+ secret?: boolean | undefined;
446
+ }, {
447
+ name: string;
448
+ file?: ".env" | ".env.local" | undefined;
449
+ description?: string | undefined;
450
+ default?: string | undefined;
451
+ required?: boolean | undefined;
452
+ secret?: boolean | undefined;
453
+ }>, "many">>;
394
454
  default: z.ZodOptional<z.ZodBoolean>;
395
455
  } & {
396
456
  framework: z.ZodString;
@@ -448,6 +508,14 @@ export declare const StarterSchema: z.ZodObject<{
448
508
  addOnSpecialSteps?: string[] | undefined;
449
509
  createSpecialSteps?: string[] | undefined;
450
510
  postInitSpecialSteps?: string[] | undefined;
511
+ envVars?: {
512
+ name: string;
513
+ file?: ".env" | ".env.local" | undefined;
514
+ description?: string | undefined;
515
+ default?: string | undefined;
516
+ required?: boolean | undefined;
517
+ secret?: boolean | undefined;
518
+ }[] | undefined;
451
519
  banner?: string | undefined;
452
520
  }, {
453
521
  type: "add-on" | "example" | "starter" | "toolchain" | "deployment";
@@ -500,6 +568,14 @@ export declare const StarterSchema: z.ZodObject<{
500
568
  addOnSpecialSteps?: string[] | undefined;
501
569
  createSpecialSteps?: string[] | undefined;
502
570
  postInitSpecialSteps?: string[] | undefined;
571
+ envVars?: {
572
+ name: string;
573
+ file?: ".env" | ".env.local" | undefined;
574
+ description?: string | undefined;
575
+ default?: string | undefined;
576
+ required?: boolean | undefined;
577
+ secret?: boolean | undefined;
578
+ }[] | undefined;
503
579
  banner?: string | undefined;
504
580
  }>;
505
581
  export declare const StarterCompiledSchema: z.ZodObject<{
@@ -597,6 +673,28 @@ export declare const StarterCompiledSchema: z.ZodObject<{
597
673
  default: string;
598
674
  description?: string | undefined;
599
675
  }>]>>>;
676
+ envVars: z.ZodOptional<z.ZodArray<z.ZodObject<{
677
+ name: z.ZodString;
678
+ description: z.ZodOptional<z.ZodString>;
679
+ required: z.ZodOptional<z.ZodBoolean>;
680
+ default: z.ZodOptional<z.ZodString>;
681
+ secret: z.ZodOptional<z.ZodBoolean>;
682
+ file: z.ZodOptional<z.ZodEnum<[".env", ".env.local"]>>;
683
+ }, "strip", z.ZodTypeAny, {
684
+ name: string;
685
+ file?: ".env" | ".env.local" | undefined;
686
+ description?: string | undefined;
687
+ default?: string | undefined;
688
+ required?: boolean | undefined;
689
+ secret?: boolean | undefined;
690
+ }, {
691
+ name: string;
692
+ file?: ".env" | ".env.local" | undefined;
693
+ description?: string | undefined;
694
+ default?: string | undefined;
695
+ required?: boolean | undefined;
696
+ secret?: boolean | undefined;
697
+ }>, "many">>;
600
698
  default: z.ZodOptional<z.ZodBoolean>;
601
699
  } & {
602
700
  framework: z.ZodString;
@@ -659,6 +757,14 @@ export declare const StarterCompiledSchema: z.ZodObject<{
659
757
  addOnSpecialSteps?: string[] | undefined;
660
758
  createSpecialSteps?: string[] | undefined;
661
759
  postInitSpecialSteps?: string[] | undefined;
760
+ envVars?: {
761
+ name: string;
762
+ file?: ".env" | ".env.local" | undefined;
763
+ description?: string | undefined;
764
+ default?: string | undefined;
765
+ required?: boolean | undefined;
766
+ secret?: boolean | undefined;
767
+ }[] | undefined;
662
768
  banner?: string | undefined;
663
769
  }, {
664
770
  type: "add-on" | "example" | "starter" | "toolchain" | "deployment";
@@ -713,6 +819,14 @@ export declare const StarterCompiledSchema: z.ZodObject<{
713
819
  addOnSpecialSteps?: string[] | undefined;
714
820
  createSpecialSteps?: string[] | undefined;
715
821
  postInitSpecialSteps?: string[] | undefined;
822
+ envVars?: {
823
+ name: string;
824
+ file?: ".env" | ".env.local" | undefined;
825
+ description?: string | undefined;
826
+ default?: string | undefined;
827
+ required?: boolean | undefined;
828
+ secret?: boolean | undefined;
829
+ }[] | undefined;
716
830
  banner?: string | undefined;
717
831
  }>;
718
832
  export declare const IntegrationSchema: z.ZodObject<{
@@ -829,6 +943,28 @@ export declare const AddOnInfoSchema: z.ZodObject<{
829
943
  default: string;
830
944
  description?: string | undefined;
831
945
  }>]>>>;
946
+ envVars: z.ZodOptional<z.ZodArray<z.ZodObject<{
947
+ name: z.ZodString;
948
+ description: z.ZodOptional<z.ZodString>;
949
+ required: z.ZodOptional<z.ZodBoolean>;
950
+ default: z.ZodOptional<z.ZodString>;
951
+ secret: z.ZodOptional<z.ZodBoolean>;
952
+ file: z.ZodOptional<z.ZodEnum<[".env", ".env.local"]>>;
953
+ }, "strip", z.ZodTypeAny, {
954
+ name: string;
955
+ file?: ".env" | ".env.local" | undefined;
956
+ description?: string | undefined;
957
+ default?: string | undefined;
958
+ required?: boolean | undefined;
959
+ secret?: boolean | undefined;
960
+ }, {
961
+ name: string;
962
+ file?: ".env" | ".env.local" | undefined;
963
+ description?: string | undefined;
964
+ default?: string | undefined;
965
+ required?: boolean | undefined;
966
+ secret?: boolean | undefined;
967
+ }>, "many">>;
832
968
  default: z.ZodOptional<z.ZodBoolean>;
833
969
  } & {
834
970
  modes: z.ZodArray<z.ZodString, "many">;
@@ -904,6 +1040,14 @@ export declare const AddOnInfoSchema: z.ZodObject<{
904
1040
  addOnSpecialSteps?: string[] | undefined;
905
1041
  createSpecialSteps?: string[] | undefined;
906
1042
  postInitSpecialSteps?: string[] | undefined;
1043
+ envVars?: {
1044
+ name: string;
1045
+ file?: ".env" | ".env.local" | undefined;
1046
+ description?: string | undefined;
1047
+ default?: string | undefined;
1048
+ required?: boolean | undefined;
1049
+ secret?: boolean | undefined;
1050
+ }[] | undefined;
907
1051
  integrations?: {
908
1052
  type?: string | undefined;
909
1053
  code?: string | undefined;
@@ -963,6 +1107,14 @@ export declare const AddOnInfoSchema: z.ZodObject<{
963
1107
  addOnSpecialSteps?: string[] | undefined;
964
1108
  createSpecialSteps?: string[] | undefined;
965
1109
  postInitSpecialSteps?: string[] | undefined;
1110
+ envVars?: {
1111
+ name: string;
1112
+ file?: ".env" | ".env.local" | undefined;
1113
+ description?: string | undefined;
1114
+ default?: string | undefined;
1115
+ required?: boolean | undefined;
1116
+ secret?: boolean | undefined;
1117
+ }[] | undefined;
966
1118
  integrations?: {
967
1119
  type?: string | undefined;
968
1120
  code?: string | undefined;
@@ -1068,6 +1220,28 @@ export declare const AddOnCompiledSchema: z.ZodObject<{
1068
1220
  default: string;
1069
1221
  description?: string | undefined;
1070
1222
  }>]>>>;
1223
+ envVars: z.ZodOptional<z.ZodArray<z.ZodObject<{
1224
+ name: z.ZodString;
1225
+ description: z.ZodOptional<z.ZodString>;
1226
+ required: z.ZodOptional<z.ZodBoolean>;
1227
+ default: z.ZodOptional<z.ZodString>;
1228
+ secret: z.ZodOptional<z.ZodBoolean>;
1229
+ file: z.ZodOptional<z.ZodEnum<[".env", ".env.local"]>>;
1230
+ }, "strip", z.ZodTypeAny, {
1231
+ name: string;
1232
+ file?: ".env" | ".env.local" | undefined;
1233
+ description?: string | undefined;
1234
+ default?: string | undefined;
1235
+ required?: boolean | undefined;
1236
+ secret?: boolean | undefined;
1237
+ }, {
1238
+ name: string;
1239
+ file?: ".env" | ".env.local" | undefined;
1240
+ description?: string | undefined;
1241
+ default?: string | undefined;
1242
+ required?: boolean | undefined;
1243
+ secret?: boolean | undefined;
1244
+ }>, "many">>;
1071
1245
  default: z.ZodOptional<z.ZodBoolean>;
1072
1246
  } & {
1073
1247
  modes: z.ZodArray<z.ZodString, "many">;
@@ -1149,6 +1323,14 @@ export declare const AddOnCompiledSchema: z.ZodObject<{
1149
1323
  addOnSpecialSteps?: string[] | undefined;
1150
1324
  createSpecialSteps?: string[] | undefined;
1151
1325
  postInitSpecialSteps?: string[] | undefined;
1326
+ envVars?: {
1327
+ name: string;
1328
+ file?: ".env" | ".env.local" | undefined;
1329
+ description?: string | undefined;
1330
+ default?: string | undefined;
1331
+ required?: boolean | undefined;
1332
+ secret?: boolean | undefined;
1333
+ }[] | undefined;
1152
1334
  integrations?: {
1153
1335
  type?: string | undefined;
1154
1336
  code?: string | undefined;
@@ -1211,6 +1393,14 @@ export declare const AddOnCompiledSchema: z.ZodObject<{
1211
1393
  addOnSpecialSteps?: string[] | undefined;
1212
1394
  createSpecialSteps?: string[] | undefined;
1213
1395
  postInitSpecialSteps?: string[] | undefined;
1396
+ envVars?: {
1397
+ name: string;
1398
+ file?: ".env" | ".env.local" | undefined;
1399
+ description?: string | undefined;
1400
+ default?: string | undefined;
1401
+ required?: boolean | undefined;
1402
+ secret?: boolean | undefined;
1403
+ }[] | undefined;
1214
1404
  integrations?: {
1215
1405
  type?: string | undefined;
1216
1406
  code?: string | undefined;
@@ -1274,6 +1464,9 @@ export interface Options {
1274
1464
  chosenAddOns: Array<AddOn>;
1275
1465
  addOnOptions: Record<string, Record<string, any>>;
1276
1466
  starter?: Starter | undefined;
1467
+ routerOnly?: boolean;
1468
+ includeExamples?: boolean;
1469
+ envVarValues?: Record<string, string>;
1277
1470
  }
1278
1471
  export type SerializedOptions = Omit<Options, 'chosenAddOns' | 'starter' | 'framework'> & {
1279
1472
  chosenAddOns: Array<string>;
package/dist/types.js CHANGED
@@ -75,6 +75,16 @@ export const AddOnBaseSchema = z.object({
75
75
  createSpecialSteps: z.array(z.string()).optional(),
76
76
  postInitSpecialSteps: z.array(z.string()).optional(),
77
77
  options: AddOnOptionsSchema.optional(),
78
+ envVars: z
79
+ .array(z.object({
80
+ name: z.string(),
81
+ description: z.string().optional(),
82
+ required: z.boolean().optional(),
83
+ default: z.string().optional(),
84
+ secret: z.boolean().optional(),
85
+ file: z.enum(['.env', '.env.local']).optional(),
86
+ }))
87
+ .optional(),
78
88
  default: z.boolean().optional(),
79
89
  });
80
90
  export const StarterSchema = AddOnBaseSchema.extend({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/create",
3
- "version": "0.61.3",
3
+ "version": "0.61.5",
4
4
  "description": "TanStack Application Builder Engine",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/create-app.ts CHANGED
@@ -16,6 +16,51 @@ import { runSpecialSteps } from './special-steps/index.js'
16
16
 
17
17
  import type { Environment, FileBundleHandler, Options } from './types.js'
18
18
 
19
+ function isDemoRoutePath(path?: string) {
20
+ if (!path) return false
21
+ const normalized = path.replace(/\\/g, '/')
22
+ return (
23
+ normalized.includes('/routes/demo/') ||
24
+ normalized.includes('/routes/demo.') ||
25
+ normalized.includes('/routes/example/') ||
26
+ normalized.includes('/routes/example.')
27
+ )
28
+ }
29
+
30
+ function stripExamplesFromOptions(options: Options): Options {
31
+ if (options.includeExamples !== false) {
32
+ return options
33
+ }
34
+
35
+ const chosenAddOns = options.chosenAddOns
36
+ .filter((addOn) => addOn.type !== 'example')
37
+ .map((addOn) => {
38
+ const filteredRoutes = (addOn.routes || []).filter(
39
+ (route) =>
40
+ !isDemoRoutePath(route.path) &&
41
+ !(route.url && route.url.startsWith('/demo')),
42
+ )
43
+
44
+ return {
45
+ ...addOn,
46
+ routes: filteredRoutes,
47
+ getFiles: async () => {
48
+ const files = await addOn.getFiles()
49
+ return files.filter((file) => !isDemoRoutePath(file))
50
+ },
51
+ getDeletedFiles: async () => {
52
+ const deletedFiles = await addOn.getDeletedFiles()
53
+ return deletedFiles.filter((file) => !isDemoRoutePath(file))
54
+ },
55
+ }
56
+ })
57
+
58
+ return {
59
+ ...options,
60
+ chosenAddOns,
61
+ }
62
+ }
63
+
19
64
  async function writeFiles(environment: Environment, options: Options) {
20
65
  const templateFileFromContent = createTemplateFile(environment, options)
21
66
 
@@ -235,6 +280,32 @@ async function runCommandsAndInstallDependencies(
235
280
  await installShadcnComponents(environment, options.targetDir, options)
236
281
  }
237
282
 
283
+ async function seedEnvValues(environment: Environment, options: Options) {
284
+ const envVarValues = options.envVarValues || {}
285
+ const entries = Object.entries(envVarValues)
286
+ if (entries.length === 0) return
287
+
288
+ const envLocalPath = resolve(options.targetDir, '.env.local')
289
+ if (!environment.exists(envLocalPath)) {
290
+ return
291
+ }
292
+
293
+ let envContents = await environment.readFile(envLocalPath)
294
+ for (const [key, value] of entries) {
295
+ const escapedValue = value.replace(/\n/g, '\\n')
296
+ const nextLine = `${key}=${escapedValue}`
297
+ const pattern = new RegExp(`^${key}=.*$`, 'm')
298
+
299
+ if (pattern.test(envContents)) {
300
+ envContents = envContents.replace(pattern, nextLine)
301
+ } else {
302
+ envContents += `${envContents.endsWith('\n') ? '' : '\n'}${nextLine}\n`
303
+ }
304
+ }
305
+
306
+ await environment.writeFile(envLocalPath, envContents)
307
+ }
308
+
238
309
  function report(environment: Environment, options: Options) {
239
310
  const warnings: Array<string> = []
240
311
  for (const addOn of options.chosenAddOns) {
@@ -282,10 +353,13 @@ Please read the README.md file for information on testing, styling, adding route
282
353
  }
283
354
 
284
355
  export async function createApp(environment: Environment, options: Options) {
356
+ const effectiveOptions = stripExamplesFromOptions(options)
357
+
285
358
  environment.startRun()
286
- await writeFiles(environment, options)
287
- await runCommandsAndInstallDependencies(environment, options)
359
+ await writeFiles(environment, effectiveOptions)
360
+ await seedEnvValues(environment, effectiveOptions)
361
+ await runCommandsAndInstallDependencies(environment, effectiveOptions)
288
362
  environment.finishRun()
289
363
 
290
- report(environment, options)
364
+ report(environment, effectiveOptions)
291
365
  }
@@ -1,4 +1,4 @@
1
- import { readFile } from 'node:fs/promises'
1
+ import { readFile, watch } from 'node:fs/promises'
2
2
  import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
3
3
  import { basename, dirname, resolve } from 'node:path'
4
4
 
@@ -36,6 +36,22 @@ const COMPILED_FILE = 'add-on.json'
36
36
 
37
37
  const ASSETS_DIR = 'assets'
38
38
 
39
+ const ADD_ON_DEV_IGNORE_PREFIXES = [
40
+ '.add-on/',
41
+ '.git/',
42
+ 'node_modules/',
43
+ '.turbo/',
44
+ 'dist/',
45
+ ]
46
+
47
+ function shouldIgnoreDevPath(path: string) {
48
+ const normalized = path.replace(/\\/g, '/')
49
+ if (normalized === COMPILED_FILE) return true
50
+ return ADD_ON_DEV_IGNORE_PREFIXES.some((prefix) =>
51
+ normalized.startsWith(prefix),
52
+ )
53
+ }
54
+
39
55
  export function camelCase(str: string) {
40
56
  return str
41
57
  .split(/(\.|-|\/)/)
@@ -122,6 +138,11 @@ export async function readOrGenerateAddOnInfo(
122
138
  },
123
139
  dependsOn: options.chosenAddOns,
124
140
  } as AddOnInfo)
141
+
142
+ if (!info.version) {
143
+ info.version = '0.0.1'
144
+ }
145
+
125
146
  return info
126
147
  }
127
148
 
@@ -213,6 +234,56 @@ export async function initAddOn(environment: Environment) {
213
234
  await compileAddOn(environment)
214
235
  }
215
236
 
237
+ export async function devAddOn(environment: Environment) {
238
+ await initAddOn(environment)
239
+
240
+ environment.info(
241
+ 'Add-on dev mode is running.',
242
+ 'Watching project files and recompiling add-on output on changes. Press Ctrl+C to stop.',
243
+ )
244
+
245
+ const abortController = new AbortController()
246
+ let debounceTimeout: ReturnType<typeof setTimeout> | undefined
247
+
248
+ const rerun = async () => {
249
+ try {
250
+ await updateAddOnInfo(environment)
251
+ await compileAddOn(environment)
252
+ environment.info('Add-on updated.', 'Compiled add-on.json and refreshed .add-on')
253
+ } catch (error) {
254
+ const message = error instanceof Error ? error.message : String(error)
255
+ environment.error('Failed to rebuild add-on.', message)
256
+ }
257
+ }
258
+
259
+ process.once('SIGINT', () => {
260
+ abortController.abort()
261
+ })
262
+
263
+ try {
264
+ for await (const event of watch(process.cwd(), {
265
+ recursive: true,
266
+ signal: abortController.signal,
267
+ })) {
268
+ const file = event.filename?.toString()
269
+ if (!file || shouldIgnoreDevPath(file)) continue
270
+
271
+ if (debounceTimeout) {
272
+ clearTimeout(debounceTimeout)
273
+ }
274
+
275
+ debounceTimeout = setTimeout(() => {
276
+ void rerun()
277
+ }, 200)
278
+ }
279
+ } catch (error) {
280
+ const message = error instanceof Error ? error.message : String(error)
281
+ if (!message.includes('aborted')) {
282
+ throw error
283
+ }
284
+ }
285
+ }
286
+
216
287
  export async function loadRemoteAddOn(url: string): Promise<AddOn> {
217
288
  const response = await fetch(url)
218
289
  const jsonContent = await response.json()
@@ -27,7 +27,7 @@ const COMPILED_FILE = 'starter.json'
27
27
  export async function readOrGenerateStarterInfo(
28
28
  options: PersistedOptions,
29
29
  ): Promise<StarterInfo> {
30
- return existsSync(INFO_FILE)
30
+ const info = existsSync(INFO_FILE)
31
31
  ? JSON.parse((await readFile(INFO_FILE)).toString())
32
32
  : {
33
33
  id: `${options.projectName}-starter`,
@@ -51,6 +51,12 @@ export async function readOrGenerateStarterInfo(
51
51
  dependsOn: options.chosenAddOns,
52
52
  typescript: true,
53
53
  }
54
+
55
+ if (!info.version) {
56
+ info.version = '0.0.1'
57
+ }
58
+
59
+ return info
54
60
  }
55
61
 
56
62
  async function loadCurrentStarterInfo(environment: Environment) {
@@ -28,5 +28,14 @@
28
28
  "jsName": "ClerkProvider",
29
29
  "path": "src/integrations/clerk/provider.tsx"
30
30
  }
31
+ ],
32
+ "envVars": [
33
+ {
34
+ "name": "VITE_CLERK_PUBLISHABLE_KEY",
35
+ "description": "Clerk publishable key",
36
+ "required": true,
37
+ "secret": false,
38
+ "file": ".env.local"
39
+ }
31
40
  ]
32
41
  }
@@ -23,5 +23,21 @@
23
23
  "path": "src/integrations/convex/provider.tsx",
24
24
  "jsName": "ConvexProvider"
25
25
  }
26
+ ],
27
+ "envVars": [
28
+ {
29
+ "name": "CONVEX_DEPLOYMENT",
30
+ "description": "Convex deployment name",
31
+ "required": false,
32
+ "secret": false,
33
+ "file": ".env.local"
34
+ },
35
+ {
36
+ "name": "VITE_CONVEX_URL",
37
+ "description": "Convex deployment URL",
38
+ "required": true,
39
+ "secret": false,
40
+ "file": ".env.local"
41
+ }
26
42
  ]
27
43
  }
@@ -3,7 +3,6 @@ node_modules
3
3
  dist
4
4
  dist-ssr
5
5
  *.local
6
- count.txt
7
6
  .env
8
7
  .nitro
9
8
  .tanstack
@@ -0,0 +1,13 @@
1
+ <% if (!routerOnly) { ignoreFile() } %>
2
+ <!doctype html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title><%= projectName %></title>
8
+ </head>
9
+ <body>
10
+ <div id="app"></div>
11
+ <script type="module" src="/src/main.tsx"></script>
12
+ </body>
13
+ </html>
@@ -0,0 +1,24 @@
1
+ <% if (!routerOnly) { ignoreFile() } %>
2
+ import React from 'react'
3
+ import ReactDOM from 'react-dom/client'
4
+ import { RouterProvider, createRouter } from '@tanstack/react-router'
5
+ import { routeTree } from './routeTree.gen'
6
+
7
+ const router = createRouter({
8
+ routeTree,
9
+ defaultPreload: 'intent',
10
+ scrollRestoration: true,
11
+ })
12
+
13
+ declare module '@tanstack/react-router' {
14
+ interface Register {
15
+ router: typeof router
16
+ }
17
+ }
18
+
19
+ const rootElement = document.getElementById('app')!
20
+
21
+ if (!rootElement.innerHTML) {
22
+ const root = ReactDOM.createRoot(rootElement)
23
+ root.render(<RouterProvider router={router} />)
24
+ }
@@ -1,3 +1,33 @@
1
+ <% if (routerOnly) { %>
2
+ import { Outlet, createRootRoute } from '@tanstack/react-router'
3
+ import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'
4
+ import { TanStackDevtools } from '@tanstack/react-devtools'
5
+
6
+ import '../styles.css'
7
+
8
+ export const Route = createRootRoute({
9
+ component: RootComponent,
10
+ })
11
+
12
+ function RootComponent() {
13
+ return (
14
+ <>
15
+ <Outlet />
16
+ <TanStackDevtools
17
+ config={{
18
+ position: 'bottom-right',
19
+ }}
20
+ plugins={[
21
+ {
22
+ name: 'TanStack Router',
23
+ render: <TanStackRouterDevtoolsPanel />,
24
+ },
25
+ ]}
26
+ />
27
+ </>
28
+ )
29
+ }
30
+ <% } else { %>
1
31
  <% let hasContext = addOnEnabled["apollo-client"] || addOnEnabled["tanstack-query"]; %>
2
32
  import {
3
33
  HeadContent, Scripts, <% if (hasContext) { %>createRootRouteWithContext<% } else { %>createRootRoute<% } %> } from '@tanstack/react-router'
@@ -93,3 +123,4 @@ function RootDocument({ children }: { children: React.ReactNode }) {
93
123
  </html>
94
124
  )
95
125
  }
126
+ <% } %>