pejay-ui 1.2.2 → 1.3.1

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 (61) hide show
  1. package/README.md +17 -2
  2. package/package.json +2 -2
  3. package/registry.json +33 -1
  4. package/templates/notes/create-pejay.md +222 -0
  5. package/templates/notes/notes-v1.md +516 -0
  6. package/templates/notes/notes-v2.md +764 -0
  7. package/templates/notes/notes-v3.md +574 -0
  8. package/templates/notes/notes-v4.md +811 -0
  9. package/templates/notes/notes-v5.md +579 -0
  10. package/templates/notes/notes-vf+1.md +311 -0
  11. package/templates/notes/notes-vfinal.md +852 -0
  12. package/templates/scaffolds/axios/api/index.ts +40 -0
  13. package/templates/scaffolds/axios/api/one.api.ts +94 -0
  14. package/templates/scaffolds/axios/endpoints.ts +9 -0
  15. package/templates/scaffolds/axios/index.ts +26 -0
  16. package/templates/scaffolds/axios/interceptors.ts +103 -0
  17. package/templates/scaffolds/axios/request.ts +32 -0
  18. package/templates/scaffolds/react-router/hook/useRouterSearch.ts +8 -0
  19. package/templates/scaffolds/react-router/router/guards/private.route.tsx +1 -0
  20. package/templates/scaffolds/react-router/router/index.ts +26 -0
  21. package/templates/scaffolds/react-router/router/layouts/error.layout.tsx +1 -1
  22. package/templates/scaffolds/redux-store/middlewares.ts +0 -0
  23. package/templates/scaffolds/redux-store/reducers.ts +30 -0
  24. package/templates/scaffolds/redux-store/selector/one.selector.ts +43 -0
  25. package/templates/scaffolds/redux-store/selector/two.selector.ts +11 -0
  26. package/templates/scaffolds/redux-store/slices/one.slice.ts +202 -0
  27. package/templates/scaffolds/redux-store/slices/two.slice.ts +21 -0
  28. package/templates/scaffolds/redux-store/store.ts +38 -0
  29. package/templates/scaffolds/rtk-query/baseApi.ts +24 -0
  30. package/templates/scaffolds/rtk-query/baseQuery.ts +12 -0
  31. package/templates/scaffolds/rtk-query/endpoints/api.one.ts +82 -0
  32. package/templates/scaffolds/rtk-query/endpoints/index.ts +1 -0
  33. package/templates/scaffolds/rtk-query/middlewares.ts +11 -0
  34. package/templates/scaffolds/rtk-query/queryTags.ts +13 -0
  35. package/templates/scaffolds/tanstack-query/api-base.ts +68 -68
  36. package/templates/scaffolds/tanstack-query/api-queries.ts +0 -19
  37. package/templates/scaffolds/tanstack-query/client.ts +8 -0
  38. package/templates/scaffolds/tanstack-query/module/index.ts +12 -12
  39. package/templates/scaffolds/tanstack-query/module/keys.ts +17 -17
  40. package/templates/scaffolds/tanstack-query/module/mappers.ts +15 -15
  41. package/templates/scaffolds/tanstack-query/module/mutations.ts +59 -55
  42. package/templates/scaffolds/tanstack-query/module/queries.ts +145 -156
  43. package/templates/scaffolds/tanstack-query/module/services.ts +74 -66
  44. package/templates/scaffolds/tanstack-router/layout/404.layout.tsx +3 -0
  45. package/templates/scaffolds/tanstack-router/layout/app.layout.tsx +10 -0
  46. package/templates/scaffolds/tanstack-router/layout/auth.layout.tsx +10 -0
  47. package/templates/scaffolds/tanstack-router/layout/error.layout.tsx +3 -0
  48. package/templates/scaffolds/tanstack-router/page/auth/login.tsx +3 -0
  49. package/templates/scaffolds/tanstack-router/page/one/index.tsx +3 -0
  50. package/templates/scaffolds/tanstack-router/page/one/one-id.tsx +128 -0
  51. package/templates/scaffolds/tanstack-router/router.ts +90 -0
  52. package/templates/scaffolds/tanstack-router/routes/_404.tsx +0 -0
  53. package/templates/scaffolds/tanstack-router/routes/__root.tsx +9 -0
  54. package/templates/scaffolds/tanstack-router/routes/_app.tsx +6 -0
  55. package/templates/scaffolds/tanstack-router/routes/_auth.tsx +6 -0
  56. package/templates/scaffolds/tanstack-router/routes/_error.tsx +0 -0
  57. package/templates/scaffolds/tanstack-router/routes/auth/login.tsx +6 -0
  58. package/templates/scaffolds/tanstack-router/routes/one/$id.tsx +191 -0
  59. package/templates/scaffolds/tanstack-router/routes/one/index.tsx +6 -0
  60. package/templates/scripts/setup.bat +284 -0
  61. package/templates/scripts/setup.ps1 +318 -0
@@ -0,0 +1,579 @@
1
+ # TanStack Router + TanStack Query Integration
2
+
3
+ This document covers:
4
+
5
+ ```txt
6
+ Loader
7
+ ensureQueryData()
8
+ useSuspenseQuery()
9
+ pendingComponent
10
+ Complete Route Lifecycle
11
+ ```
12
+
13
+ These concepts are the foundation of most production TanStack Router applications.
14
+
15
+ ---
16
+
17
+ # Why Use Loaders With TanStack Query?
18
+
19
+ Without a loader:
20
+
21
+ ```txt
22
+ Navigate
23
+
24
+ Component Mounts
25
+
26
+ useSuspenseQuery()
27
+
28
+ Request Starts
29
+
30
+ Data Arrives
31
+ ```
32
+
33
+ The request only starts after the component renders.
34
+
35
+ ---
36
+
37
+ With a loader:
38
+
39
+ ```txt
40
+ Navigate
41
+
42
+ Loader Runs First
43
+
44
+ Query Starts
45
+
46
+ Data Cached
47
+
48
+ Component Mounts
49
+ ```
50
+
51
+ The route prepares data before rendering.
52
+
53
+ ---
54
+
55
+ # ensureQueryData()
56
+
57
+ The most common loader pattern.
58
+
59
+ Example:
60
+
61
+ ```tsx
62
+ export const Route = createFileRoute(
63
+ "/_app/users/$id"
64
+ )({
65
+ loader: ({ context, params }) =>
66
+ context.queryClient.ensureQueryData(
67
+ apiQueries.users.detail(params.id)
68
+ ),
69
+
70
+ component: UserDetails,
71
+ });
72
+ ```
73
+
74
+ ---
75
+
76
+ ## What Does It Do?
77
+
78
+ Think:
79
+
80
+ ```txt
81
+ If Data Exists In Cache
82
+
83
+ Return Cached Data
84
+
85
+ Else
86
+
87
+ Fetch Data
88
+
89
+ Save To Cache
90
+
91
+ Return Data
92
+ ```
93
+
94
+ ---
95
+
96
+ ## Benefits
97
+
98
+ ```txt
99
+ ✓ Uses Query Cache
100
+
101
+ ✓ Avoids Duplicate Requests
102
+
103
+ ✓ Faster Navigation
104
+
105
+ ✓ Works With Suspense
106
+
107
+ ✓ Integrates Naturally With Mutations
108
+ ```
109
+
110
+ ---
111
+
112
+ # Complete Example
113
+
114
+ Query Factory:
115
+
116
+ ```tsx
117
+ export const userQueries = {
118
+ detail: (id: string) =>
119
+ queryOptions({
120
+ queryKey: ["user", id],
121
+
122
+ queryFn: () =>
123
+ UserService.getById(id),
124
+ }),
125
+ };
126
+ ```
127
+
128
+ ---
129
+
130
+ Route:
131
+
132
+ ```tsx
133
+ export const Route = createFileRoute(
134
+ "/_app/users/$id"
135
+ )({
136
+ loader: ({ context, params }) =>
137
+ context.queryClient.ensureQueryData(
138
+ userQueries.detail(params.id)
139
+ ),
140
+
141
+ component: UserDetails,
142
+ });
143
+ ```
144
+
145
+ ---
146
+
147
+ Component:
148
+
149
+ ```tsx
150
+ export default function UserDetails() {
151
+ const { id } =
152
+ Route.useParams();
153
+
154
+ const { data } =
155
+ useSuspenseQuery(
156
+ userQueries.detail(id)
157
+ );
158
+
159
+ return (
160
+ <div>
161
+ {data.name}
162
+ </div>
163
+ );
164
+ }
165
+ ```
166
+
167
+ ---
168
+
169
+ # Important Question
170
+
171
+ Why call:
172
+
173
+ ```tsx
174
+ useSuspenseQuery(
175
+ userQueries.detail(id)
176
+ )
177
+ ```
178
+
179
+ again inside the component?
180
+
181
+ Didn't the loader already fetch the data?
182
+
183
+ ---
184
+
185
+ Answer:
186
+
187
+ ```txt
188
+ Loader
189
+
190
+ Puts Data Into Cache
191
+
192
+ Component
193
+
194
+ Reads Data From Cache
195
+ ```
196
+
197
+ No second request occurs.
198
+
199
+ The component is simply reading cached data.
200
+
201
+ ---
202
+
203
+ # Request Lifecycle
204
+
205
+ First Visit:
206
+
207
+ ```txt
208
+ Navigate
209
+
210
+ Loader Runs
211
+
212
+ ensureQueryData()
213
+
214
+ API Request
215
+
216
+ Query Cache Updated
217
+
218
+ Component Mounts
219
+
220
+ useSuspenseQuery()
221
+
222
+ Reads Cache
223
+ ```
224
+
225
+ ---
226
+
227
+ Second Visit:
228
+
229
+ ```txt
230
+ Navigate
231
+
232
+ Loader Runs
233
+
234
+ Cache Already Exists
235
+
236
+ No Request
237
+
238
+ Component Mounts
239
+
240
+ useSuspenseQuery()
241
+
242
+ Reads Cache
243
+ ```
244
+
245
+ ---
246
+
247
+ # pendingComponent
248
+
249
+ Provides route-level loading UI.
250
+
251
+ Example:
252
+
253
+ ```tsx
254
+ export const Route = createFileRoute(
255
+ "/_app/users/$id"
256
+ )({
257
+ pendingComponent:
258
+ UserSkeleton,
259
+
260
+ loader: ({ context, params }) =>
261
+ context.queryClient.ensureQueryData(
262
+ userQueries.detail(params.id)
263
+ ),
264
+
265
+ component: UserDetails,
266
+ });
267
+ ```
268
+
269
+ ---
270
+
271
+ # What Happens?
272
+
273
+ ```txt
274
+ Navigate
275
+
276
+ Loader Starts
277
+
278
+ Data Not Ready
279
+
280
+ pendingComponent Appears
281
+
282
+ Data Arrives
283
+
284
+ Real Component Renders
285
+ ```
286
+
287
+ ---
288
+
289
+ # Why Suspense Works So Well Here
290
+
291
+ Component:
292
+
293
+ ```tsx
294
+ const { data } =
295
+ useSuspenseQuery(
296
+ userQueries.detail(id)
297
+ );
298
+ ```
299
+
300
+ Normally Suspense would wait for the query.
301
+
302
+ But:
303
+
304
+ ```txt
305
+ Loader
306
+
307
+ Already Loaded Query
308
+
309
+ Cache Ready
310
+
311
+ Suspense Instantly Resolves
312
+ ```
313
+
314
+ Meaning:
315
+
316
+ ```txt
317
+ Less Loading
318
+ Less Flicker
319
+ Better UX
320
+ ```
321
+
322
+ ---
323
+
324
+ # useQuery vs useSuspenseQuery
325
+
326
+ ## useQuery
327
+
328
+ ```tsx
329
+ const {
330
+ data,
331
+ isLoading,
332
+ error,
333
+ } = useQuery(
334
+ userQueries.detail(id)
335
+ );
336
+ ```
337
+
338
+ Requires handling:
339
+
340
+ ```tsx
341
+ if (isLoading) {
342
+ return <Loader />;
343
+ }
344
+ ```
345
+
346
+ ---
347
+
348
+ ## useSuspenseQuery
349
+
350
+ ```tsx
351
+ const { data } =
352
+ useSuspenseQuery(
353
+ userQueries.detail(id)
354
+ );
355
+ ```
356
+
357
+ No:
358
+
359
+ ```tsx
360
+ isLoading
361
+ ```
362
+
363
+ No:
364
+
365
+ ```tsx
366
+ if (loading)
367
+ ```
368
+
369
+ No:
370
+
371
+ ```tsx
372
+ if (data)
373
+ ```
374
+
375
+ Suspense guarantees data exists.
376
+
377
+ ---
378
+
379
+ # Typical TanStack Router Setup
380
+
381
+ Route:
382
+
383
+ ```tsx
384
+ export const Route = createFileRoute(
385
+ "/_app/users/$id"
386
+ )({
387
+ pendingComponent:
388
+ UserSkeleton,
389
+
390
+ loader: ({ context, params }) =>
391
+ context.queryClient.ensureQueryData(
392
+ userQueries.detail(params.id)
393
+ ),
394
+
395
+ component: UserDetails,
396
+ });
397
+ ```
398
+
399
+ ---
400
+
401
+ Component:
402
+
403
+ ```tsx
404
+ export default function UserDetails() {
405
+ const { id } =
406
+ Route.useParams();
407
+
408
+ const { data } =
409
+ useSuspenseQuery(
410
+ userQueries.detail(id)
411
+ );
412
+
413
+ return (
414
+ <div>{data.name}</div>
415
+ );
416
+ }
417
+ ```
418
+
419
+ This is probably the most common enterprise TanStack Router pattern.
420
+
421
+ ---
422
+
423
+ # When To Use Route.useLoaderData()
424
+
425
+ Example:
426
+
427
+ ```tsx
428
+ loader: async () => ({
429
+ pageTitle: "Users",
430
+ });
431
+ ```
432
+
433
+ Component:
434
+
435
+ ```tsx
436
+ const data =
437
+ Route.useLoaderData();
438
+ ```
439
+
440
+ Good for:
441
+
442
+ ```txt
443
+ Metadata
444
+ Configuration
445
+ Simple Route Information
446
+ ```
447
+
448
+ ---
449
+
450
+ # When To Use useSuspenseQuery()
451
+
452
+ Good for:
453
+
454
+ ```txt
455
+ API Data
456
+ Server Data
457
+ CRUD Screens
458
+ Tables
459
+ Detail Pages
460
+ Dashboards
461
+ ```
462
+
463
+ ---
464
+
465
+ # Complete Mental Model
466
+
467
+ ```txt
468
+ URL
469
+
470
+ Route Match
471
+
472
+ beforeLoad()
473
+
474
+ loader()
475
+
476
+ ensureQueryData()
477
+
478
+ Query Cache Filled
479
+
480
+ pendingComponent
481
+
482
+ Component Mounts
483
+
484
+ useSuspenseQuery()
485
+
486
+ Reads Cached Data
487
+ ```
488
+
489
+ ---
490
+
491
+ # Recommended Pattern For CRM Apps
492
+
493
+ ```tsx
494
+ beforeLoad()
495
+ ```
496
+
497
+ for:
498
+
499
+ ```txt
500
+ Auth
501
+ Permissions
502
+ Roles
503
+ ```
504
+
505
+ ---
506
+
507
+ ```tsx
508
+ loader()
509
+ ```
510
+
511
+ for:
512
+
513
+ ```txt
514
+ Prefetching Queries
515
+ ```
516
+
517
+ ---
518
+
519
+ ```tsx
520
+ ensureQueryData()
521
+ ```
522
+
523
+ for:
524
+
525
+ ```txt
526
+ Cache Population
527
+ ```
528
+
529
+ ---
530
+
531
+ ```tsx
532
+ pendingComponent()
533
+ ```
534
+
535
+ for:
536
+
537
+ ```txt
538
+ Page Skeletons
539
+ ```
540
+
541
+ ---
542
+
543
+ ```tsx
544
+ useSuspenseQuery()
545
+ ```
546
+
547
+ for:
548
+
549
+ ```txt
550
+ Reading Data
551
+ ```
552
+
553
+ ---
554
+
555
+ # Final Rule
556
+
557
+ If a page needs server data:
558
+
559
+ ```txt
560
+ Route
561
+
562
+ loader()
563
+
564
+ ensureQueryData()
565
+
566
+ useSuspenseQuery()
567
+ ```
568
+
569
+ If a page only needs route information:
570
+
571
+ ```txt
572
+ Route
573
+
574
+ loader()
575
+
576
+ Route.useLoaderData()
577
+ ```
578
+
579
+ This distinction alone will help keep TanStack Router applications clean and predictable.