create-m5kdev 0.21.3 → 0.21.4
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/package.json +1 -1
- package/templates/minimal-app/.cursor/rules/module-module-guide.mdc +18 -20
- package/templates/minimal-app/AGENTS.md.tpl +4 -3
- package/templates/minimal-app/apps/email/src/emails/accountDeletionEmail.tsx.tpl +8 -4
- package/templates/minimal-app/apps/server/AGENTS.md.tpl +6 -5
- package/templates/minimal-app/apps/server/drizzle/generate-schema.ts.tpl +1 -5
- package/templates/minimal-app/apps/server/drizzle/seed.ts.tpl +96 -27
- package/templates/minimal-app/apps/server/src/app.ts.tpl +84 -64
- package/templates/minimal-app/apps/server/src/generated/schema.ts.tpl +13 -0
- package/templates/minimal-app/apps/server/src/index.ts.tpl +4 -1
- package/templates/minimal-app/apps/server/src/lib/auth.ts.tpl +7 -1
- package/templates/minimal-app/apps/server/src/modules/posts/posts.db.ts.tpl +1 -1
- package/templates/minimal-app/apps/server/src/modules/posts/posts.grants.ts.tpl +40 -40
- package/templates/minimal-app/apps/server/src/modules/posts/posts.module.ts.tpl +5 -11
- package/templates/minimal-app/apps/server/src/modules/posts/posts.repository.ts.tpl +2 -2
- package/templates/minimal-app/apps/server/src/modules/posts/posts.service.ts.tpl +4 -4
- package/templates/minimal-app/apps/server/src/modules/posts/posts.trpc.ts.tpl +1 -1
- package/templates/minimal-app/apps/server/src/types.ts.tpl +1 -3
- package/templates/minimal-app/apps/server/tsconfig.json.tpl +1 -0
- package/templates/minimal-app/apps/shared/.env.example.tpl +1 -0
- package/templates/minimal-app/apps/shared/.env.tpl +1 -0
- package/templates/minimal-app/apps/shared/src/modules/app/app.constants.ts.tpl +2 -0
- package/templates/minimal-app/apps/webapp/package.json.tpl +0 -1
- package/templates/minimal-app/apps/webapp/public/push-sw.js +2 -2
- package/templates/minimal-app/apps/webapp/src/Layout.tsx.tpl +51 -40
- package/templates/minimal-app/apps/webapp/src/Providers.tsx.tpl +21 -11
- package/templates/minimal-app/apps/webapp/src/Router.tsx.tpl +76 -20
- package/templates/minimal-app/apps/webapp/src/modules/notification/PushNotificationsPanel.tsx.tpl +12 -16
- package/templates/minimal-app/apps/webapp/src/modules/posts/PostsRoute.tsx.tpl +121 -119
- package/templates/minimal-app/apps/webapp/src/utils/trpc.ts.tpl +5 -3
- package/templates/minimal-app/apps/webapp/translations/en/blog-app.json.tpl +13 -1
- package/templates/minimal-app/apps/webapp/tsconfig.json.tpl +1 -0
- package/templates/minimal-app/pnpm-workspace.yaml.tpl +8 -8
- package/templates/minimal-app/apps/server/src/modules.ts.tpl +0 -33
- package/templates/minimal-app/apps/server/src/repository.ts.tpl +0 -6
- package/templates/minimal-app/apps/server/src/schema-modules.ts.tpl +0 -19
- package/templates/minimal-app/apps/server/src/service.ts.tpl +0 -7
- package/templates/minimal-app/apps/server/src/trpc.ts.tpl +0 -6
- package/templates/minimal-app/apps/server/src/workflow.ts.tpl +0 -4
- package/templates/minimal-app/apps/webapp/src/components/TrpcQueryProvider.tsx.tpl +0 -61
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
POST_FILTER_VALUES,
|
|
3
|
-
POSTS_PAGE_SIZE,
|
|
4
|
-
} from "{{PACKAGE_SCOPE}}/shared/modules/posts/posts.constants";
|
|
5
|
-
import type {
|
|
6
|
-
PostCreateInputSchema,
|
|
7
|
-
PostPublishInputSchema,
|
|
8
|
-
PostSoftDeleteInputSchema,
|
|
9
|
-
PostsListInputSchema,
|
|
10
|
-
PostsListOutputSchema,
|
|
11
|
-
PostUpdateInputSchema,
|
|
12
|
-
} from "{{PACKAGE_SCOPE}}/shared/modules/posts/posts.schema";
|
|
13
1
|
import {
|
|
14
2
|
Button,
|
|
15
3
|
Card,
|
|
@@ -23,6 +11,18 @@ import {
|
|
|
23
11
|
TextArea,
|
|
24
12
|
} from "@heroui/react";
|
|
25
13
|
import { useDialog } from "@m5kdev/web-ui/components/DialogProvider";
|
|
14
|
+
import {
|
|
15
|
+
POST_FILTER_VALUES,
|
|
16
|
+
POSTS_PAGE_SIZE,
|
|
17
|
+
} from "{{PACKAGE_SCOPE}}/shared/modules/posts/posts.constants";
|
|
18
|
+
import type {
|
|
19
|
+
PostCreateInputSchema,
|
|
20
|
+
PostPublishInputSchema,
|
|
21
|
+
PostSoftDeleteInputSchema,
|
|
22
|
+
PostsListInputSchema,
|
|
23
|
+
PostsListOutputSchema,
|
|
24
|
+
PostUpdateInputSchema,
|
|
25
|
+
} from "{{PACKAGE_SCOPE}}/shared/modules/posts/posts.schema";
|
|
26
26
|
import { type UseQueryOptions, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
27
27
|
import {
|
|
28
28
|
ArrowLeftIcon,
|
|
@@ -78,7 +78,7 @@ function getReadingTime(content: string): string {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
export function PostsRoute() {
|
|
81
|
-
const { t } = useTranslation("blog
|
|
81
|
+
const { t } = useTranslation("blog{{PACKAGE_SCOPE}}");
|
|
82
82
|
const trpc = useTRPC();
|
|
83
83
|
const queryClient = useQueryClient();
|
|
84
84
|
const showDialog = useDialog();
|
|
@@ -235,7 +235,7 @@ export function PostsRoute() {
|
|
|
235
235
|
showDialog({
|
|
236
236
|
title: t("posts.deleteDialog.title"),
|
|
237
237
|
description: t("posts.deleteDialog.body"),
|
|
238
|
-
|
|
238
|
+
intent: "danger",
|
|
239
239
|
cancelable: true,
|
|
240
240
|
confirmLabel: t("posts.deleteDialog.confirm"),
|
|
241
241
|
cancelLabel: t("posts.deleteDialog.cancel"),
|
|
@@ -268,11 +268,7 @@ export function PostsRoute() {
|
|
|
268
268
|
</h2>
|
|
269
269
|
<p className="mt-4 max-w-2xl text-sm leading-7 text-muted-ink">{t("posts.hero.body")}</p>
|
|
270
270
|
<div className="mt-6 flex flex-wrap gap-3">
|
|
271
|
-
<Button
|
|
272
|
-
className="rounded-full"
|
|
273
|
-
variant="primary"
|
|
274
|
-
onPress={openCreate}
|
|
275
|
-
>
|
|
271
|
+
<Button className="rounded-full" variant="primary" onPress={openCreate}>
|
|
276
272
|
<span className="inline-flex items-center gap-2">
|
|
277
273
|
<PlusIcon className="h-4 w-4" />
|
|
278
274
|
{t("posts.hero.new")}
|
|
@@ -337,17 +333,25 @@ export function PostsRoute() {
|
|
|
337
333
|
</Select.Trigger>
|
|
338
334
|
<Select.Popover>
|
|
339
335
|
<ListBox>
|
|
340
|
-
<ListBox.Item
|
|
336
|
+
<ListBox.Item
|
|
337
|
+
className="text-sm"
|
|
338
|
+
id={`${statusFieldId}-all`}
|
|
339
|
+
textValue={t("posts.filters.all")}
|
|
340
|
+
>
|
|
341
341
|
{t("posts.filters.all")}
|
|
342
342
|
<ListBox.ItemIndicator />
|
|
343
343
|
</ListBox.Item>
|
|
344
|
-
<ListBox.Item
|
|
344
|
+
<ListBox.Item
|
|
345
|
+
className="text-sm"
|
|
346
|
+
id={`${statusFieldId}-draft`}
|
|
347
|
+
textValue={t("posts.filters.draft")}
|
|
348
|
+
>
|
|
345
349
|
{t("posts.filters.draft")}
|
|
346
350
|
<ListBox.ItemIndicator />
|
|
347
351
|
</ListBox.Item>
|
|
348
352
|
<ListBox.Item
|
|
349
353
|
className="text-sm"
|
|
350
|
-
id=
|
|
354
|
+
id={`${statusFieldId}-published`}
|
|
351
355
|
textValue={t("posts.filters.published")}
|
|
352
356
|
>
|
|
353
357
|
{t("posts.filters.published")}
|
|
@@ -395,6 +399,7 @@ export function PostsRoute() {
|
|
|
395
399
|
deleteMutation.isPending && deleteMutation.variables?.id === row.id;
|
|
396
400
|
|
|
397
401
|
return (
|
|
402
|
+
// biome-ignore lint/a11y/useSemanticElements: post row card with nested action buttons
|
|
398
403
|
<Card
|
|
399
404
|
key={row.id}
|
|
400
405
|
role="button"
|
|
@@ -621,103 +626,100 @@ export function PostsRoute() {
|
|
|
621
626
|
}}
|
|
622
627
|
>
|
|
623
628
|
<Modal.Backdrop>
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
>
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
</form>
|
|
719
|
-
</Modal.Dialog>
|
|
720
|
-
</Modal.Container>
|
|
629
|
+
<Modal.Container scroll="inside" size="lg" className="max-w-5xl">
|
|
630
|
+
<Modal.Dialog>
|
|
631
|
+
<form className="contents" onSubmit={onSubmit}>
|
|
632
|
+
<Modal.Header className="flex flex-col gap-2 px-6 pt-6">
|
|
633
|
+
<p className="text-[0.68rem] font-semibold uppercase tracking-[0.28em] text-amber-700/80">
|
|
634
|
+
{editorState.id ? t("posts.editor.editEyebrow") : t("posts.editor.newEyebrow")}
|
|
635
|
+
</p>
|
|
636
|
+
<Modal.Heading className="font-editorial text-4xl leading-none text-ink">
|
|
637
|
+
{editorState.id ? t("posts.editor.editTitle") : t("posts.editor.newTitle")}
|
|
638
|
+
</Modal.Heading>
|
|
639
|
+
</Modal.Header>
|
|
640
|
+
<Modal.Body className="grid gap-4 px-6 pb-2">
|
|
641
|
+
<div className="grid gap-2">
|
|
642
|
+
<Label className="text-sm font-medium" htmlFor={editorTitleId}>
|
|
643
|
+
{t("posts.editor.fields.title")}
|
|
644
|
+
</Label>
|
|
645
|
+
<Input
|
|
646
|
+
id={editorTitleId}
|
|
647
|
+
className="rounded-lg"
|
|
648
|
+
variant="secondary"
|
|
649
|
+
value={editorState.title}
|
|
650
|
+
onChange={(event) =>
|
|
651
|
+
setEditorState((state) => ({ ...state, title: event.target.value }))
|
|
652
|
+
}
|
|
653
|
+
required
|
|
654
|
+
/>
|
|
655
|
+
</div>
|
|
656
|
+
<div className="grid gap-2">
|
|
657
|
+
<Label className="text-sm font-medium" htmlFor={editorSlugId}>
|
|
658
|
+
{t("posts.editor.fields.slug")}
|
|
659
|
+
</Label>
|
|
660
|
+
<Input
|
|
661
|
+
id={editorSlugId}
|
|
662
|
+
className="rounded-lg"
|
|
663
|
+
variant="secondary"
|
|
664
|
+
value={editorState.slug}
|
|
665
|
+
onChange={(event) =>
|
|
666
|
+
setEditorState((state) => ({ ...state, slug: event.target.value }))
|
|
667
|
+
}
|
|
668
|
+
/>
|
|
669
|
+
</div>
|
|
670
|
+
<div className="grid gap-2">
|
|
671
|
+
<Label className="text-sm font-medium" htmlFor={editorExcerptId}>
|
|
672
|
+
{t("posts.editor.fields.excerpt")}
|
|
673
|
+
</Label>
|
|
674
|
+
<TextArea
|
|
675
|
+
id={editorExcerptId}
|
|
676
|
+
className="rounded-lg min-h-[5.5rem]"
|
|
677
|
+
variant="secondary"
|
|
678
|
+
rows={3}
|
|
679
|
+
value={editorState.excerpt}
|
|
680
|
+
onChange={(event) =>
|
|
681
|
+
setEditorState((state) => ({ ...state, excerpt: event.target.value }))
|
|
682
|
+
}
|
|
683
|
+
/>
|
|
684
|
+
</div>
|
|
685
|
+
<div className="grid gap-2">
|
|
686
|
+
<Label className="text-sm font-medium" htmlFor={editorContentId}>
|
|
687
|
+
{t("posts.editor.fields.content")}
|
|
688
|
+
</Label>
|
|
689
|
+
<TextArea
|
|
690
|
+
id={editorContentId}
|
|
691
|
+
className="rounded-lg min-h-[12rem]"
|
|
692
|
+
variant="secondary"
|
|
693
|
+
rows={10}
|
|
694
|
+
value={editorState.content}
|
|
695
|
+
onChange={(event) =>
|
|
696
|
+
setEditorState((state) => ({ ...state, content: event.target.value }))
|
|
697
|
+
}
|
|
698
|
+
required
|
|
699
|
+
/>
|
|
700
|
+
</div>
|
|
701
|
+
</Modal.Body>
|
|
702
|
+
<Modal.Footer className="px-6 pb-6">
|
|
703
|
+
<Button
|
|
704
|
+
className="rounded-full"
|
|
705
|
+
variant="tertiary"
|
|
706
|
+
type="button"
|
|
707
|
+
onPress={() => setIsEditorOpen(false)}
|
|
708
|
+
>
|
|
709
|
+
{t("posts.editor.cancel")}
|
|
710
|
+
</Button>
|
|
711
|
+
<Button
|
|
712
|
+
className="rounded-full"
|
|
713
|
+
variant="primary"
|
|
714
|
+
type="submit"
|
|
715
|
+
isPending={createMutation.isPending || updateMutation.isPending}
|
|
716
|
+
>
|
|
717
|
+
{editorState.id ? t("posts.editor.save") : t("posts.editor.create")}
|
|
718
|
+
</Button>
|
|
719
|
+
</Modal.Footer>
|
|
720
|
+
</form>
|
|
721
|
+
</Modal.Dialog>
|
|
722
|
+
</Modal.Container>
|
|
721
723
|
</Modal.Backdrop>
|
|
722
724
|
</Modal>
|
|
723
725
|
</div>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { useAppTRPC } from "@m5kdev/frontend/modules/app/hooks/useAppTrpc";
|
|
1
2
|
import type { AppRouter } from "{{PACKAGE_SCOPE}}/server/types";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import type { TRPCOptionsProxy } from "@trpc/tanstack-react-query";
|
|
4
|
+
export function useTRPC(): TRPCOptionsProxy<AppRouter> {
|
|
5
|
+
return useAppTRPC<AppRouter>();
|
|
6
|
+
}
|
|
@@ -12,7 +12,13 @@
|
|
|
12
12
|
"auth": "Better Auth"
|
|
13
13
|
},
|
|
14
14
|
"navigation": {
|
|
15
|
-
"posts": "Posts"
|
|
15
|
+
"posts": "Posts",
|
|
16
|
+
"members": "Members",
|
|
17
|
+
"childOrgs": "Child orgs",
|
|
18
|
+
"orgPreferences": "Org preferences",
|
|
19
|
+
"profile": "Profile",
|
|
20
|
+
"invites": "Invites",
|
|
21
|
+
"admin": "Admin"
|
|
16
22
|
},
|
|
17
23
|
"push": {
|
|
18
24
|
"eyebrow": "Browser push",
|
|
@@ -117,5 +123,11 @@
|
|
|
117
123
|
"deleted": "Post archived.",
|
|
118
124
|
"validation": "Title and content are required."
|
|
119
125
|
}
|
|
126
|
+
},
|
|
127
|
+
"auth": {
|
|
128
|
+
"header": {
|
|
129
|
+
"eyebrow": "Framework Starter",
|
|
130
|
+
"tagline": "A minimal m5kdev starter with auth, tRPC, and one polished posts module."
|
|
131
|
+
}
|
|
120
132
|
}
|
|
121
133
|
}
|
|
@@ -3,18 +3,17 @@ packages:
|
|
|
3
3
|
|
|
4
4
|
catalog:
|
|
5
5
|
'@biomejs/biome': 2.2.0
|
|
6
|
-
'@heroui/react': 3.0.
|
|
7
|
-
'@heroui/styles': 3.0.
|
|
6
|
+
'@heroui/react': 3.0.3
|
|
7
|
+
'@heroui/styles': 3.0.3
|
|
8
8
|
'@libsql/client': 0.17.0
|
|
9
|
-
'@m5kdev/backend': 0.
|
|
10
|
-
'@m5kdev/commons': 0.
|
|
11
|
-
'@m5kdev/config': 0.
|
|
12
|
-
'@m5kdev/frontend': 0.
|
|
13
|
-
'@m5kdev/web-ui': 0.
|
|
9
|
+
'@m5kdev/backend': 0.21.3
|
|
10
|
+
'@m5kdev/commons': 0.21.3
|
|
11
|
+
'@m5kdev/config': 0.21.3
|
|
12
|
+
'@m5kdev/frontend': 0.21.3
|
|
13
|
+
'@m5kdev/web-ui': 0.21.3
|
|
14
14
|
'@react-email/components': 1.0.1
|
|
15
15
|
'@tailwindcss/vite': 4.1.11
|
|
16
16
|
'@tanstack/react-query': 5.83.0
|
|
17
|
-
'@tanstack/react-query-devtools': 5.83.0
|
|
18
17
|
'@trpc/client': 11.4.3
|
|
19
18
|
'@trpc/server': 11.4.3
|
|
20
19
|
'@trpc/tanstack-react-query': 11.4.3
|
|
@@ -32,6 +31,7 @@ catalog:
|
|
|
32
31
|
drizzle-orm: 0.44.3
|
|
33
32
|
express: 4.21.2
|
|
34
33
|
i18next: 25.3.2
|
|
34
|
+
ioredis: 5.7.0
|
|
35
35
|
lucide-react: 0.488.0
|
|
36
36
|
neverthrow: 8.2.0
|
|
37
37
|
nuqs: 2.4.3
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { defineBackendModules } from "@m5kdev/backend/app";
|
|
2
|
-
import { AuthModule } from "@m5kdev/backend/modules/auth/auth.module";
|
|
3
|
-
import { EmailModule } from "@m5kdev/backend/modules/email/email.module";
|
|
4
|
-
import { NotificationModule } from "@m5kdev/backend/modules/notification/notification.module";
|
|
5
|
-
import { WorkflowModule } from "@m5kdev/backend/modules/workflow/workflow.module";
|
|
6
|
-
import { templates } from "{{PACKAGE_SCOPE}}/email";
|
|
7
|
-
import { PostsModule } from "./modules/posts/posts.module";
|
|
8
|
-
|
|
9
|
-
export const emailBackendModule = new EmailModule(templates as never);
|
|
10
|
-
|
|
11
|
-
export const authBackendModule = new AuthModule();
|
|
12
|
-
|
|
13
|
-
export const workflowBackendModule = new WorkflowModule({
|
|
14
|
-
queues: {
|
|
15
|
-
fast: { concurrency: 5 },
|
|
16
|
-
},
|
|
17
|
-
defaultQueue: "fast",
|
|
18
|
-
defaults: {
|
|
19
|
-
timeout: 60_000,
|
|
20
|
-
jobOptions: { removeOnComplete: { age: 3600 } },
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
export const notificationBackendModule = new NotificationModule();
|
|
25
|
-
export const postsBackendModule = new PostsModule();
|
|
26
|
-
|
|
27
|
-
export const backendModules = defineBackendModules([
|
|
28
|
-
emailBackendModule,
|
|
29
|
-
authBackendModule,
|
|
30
|
-
workflowBackendModule,
|
|
31
|
-
notificationBackendModule,
|
|
32
|
-
postsBackendModule,
|
|
33
|
-
] as const);
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { builtBackendApp } from "./app";
|
|
2
|
-
|
|
3
|
-
export const authRepository = builtBackendApp.modules.auth.repositories.auth;
|
|
4
|
-
export const workflowRepository = builtBackendApp.modules.workflow.repositories.workflow;
|
|
5
|
-
export const notificationRepository = builtBackendApp.modules.notification.repositories.notification;
|
|
6
|
-
export const postsRepository = builtBackendApp.modules.posts.repositories.posts;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { defineBackendModule, defineBackendModules } from "@m5kdev/backend/app";
|
|
2
|
-
import {
|
|
3
|
-
authBackendModule,
|
|
4
|
-
notificationBackendModule,
|
|
5
|
-
postsBackendModule,
|
|
6
|
-
workflowBackendModule,
|
|
7
|
-
} from "./modules";
|
|
8
|
-
|
|
9
|
-
export const emailSchemaModule = defineBackendModule({
|
|
10
|
-
id: "email",
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
export const backendSchemaModules = defineBackendModules([
|
|
14
|
-
emailSchemaModule,
|
|
15
|
-
authBackendModule,
|
|
16
|
-
workflowBackendModule,
|
|
17
|
-
notificationBackendModule,
|
|
18
|
-
postsBackendModule,
|
|
19
|
-
] as const);
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { builtBackendApp, emailService } from "./app";
|
|
2
|
-
|
|
3
|
-
export { emailService };
|
|
4
|
-
|
|
5
|
-
export const authService = builtBackendApp.modules.auth.services.auth;
|
|
6
|
-
export const postsService = builtBackendApp.modules.posts.services.posts;
|
|
7
|
-
export const notificationService = builtBackendApp.modules.notification.services.notification;
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import type { AppRouter } from "{{PACKAGE_SCOPE}}/server/types";
|
|
2
|
-
import { transformer } from "@m5kdev/commons/utils/trpc";
|
|
3
|
-
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
4
|
-
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
|
5
|
-
import { createTRPCClient, httpBatchLink } from "@trpc/client";
|
|
6
|
-
import { type ReactNode, useState } from "react";
|
|
7
|
-
import { TRPCProvider } from "@/utils/trpc";
|
|
8
|
-
|
|
9
|
-
let browserQueryClient: QueryClient | undefined;
|
|
10
|
-
|
|
11
|
-
function createQueryClient() {
|
|
12
|
-
return new QueryClient({
|
|
13
|
-
defaultOptions: {
|
|
14
|
-
queries: {
|
|
15
|
-
staleTime: 60 * 1000,
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function getQueryClient() {
|
|
22
|
-
if (typeof window === "undefined") {
|
|
23
|
-
return createQueryClient();
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (!browserQueryClient) {
|
|
27
|
-
browserQueryClient = createQueryClient();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return browserQueryClient;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function TrpcQueryProvider({ children }: { children: ReactNode }) {
|
|
34
|
-
const queryClient = getQueryClient();
|
|
35
|
-
const [trpcClient] = useState(() =>
|
|
36
|
-
createTRPCClient<AppRouter>({
|
|
37
|
-
links: [
|
|
38
|
-
httpBatchLink({
|
|
39
|
-
url: `${import.meta.env.VITE_SERVER_URL}/trpc`,
|
|
40
|
-
fetch(url, options) {
|
|
41
|
-
return fetch(url, {
|
|
42
|
-
...options,
|
|
43
|
-
body: options?.body ? (options.body as BodyInit | null | undefined) : undefined,
|
|
44
|
-
credentials: "include",
|
|
45
|
-
});
|
|
46
|
-
},
|
|
47
|
-
transformer,
|
|
48
|
-
}),
|
|
49
|
-
],
|
|
50
|
-
})
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<QueryClientProvider client={queryClient}>
|
|
55
|
-
<TRPCProvider trpcClient={trpcClient} queryClient={queryClient}>
|
|
56
|
-
{children}
|
|
57
|
-
</TRPCProvider>
|
|
58
|
-
<ReactQueryDevtools client={queryClient} />
|
|
59
|
-
</QueryClientProvider>
|
|
60
|
-
);
|
|
61
|
-
}
|