create-fate 1.7.7 → 1.9.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/bin/create-fate.mjs +50 -8
- package/package.json +1 -1
- package/templates/fate/_shared/vue-app/package.json +12 -11
- package/templates/fate/_shared/vue-app/src/App.css +1 -6
- package/templates/fate/_shared/vue-app/vite.config.ts +12 -1
- package/templates/fate/drizzle/AGENTS.md +1 -1
- package/templates/fate/drizzle/_gitignore +1 -0
- package/templates/fate/drizzle/client/package.json +15 -15
- package/templates/fate/drizzle/client/pages/layout.tsx +2 -2
- package/templates/fate/drizzle/client/src/App.css +1 -6
- package/templates/fate/drizzle/package.json +6 -7
- package/templates/fate/drizzle/pnpm-workspace.yaml +6 -6
- package/templates/fate/drizzle/server/package.json +9 -9
- package/templates/fate/graphql/AGENTS.md +2 -2
- package/templates/fate/graphql/README.md +12 -0
- package/templates/fate/graphql/_gitignore +1 -0
- package/templates/fate/graphql/client/package.json +14 -14
- package/templates/fate/graphql/client/pages/index.tsx +1 -1
- package/templates/fate/graphql/client/pages/layout.tsx +2 -2
- package/templates/fate/graphql/client/pages/search.tsx +2 -2
- package/templates/fate/graphql/client/src/App.css +1 -6
- package/templates/fate/graphql/client/src/fate/graphql.ts +20 -0
- package/templates/fate/graphql/client/src/ui/CommentCard.tsx +1 -1
- package/templates/fate/graphql/client/src/ui/PostCard.tsx +1 -1
- package/templates/fate/graphql/client/src/ui/UserCard.tsx +1 -1
- package/templates/fate/graphql/client/vite.config.ts +1 -1
- package/templates/fate/graphql/package.json +6 -7
- package/templates/fate/graphql/pnpm-workspace.yaml +5 -5
- package/templates/fate/graphql/server/README.md +5 -4
- package/templates/fate/graphql/server/package.json +19 -19
- package/templates/fate/graphql/server/scripts/generate-graphql.tsx +7 -1
- package/templates/fate/graphql/server/src/graphql/fate.ts +0 -56
- package/templates/fate/graphql/server/src/graphql/schema.tsx +22 -3
- package/templates/fate/graphql/server/src/graphql/views.ts +0 -43
- package/templates/fate/graphql-client/AGENTS.md +20 -0
- package/templates/fate/graphql-client/README.md +16 -14
- package/templates/fate/graphql-client/_gitignore +1 -0
- package/templates/fate/graphql-client/package.json +14 -13
- package/templates/fate/graphql-client/pages/index.tsx +2 -2
- package/templates/fate/graphql-client/pnpm-workspace.yaml +5 -6
- package/templates/fate/graphql-client/src/App.css +1 -7
- package/templates/fate/graphql-client/src/fate/graphql.ts +7 -48
- package/templates/fate/graphql-client/src/fate/schema.graphql +48 -0
- package/templates/fate/graphql-client/vite.config.ts +1 -11
- package/templates/fate/http/AGENTS.md +1 -1
- package/templates/fate/http/_gitignore +1 -0
- package/templates/fate/http/client/package.json +13 -13
- package/templates/fate/http/client/pages/layout.tsx +2 -2
- package/templates/fate/http/client/src/App.css +1 -6
- package/templates/fate/http/package.json +6 -7
- package/templates/fate/http/pnpm-workspace.yaml +6 -6
- package/templates/fate/http/server/package.json +8 -8
- package/templates/fate/prisma/AGENTS.md +1 -1
- package/templates/fate/prisma/_gitignore +1 -0
- package/templates/fate/prisma/client/package.json +15 -15
- package/templates/fate/prisma/client/pages/layout.tsx +2 -2
- package/templates/fate/prisma/client/src/App.css +1 -6
- package/templates/fate/prisma/package.json +6 -7
- package/templates/fate/prisma/pnpm-workspace.yaml +5 -5
- package/templates/fate/prisma/server/package.json +8 -8
- package/templates/fate/void/AGENTS.md +23 -0
- package/templates/fate/void/_gitignore +1 -0
- package/templates/fate/void/db/migrations/20261015035853_better_auth_accounts.sql +3 -0
- package/templates/fate/void/db/migrations/meta/20261015035853_snapshot.json +918 -0
- package/templates/fate/void/db/migrations/meta/_journal.json +7 -0
- package/templates/fate/void/db/schema.ts +20 -3
- package/templates/fate/void/package.json +17 -17
- package/templates/fate/void/pnpm-workspace.yaml +7 -7
- package/templates/fate/void/src/App.css +1 -6
- package/templates/fate/void/vite.config.ts +0 -7
package/bin/create-fate.mjs
CHANGED
|
@@ -364,7 +364,7 @@ const reactPackageEntries = [
|
|
|
364
364
|
'react-fate',
|
|
365
365
|
];
|
|
366
366
|
|
|
367
|
-
const vueAgentsGuide = `# Using _fate_ for Vue applications
|
|
367
|
+
const vueAgentsGuide = (docsDir) => `# Using _fate_ for Vue applications
|
|
368
368
|
|
|
369
369
|
This guidance is for agents working in projects bootstrapped from the fate Vue template. It focuses on Vue-native composables for fate's view composition and request execution.
|
|
370
370
|
|
|
@@ -391,7 +391,7 @@ This guidance is for agents working in projects bootstrapped from the fate Vue t
|
|
|
391
391
|
- **\`useRequest\` only at route roots:** Create a dedicated \`useRequest\` call per screen root that pulls together all child views; do not scatter \`useRequest\` across leaf components unless it is necessary to issue a separate request.
|
|
392
392
|
- **fate client support:** fate's local client support files are maintained by the Vite/fate tooling. Do not manually edit \`.fate\` files; make the proper schema changes on the server and run \`pnpm fate:generate\` when working outside Vite dev.
|
|
393
393
|
|
|
394
|
-
|
|
394
|
+
Before working on fate, read only the relevant Markdown docs in \`${docsDir}/\`. Start with \`index.md\` to find guides, integrations, and API references; read \`guide/vue.md\` for Vue-specific APIs. The docs match the installed package version. Online documentation is at [fate.technology](https://fate.technology/).
|
|
395
395
|
|
|
396
396
|
## Review Checklist for Agents
|
|
397
397
|
|
|
@@ -482,9 +482,9 @@ import env from '../src/lib/env.ts';`,
|
|
|
482
482
|
envValues: `{
|
|
483
483
|
SERVER_URL: import.meta.env.VITE_SERVER_URL,
|
|
484
484
|
}`,
|
|
485
|
-
fateModule: '
|
|
485
|
+
fateModule: './src/fate/graphql.ts',
|
|
486
486
|
fateTransport: `transport: 'graphql',`,
|
|
487
|
-
typeModule: '
|
|
487
|
+
typeModule: './fate/graphql.ts',
|
|
488
488
|
},
|
|
489
489
|
'graphql-client': {
|
|
490
490
|
clientImports: ``,
|
|
@@ -651,6 +651,31 @@ const configureVueRootPackageJson = (targetPath) => {
|
|
|
651
651
|
writePackageJson(packagePath, packageJson);
|
|
652
652
|
};
|
|
653
653
|
|
|
654
|
+
const configureVueRootViteConfig = (targetPath) => {
|
|
655
|
+
const configPath = path.join(targetPath, 'vite.config.ts');
|
|
656
|
+
const config = fs.readFileSync(configPath, 'utf8');
|
|
657
|
+
fs.writeFileSync(
|
|
658
|
+
configPath,
|
|
659
|
+
config.replace(
|
|
660
|
+
'overrides: [',
|
|
661
|
+
`overrides: [
|
|
662
|
+
{
|
|
663
|
+
env: { browser: true },
|
|
664
|
+
files: ['**/*.vue'],
|
|
665
|
+
globals: {
|
|
666
|
+
defineEmits: 'readonly',
|
|
667
|
+
defineExpose: 'readonly',
|
|
668
|
+
defineModel: 'readonly',
|
|
669
|
+
defineOptions: 'readonly',
|
|
670
|
+
defineProps: 'readonly',
|
|
671
|
+
defineSlots: 'readonly',
|
|
672
|
+
withDefaults: 'readonly',
|
|
673
|
+
},
|
|
674
|
+
},`,
|
|
675
|
+
),
|
|
676
|
+
);
|
|
677
|
+
};
|
|
678
|
+
|
|
654
679
|
const configureVueVoidServerFiles = (frontendRoot) => {
|
|
655
680
|
const oldSessionUser = path.join(frontendRoot, 'src', 'user', 'SessionUser.tsx');
|
|
656
681
|
const nextSessionUser = path.join(frontendRoot, 'src', 'user', 'SessionUser.ts');
|
|
@@ -667,17 +692,25 @@ const configureVueVoidServerFiles = (frontendRoot) => {
|
|
|
667
692
|
);
|
|
668
693
|
};
|
|
669
694
|
|
|
670
|
-
const configureVueAgents = (targetPath) => {
|
|
695
|
+
const configureVueAgents = (targetPath, selectedVariant) => {
|
|
671
696
|
const agentsPath = path.join(targetPath, 'AGENTS.md');
|
|
697
|
+
const docsDir = path
|
|
698
|
+
.relative(
|
|
699
|
+
targetPath,
|
|
700
|
+
path.join(frontendRootForVariant(targetPath, selectedVariant), 'node_modules/vue-fate/docs'),
|
|
701
|
+
)
|
|
702
|
+
.split(path.sep)
|
|
703
|
+
.join('/');
|
|
704
|
+
const guide = vueAgentsGuide(docsDir);
|
|
672
705
|
if (!fs.existsSync(agentsPath)) {
|
|
673
|
-
fs.writeFileSync(agentsPath, `${
|
|
706
|
+
fs.writeFileSync(agentsPath, `${guide}\n`);
|
|
674
707
|
return;
|
|
675
708
|
}
|
|
676
709
|
|
|
677
710
|
const agents = fs.readFileSync(agentsPath, 'utf8');
|
|
678
711
|
const vitePlusIndex = agents.indexOf('<!--VITE PLUS START-->');
|
|
679
712
|
const suffix = vitePlusIndex === -1 ? agents : agents.slice(vitePlusIndex);
|
|
680
|
-
fs.writeFileSync(agentsPath, `${
|
|
713
|
+
fs.writeFileSync(agentsPath, `${guide}\n\n${suffix.trim()}\n`);
|
|
681
714
|
};
|
|
682
715
|
|
|
683
716
|
const configureVueReadme = (targetPath, selectedVariant) => {
|
|
@@ -763,6 +796,14 @@ const configureVueTemplate = (targetPath, selectedVariant) => {
|
|
|
763
796
|
fs.mkdirSync(frontendRoot, { recursive: true });
|
|
764
797
|
fs.cpSync(vueTemplatePackage(), frontendRoot, { recursive: true });
|
|
765
798
|
|
|
799
|
+
if (selectedVariant === 'graphql') {
|
|
800
|
+
fs.cpSync(
|
|
801
|
+
path.join(packageRoot, 'templates/fate/graphql/client/src/fate'),
|
|
802
|
+
path.join(frontendRoot, 'src/fate'),
|
|
803
|
+
{ recursive: true },
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
|
|
766
807
|
if (selectedVariant === 'void') {
|
|
767
808
|
configureVueVoidServerFiles(frontendRoot);
|
|
768
809
|
}
|
|
@@ -770,8 +811,9 @@ const configureVueTemplate = (targetPath, selectedVariant) => {
|
|
|
770
811
|
configureVuePackageJson(frontendRoot, selectedVariant, originalPackageJson);
|
|
771
812
|
if (frontendRoot !== targetPath) {
|
|
772
813
|
configureVueRootPackageJson(targetPath);
|
|
814
|
+
configureVueRootViteConfig(targetPath);
|
|
773
815
|
}
|
|
774
|
-
configureVueAgents(targetPath);
|
|
816
|
+
configureVueAgents(targetPath, selectedVariant);
|
|
775
817
|
if (selectedVariant === 'void') {
|
|
776
818
|
configureVueVoidDemoContent(targetPath);
|
|
777
819
|
}
|
package/package.json
CHANGED
|
@@ -18,27 +18,28 @@
|
|
|
18
18
|
"test:all": "vp check && vp test"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@lucide/vue": "^1.
|
|
21
|
+
"@lucide/vue": "^1.59.0",
|
|
22
22
|
"@nkzw/core": "^1.3.1",
|
|
23
23
|
"@nkzw/define-env": "^1.1.0",
|
|
24
|
-
"@trpc/client": "^11.
|
|
25
|
-
"@void/vue": "^
|
|
24
|
+
"@trpc/client": "^11.19.0",
|
|
25
|
+
"@void/vue": "^1.1.12",
|
|
26
26
|
"class-variance-authority": "^0.7.1",
|
|
27
27
|
"clsx": "^2.1.1",
|
|
28
|
-
"dotenv": "^
|
|
29
|
-
"graphql-sse": "^2.6.
|
|
30
|
-
"tailwind-merge": "^3.
|
|
31
|
-
"void": "^
|
|
32
|
-
"vue": "^3.5.
|
|
28
|
+
"dotenv": "^18.0.8",
|
|
29
|
+
"graphql-sse": "^2.6.3",
|
|
30
|
+
"tailwind-merge": "^3.7.0",
|
|
31
|
+
"void": "^1.1.12",
|
|
32
|
+
"vue": "^3.5.44",
|
|
33
33
|
"vue-fate": "latest"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@nkzw/eslint-plugin": "^2.0.0",
|
|
37
37
|
"@nkzw/oxlint-config": "^2.0.1",
|
|
38
|
-
"@oxc-node/core": "^0.1.
|
|
39
|
-
"@swc/core": "^1.16.
|
|
38
|
+
"@oxc-node/core": "^0.1.7",
|
|
39
|
+
"@swc/core": "^1.16.18",
|
|
40
40
|
"@tailwindcss/vite": "^4.3.3",
|
|
41
|
-
"@types/node": "^26.
|
|
41
|
+
"@types/node": "^26.6.5",
|
|
42
|
+
"@vitejs/plugin-vue": "^6.0.10",
|
|
42
43
|
"tailwindcss": "^4.3.3",
|
|
43
44
|
"typescript": "^7.0.2",
|
|
44
45
|
"vite": "catalog:",
|
|
@@ -2,12 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
body {
|
|
4
4
|
font-family:
|
|
5
|
-
system-ui,
|
|
6
|
-
-apple-system,
|
|
7
|
-
BlinkMacSystemFont,
|
|
8
|
-
'Segoe UI',
|
|
9
|
-
'Open Sans',
|
|
10
|
-
'Helvetica Neue',
|
|
5
|
+
system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Open Sans', 'Helvetica Neue',
|
|
11
6
|
sans-serif;
|
|
12
7
|
|
|
13
8
|
background-color: hsl(var(--background));
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import nkzw from '@nkzw/oxlint-config';
|
|
2
2
|
import tailwindcss from '@tailwindcss/vite';
|
|
3
|
+
import vue from '@vitejs/plugin-vue';
|
|
3
4
|
import { voidVue } from '@void/vue/plugin';
|
|
4
5
|
import { defineConfig, lazyPlugins } from 'vite-plus';
|
|
5
6
|
import { voidPlugin } from 'void';
|
|
@@ -7,6 +8,8 @@ import { fate } from 'vue-fate/vite';
|
|
|
7
8
|
|
|
8
9
|
/* __ENV_CONFIG__ */
|
|
9
10
|
|
|
11
|
+
const isTest = process.env.NODE_ENV === 'test' || process.env.VITEST;
|
|
12
|
+
|
|
10
13
|
export default defineConfig({
|
|
11
14
|
/* __BUILD_CONFIG__ */
|
|
12
15
|
optimizeDeps: {
|
|
@@ -31,6 +34,7 @@ export default defineConfig({
|
|
|
31
34
|
options: { typeAware: true, typeCheck: true },
|
|
32
35
|
overrides: [
|
|
33
36
|
{
|
|
37
|
+
env: { browser: true },
|
|
34
38
|
files: ['**/*.vue'],
|
|
35
39
|
globals: {
|
|
36
40
|
defineEmits: 'readonly',
|
|
@@ -42,13 +46,20 @@ export default defineConfig({
|
|
|
42
46
|
withDefaults: 'readonly',
|
|
43
47
|
},
|
|
44
48
|
},
|
|
49
|
+
{
|
|
50
|
+
files: ['db/seed.ts', '**/__tests__/**'],
|
|
51
|
+
rules: {
|
|
52
|
+
'no-console': 'off',
|
|
53
|
+
},
|
|
54
|
+
},
|
|
45
55
|
],
|
|
46
56
|
rules: {
|
|
47
57
|
'@typescript-eslint/no-explicit-any': 'off',
|
|
48
58
|
},
|
|
49
59
|
},
|
|
50
60
|
plugins: [
|
|
51
|
-
...(lazyPlugins(() => [tailwindcss(), voidPlugin(), voidVue()]) ??
|
|
61
|
+
...(lazyPlugins(() => [tailwindcss(), ...(isTest ? [vue()] : [voidPlugin(), voidVue()])]) ??
|
|
62
|
+
[]),
|
|
52
63
|
fate({
|
|
53
64
|
module: '__FATE_MODULE__',
|
|
54
65
|
/* __FATE_TRANSPORT__ */
|
|
@@ -29,7 +29,7 @@ This guidance is for agents working in projects bootstrapped from the fate templ
|
|
|
29
29
|
- **fate client support** fate's local client support files are maintained by the Vite/fate tooling. Do not manually edit `.fate` files; make the proper schema changes on the server and run `pnpm fate:generate` when working outside Vite dev.
|
|
30
30
|
- **Library Versions:** This repository uses the most recent releases of React, fate, Vite, tRPC, and more. You might not know about the new releases yet, please don't get confused. The versions you see are real, and there are no feature or version mismatches. You can search the internet for more information about them.
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Before working on fate, read only the relevant Markdown docs in `client/node_modules/react-fate/docs/`. Start with `index.md` to find guides, integrations, and API references. The docs match the installed package version. Online documentation is at [fate.technology](https://fate.technology/).
|
|
33
33
|
|
|
34
34
|
## Review Checklist for Agents
|
|
35
35
|
|
|
@@ -21,35 +21,35 @@
|
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@app/server": "workspace:*",
|
|
24
|
-
"@hono/node-server": "^2.1.
|
|
24
|
+
"@hono/node-server": "^2.1.5",
|
|
25
25
|
"@nkzw/core": "^1.3.1",
|
|
26
26
|
"@nkzw/define-env": "^1.1.0",
|
|
27
27
|
"@nkzw/stack": "^2.3.2",
|
|
28
|
-
"@radix-ui/react-slot": "^1.
|
|
29
|
-
"@trpc/client": "^11.
|
|
30
|
-
"@void/react": "^
|
|
31
|
-
"better-auth": "^1.7.
|
|
28
|
+
"@radix-ui/react-slot": "^1.5.0",
|
|
29
|
+
"@trpc/client": "^11.19.0",
|
|
30
|
+
"@void/react": "^1.1.12",
|
|
31
|
+
"better-auth": "^1.7.11",
|
|
32
32
|
"class-variance-authority": "^0.7.1",
|
|
33
33
|
"clsx": "^2.1.1",
|
|
34
34
|
"fbtee": "^5.0.0",
|
|
35
|
-
"lucide-react": "^1.
|
|
36
|
-
"react": "^19.3.
|
|
37
|
-
"react-dom": "^19.3.
|
|
38
|
-
"react-error-boundary": "^6.1.
|
|
35
|
+
"lucide-react": "^1.59.0",
|
|
36
|
+
"react": "^19.3.1",
|
|
37
|
+
"react-dom": "^19.3.1",
|
|
38
|
+
"react-error-boundary": "^6.1.6",
|
|
39
39
|
"react-fate": "latest",
|
|
40
|
-
"tailwind-merge": "^3.
|
|
41
|
-
"void": "^
|
|
40
|
+
"tailwind-merge": "^3.7.0",
|
|
41
|
+
"void": "^1.1.12"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@nkzw/fbtee-compiler": "^5.0.0",
|
|
45
45
|
"@nkzw/vite-plugin-fbtee": "^5.0.0",
|
|
46
46
|
"@tailwindcss/vite": "^4.3.3",
|
|
47
|
-
"@trpc/server": "^11.
|
|
48
|
-
"@types/node": "^26.
|
|
47
|
+
"@trpc/server": "^11.19.0",
|
|
48
|
+
"@types/node": "^26.6.5",
|
|
49
49
|
"@types/react": "^19.3.0",
|
|
50
50
|
"@types/react-dom": "^19.3.0",
|
|
51
|
-
"@vitejs/plugin-react": "^6.1.
|
|
52
|
-
"oxc-transform-react": "^0.
|
|
51
|
+
"@vitejs/plugin-react": "^6.1.2",
|
|
52
|
+
"oxc-transform-react": "^0.154.0",
|
|
53
53
|
"tailwindcss": "^4.3.3",
|
|
54
54
|
"vite": "catalog:",
|
|
55
55
|
"vite-plus": "catalog:"
|
|
@@ -23,7 +23,7 @@ const Thinking = () => (
|
|
|
23
23
|
);
|
|
24
24
|
|
|
25
25
|
export default function Layout({ children }: { children: ReactNode }) {
|
|
26
|
-
const { data: session } = AuthClient.useSession();
|
|
26
|
+
const { data: session, isPending } = AuthClient.useSession();
|
|
27
27
|
const userId = session?.user.id;
|
|
28
28
|
|
|
29
29
|
const fate = useMemo(
|
|
@@ -58,7 +58,7 @@ export default function Layout({ children }: { children: ReactNode }) {
|
|
|
58
58
|
<div className="min-h-screen bg-background text-foreground">
|
|
59
59
|
<div className="min-h-screen bg-[radial-gradient(circle_at_20%_20%,rgba(59,130,246,0.08),transparent_35%),radial-gradient(circle_at_80%_0,rgba(99,102,241,0.08),transparent_28%)]">
|
|
60
60
|
<Header />
|
|
61
|
-
{
|
|
61
|
+
{isPending ? (
|
|
62
62
|
<Thinking />
|
|
63
63
|
) : (
|
|
64
64
|
<FateClient client={fate} key={userId}>
|
|
@@ -2,12 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
body {
|
|
4
4
|
font-family:
|
|
5
|
-
system-ui,
|
|
6
|
-
-apple-system,
|
|
7
|
-
BlinkMacSystemFont,
|
|
8
|
-
'Segoe UI',
|
|
9
|
-
'Open Sans',
|
|
10
|
-
'Helvetica Neue',
|
|
5
|
+
system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Open Sans', 'Helvetica Neue',
|
|
11
6
|
sans-serif;
|
|
12
7
|
|
|
13
8
|
background-color: hsl(var(--background));
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"type": "module",
|
|
12
12
|
"scripts": {
|
|
13
|
-
"build": "dotenv -
|
|
13
|
+
"build": "dotenv run -f server/.env -- vp run --filter '@app/client' --filter '@app/server' build",
|
|
14
14
|
"dev": "npm-run-all --parallel dev:client dev:server",
|
|
15
15
|
"dev:client": "cd client && vp dev",
|
|
16
16
|
"dev:server": "cd server && vp run dev",
|
|
@@ -23,11 +23,10 @@
|
|
|
23
23
|
"@app/server": "workspace:*",
|
|
24
24
|
"@nkzw/eslint-plugin": "^2.0.0",
|
|
25
25
|
"@nkzw/oxlint-config": "^2.0.1",
|
|
26
|
-
"@oxc-node/core": "^0.1.
|
|
27
|
-
"@swc/core": "^1.16.
|
|
28
|
-
"@types/node": "^26.
|
|
29
|
-
"dotenv": "^
|
|
30
|
-
"dotenv-cli": "^11.0.0",
|
|
26
|
+
"@oxc-node/core": "^0.1.7",
|
|
27
|
+
"@swc/core": "^1.16.18",
|
|
28
|
+
"@types/node": "^26.6.5",
|
|
29
|
+
"dotenv": "^18.0.8",
|
|
31
30
|
"npm-run-all2": "^9.0.3",
|
|
32
31
|
"typescript": "^7.0.2",
|
|
33
32
|
"vite": "catalog:",
|
|
@@ -38,5 +37,5 @@
|
|
|
38
37
|
"node": ">=24.0.0",
|
|
39
38
|
"pnpm": ">=11.0.0"
|
|
40
39
|
},
|
|
41
|
-
"packageManager": "pnpm@
|
|
40
|
+
"packageManager": "pnpm@12.6.0"
|
|
42
41
|
}
|
|
@@ -4,16 +4,16 @@ packages:
|
|
|
4
4
|
|
|
5
5
|
allowBuilds:
|
|
6
6
|
'@swc/core': true
|
|
7
|
-
better-sqlite3:
|
|
7
|
+
better-sqlite3: false
|
|
8
8
|
drizzle-kit: true
|
|
9
9
|
esbuild: true
|
|
10
10
|
sharp: true
|
|
11
11
|
workerd: true
|
|
12
12
|
|
|
13
13
|
catalog:
|
|
14
|
-
vite: npm:@voidzero-dev/vite-plus-core@1.
|
|
15
|
-
vite-plus: 1.
|
|
16
|
-
vitest: 5.0.
|
|
14
|
+
vite: npm:@voidzero-dev/vite-plus-core@1.3.0
|
|
15
|
+
vite-plus: 1.3.0
|
|
16
|
+
vitest: 5.0.5
|
|
17
17
|
|
|
18
18
|
minimumReleaseAgeExclude:
|
|
19
19
|
- '@voidzero-dev/vite-plus-core'
|
|
@@ -28,8 +28,8 @@ onlyBuiltDependencies:
|
|
|
28
28
|
- unrs-resolver
|
|
29
29
|
|
|
30
30
|
overrides:
|
|
31
|
-
better-auth: 1.7.
|
|
32
|
-
drizzle-orm: 0.45.
|
|
31
|
+
better-auth: 1.7.11
|
|
32
|
+
drizzle-orm: 0.45.4
|
|
33
33
|
kysely: 0.28.17
|
|
34
34
|
vite: 'catalog:'
|
|
35
35
|
vitest: 'catalog:'
|
|
@@ -20,22 +20,22 @@
|
|
|
20
20
|
"drizzle": "drizzle-kit --config drizzle.config.ts"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@hono/node-server": "^2.1.
|
|
23
|
+
"@hono/node-server": "^2.1.5",
|
|
24
24
|
"@hono/trpc-server": "^0.4.2",
|
|
25
25
|
"@nkzw/core": "^1.3.1",
|
|
26
26
|
"@nkzw/define-env": "^1.1.0",
|
|
27
27
|
"@nkzw/fate": "latest",
|
|
28
|
-
"@trpc/server": "^11.
|
|
29
|
-
"better-auth": "^1.7.
|
|
30
|
-
"drizzle-orm": "^0.45.
|
|
31
|
-
"hono": "^4.13.
|
|
32
|
-
"pg": "
|
|
33
|
-
"zod": "^4.
|
|
28
|
+
"@trpc/server": "^11.19.0",
|
|
29
|
+
"better-auth": "^1.7.11",
|
|
30
|
+
"drizzle-orm": "^0.45.4",
|
|
31
|
+
"hono": "^4.13.13",
|
|
32
|
+
"pg": "8.23.1",
|
|
33
|
+
"zod": "^4.6.7"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@types/node": "^26.
|
|
36
|
+
"@types/node": "^26.6.5",
|
|
37
37
|
"@types/pg": "^8.23.1",
|
|
38
|
-
"drizzle-kit": "^0.31.
|
|
38
|
+
"drizzle-kit": "^0.31.11",
|
|
39
39
|
"nodemon": "^3.1.14",
|
|
40
40
|
"vite-plus": "catalog:"
|
|
41
41
|
},
|
|
@@ -23,13 +23,13 @@ This guidance is for agents working in projects bootstrapped from the fate templ
|
|
|
23
23
|
- **Use ViewRefs:** Pass references instead of raw data. Keep components focused on views and `ViewRef`s to let fate manage data masking and updates.
|
|
24
24
|
- **Co-locate data needs:** Keep view definitions near their components and compose them upward to the request root for predictable fetching.
|
|
25
25
|
- **Use Suspense:** Wrap pages in `Suspense`/`ErrorBoundary` instead of ad-hoc loading/error flags; fate aligns with Async React by design.
|
|
26
|
-
- **Do not duplicate types:**
|
|
26
|
+
- **Do not duplicate types:** Use `GraphQLEntities` from `client/.fate/schema.generated.ts` for GraphQL view types. The client mapping exports convenient aliases; avoid redefining entity shapes on the client. This ensures view selections stay type-safe end-to-end.
|
|
27
27
|
- **`useRequest` only at the root:** When adding routes or layouts, create a dedicated `useRequest` call per screen root that pulls together all child views; do not scatter `useRequest` across leaf components unless it's necessary to issue requests due to user input.
|
|
28
28
|
- **React Actions:** Prefer React Action-friendly UI primitives (buttons/forms that accept an `action` prop). If unavailable, wrap action calls with `startTransition` in `onClick` handlers.
|
|
29
29
|
- **fate client support** fate's local client support files are maintained by the Vite/fate tooling. Do not manually edit `.fate` files; make the proper schema changes on the server and run `pnpm fate:generate` when working outside Vite dev.
|
|
30
30
|
- **Library Versions:** This repository uses the most recent releases of React, fate, Vite, GraphQL, and more. You might not know about the new releases yet, please don't get confused. The versions you see are real, and there are no feature or version mismatches. You can search the internet for more information about them.
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Before working on fate, read only the relevant Markdown docs in `client/node_modules/react-fate/docs/`. Start with `index.md` to find guides, integrations, and API references. The docs match the installed package version. Online documentation is at [fate.technology](https://fate.technology/).
|
|
33
33
|
|
|
34
34
|
## Review Checklist for Agents
|
|
35
35
|
|
|
@@ -16,6 +16,18 @@ vp create fate -- --template graphql
|
|
|
16
16
|
|
|
17
17
|
Read the [Getting Started Guide](https://fate.technology/guide/core-concepts) to learn how to use _fate_ in your React applications.
|
|
18
18
|
|
|
19
|
+
## GraphQL Types
|
|
20
|
+
|
|
21
|
+
`client/src/fate/graphql.ts` imports the SDL exported from the Pothos schema during `dev:setup` and maps application root
|
|
22
|
+
and mutation names. Fate generates `client/.fate/schema.generated.ts` from that
|
|
23
|
+
schema; its `GraphQLEntities` types are used by the client views. Mutation inputs,
|
|
24
|
+
output nullability, and connection shapes also come from the schema.
|
|
25
|
+
|
|
26
|
+
Run `vp run --filter '@app/server' generate-graphql` after changing schema fields,
|
|
27
|
+
then `vp run fate:generate` to update the client contracts. The server's
|
|
28
|
+
Prisma data views implement live-event resolution and authorization; they are
|
|
29
|
+
independent of these generated client contracts.
|
|
30
|
+
|
|
19
31
|
## Technologies
|
|
20
32
|
|
|
21
33
|
This default template combines the Nakazawa Tech's [Web App Template](https://github.com/nkzw-tech/web-app-template) and [Server Template](https://github.com/nkzw-tech/server-template) into a monorepo, with unified tooling and _fate_ as the data client. It currently uses GraphQL with Pothos, Relay-style connections, and Prisma.
|
|
@@ -21,34 +21,34 @@
|
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@app/server": "workspace:*",
|
|
24
|
-
"@hono/node-server": "^2.1.
|
|
24
|
+
"@hono/node-server": "^2.1.5",
|
|
25
25
|
"@nkzw/core": "^1.3.1",
|
|
26
26
|
"@nkzw/define-env": "^1.1.0",
|
|
27
27
|
"@nkzw/stack": "^2.3.2",
|
|
28
|
-
"@radix-ui/react-slot": "^1.
|
|
29
|
-
"@void/react": "^
|
|
30
|
-
"better-auth": "^1.7.
|
|
28
|
+
"@radix-ui/react-slot": "^1.5.0",
|
|
29
|
+
"@void/react": "^1.1.12",
|
|
30
|
+
"better-auth": "^1.7.11",
|
|
31
31
|
"class-variance-authority": "^0.7.1",
|
|
32
32
|
"clsx": "^2.1.1",
|
|
33
33
|
"fbtee": "^5.0.0",
|
|
34
|
-
"graphql-sse": "^2.6.
|
|
35
|
-
"lucide-react": "^1.
|
|
36
|
-
"react": "^19.3.
|
|
37
|
-
"react-dom": "^19.3.
|
|
38
|
-
"react-error-boundary": "^6.1.
|
|
34
|
+
"graphql-sse": "^2.6.3",
|
|
35
|
+
"lucide-react": "^1.59.0",
|
|
36
|
+
"react": "^19.3.1",
|
|
37
|
+
"react-dom": "^19.3.1",
|
|
38
|
+
"react-error-boundary": "^6.1.6",
|
|
39
39
|
"react-fate": "latest",
|
|
40
|
-
"tailwind-merge": "^3.
|
|
41
|
-
"void": "^
|
|
40
|
+
"tailwind-merge": "^3.7.0",
|
|
41
|
+
"void": "^1.1.12"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@nkzw/fbtee-compiler": "^5.0.0",
|
|
45
45
|
"@nkzw/vite-plugin-fbtee": "^5.0.0",
|
|
46
46
|
"@tailwindcss/vite": "^4.3.3",
|
|
47
|
-
"@types/node": "^26.
|
|
47
|
+
"@types/node": "^26.6.5",
|
|
48
48
|
"@types/react": "^19.3.0",
|
|
49
49
|
"@types/react-dom": "^19.3.0",
|
|
50
|
-
"@vitejs/plugin-react": "^6.1.
|
|
51
|
-
"oxc-transform-react": "^0.
|
|
50
|
+
"@vitejs/plugin-react": "^6.1.2",
|
|
51
|
+
"oxc-transform-react": "^0.154.0",
|
|
52
52
|
"tailwindcss": "^4.3.3",
|
|
53
53
|
"vite": "catalog:",
|
|
54
54
|
"vite-plus": "catalog:"
|
|
@@ -22,7 +22,7 @@ const Thinking = () => (
|
|
|
22
22
|
);
|
|
23
23
|
|
|
24
24
|
export default function Layout({ children }: { children: ReactNode }) {
|
|
25
|
-
const { data: session } = AuthClient.useSession();
|
|
25
|
+
const { data: session, isPending } = AuthClient.useSession();
|
|
26
26
|
const userId = session?.user.id;
|
|
27
27
|
|
|
28
28
|
const fate = useMemo(
|
|
@@ -45,7 +45,7 @@ export default function Layout({ children }: { children: ReactNode }) {
|
|
|
45
45
|
<div className="min-h-screen bg-background text-foreground">
|
|
46
46
|
<div className="min-h-screen bg-[radial-gradient(circle_at_20%_20%,rgba(59,130,246,0.08),transparent_35%),radial-gradient(circle_at_80%_0,rgba(99,102,241,0.08),transparent_28%)]">
|
|
47
47
|
<Header />
|
|
48
|
-
{
|
|
48
|
+
{isPending ? (
|
|
49
49
|
<Thinking />
|
|
50
50
|
) : (
|
|
51
51
|
<FateClient client={fate} key={userId}>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { Comment, Post } from '@app/server/src/graphql/fate.ts';
|
|
2
1
|
import Stack, { VStack } from '@nkzw/stack';
|
|
3
2
|
import { fbs } from 'fbtee';
|
|
4
3
|
import { Suspense, useDeferredValue, useState } from 'react';
|
|
5
4
|
import { ErrorBoundary } from 'react-error-boundary';
|
|
6
5
|
import { useRequest, useView, view, ViewRef } from 'react-fate';
|
|
6
|
+
import type { Comment, Post } from '../src/fate/graphql.ts';
|
|
7
7
|
import cx from '../src/lib/cx.tsx';
|
|
8
8
|
import Card from '../src/ui/Card.tsx';
|
|
9
9
|
import CommentCard, { CommentView } from '../src/ui/CommentCard.tsx';
|
|
@@ -37,7 +37,7 @@ const SearchResults = ({ isStale, query }: { isStale: boolean; query: string })
|
|
|
37
37
|
commentSearch: { args: { query }, list: CommentSearchView },
|
|
38
38
|
});
|
|
39
39
|
|
|
40
|
-
if (commentSearch
|
|
40
|
+
if (!commentSearch?.length) {
|
|
41
41
|
return (
|
|
42
42
|
<p>
|
|
43
43
|
<fbt desc="No matches text">
|
|
@@ -2,12 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
body {
|
|
4
4
|
font-family:
|
|
5
|
-
system-ui,
|
|
6
|
-
-apple-system,
|
|
7
|
-
BlinkMacSystemFont,
|
|
8
|
-
'Segoe UI',
|
|
9
|
-
'Open Sans',
|
|
10
|
-
'Helvetica Neue',
|
|
5
|
+
system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Open Sans', 'Helvetica Neue',
|
|
11
6
|
sans-serif;
|
|
12
7
|
|
|
13
8
|
background-color: hsl(var(--background));
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import schema from '@app/server/src/graphql/schema.graphql?raw';
|
|
2
|
+
import type { GraphQLEntities } from '../../.fate/schema.generated.ts';
|
|
3
|
+
|
|
4
|
+
export type User = GraphQLEntities['User'];
|
|
5
|
+
export type Post = GraphQLEntities['Post'];
|
|
6
|
+
export type Comment = GraphQLEntities['Comment'];
|
|
7
|
+
|
|
8
|
+
export const fateGraphQL = {
|
|
9
|
+
mutations: {
|
|
10
|
+
'comment.add': { entity: 'Comment', field: 'commentAdd' },
|
|
11
|
+
'comment.delete': { entity: 'Comment', field: 'commentDelete' },
|
|
12
|
+
'post.add': { entity: 'Post', field: 'postAdd' },
|
|
13
|
+
'post.like': { entity: 'Post', field: 'postLike' },
|
|
14
|
+
'post.unlike': { entity: 'Post', field: 'postUnlike' },
|
|
15
|
+
'user.update': { entity: 'User', field: 'userUpdate' },
|
|
16
|
+
},
|
|
17
|
+
roots: { categories: {}, commentSearch: {}, events: {}, posts: {}, viewer: {} },
|
|
18
|
+
scalars: { DateTime: 'string' },
|
|
19
|
+
schema,
|
|
20
|
+
} as const;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { Comment } from '@app/server/src/graphql/fate.ts';
|
|
2
1
|
import Stack from '@nkzw/stack';
|
|
3
2
|
import { X } from 'lucide-react';
|
|
4
3
|
import { useView, view, ViewRef } from 'react-fate';
|
|
5
4
|
import { useFateClient } from 'react-fate';
|
|
5
|
+
import type { Comment } from '../fate/graphql.ts';
|
|
6
6
|
import { Button } from './Button.tsx';
|
|
7
7
|
import Link from './Link.tsx';
|
|
8
8
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { Comment as InlineComment, Post } from '@app/server/src/graphql/fate.ts';
|
|
2
1
|
import Stack, { VStack } from '@nkzw/stack';
|
|
3
2
|
import { cx } from 'class-variance-authority';
|
|
4
3
|
import { fbs } from 'fbtee';
|
|
@@ -21,6 +20,7 @@ import {
|
|
|
21
20
|
view,
|
|
22
21
|
ViewRef,
|
|
23
22
|
} from 'react-fate';
|
|
23
|
+
import type { Comment as InlineComment, Post } from '../fate/graphql.ts';
|
|
24
24
|
import { Button } from '../ui/Button.tsx';
|
|
25
25
|
import Card from '../ui/Card.tsx';
|
|
26
26
|
import AuthClient from '../user/AuthClient.tsx';
|