@cogito.ai/cli 0.3.4 → 0.4.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/dist/index.js +77 -6
- package/dist/templates/web-nextjs/apps/docs/.source/browser.ts +1 -1
- package/dist/templates/web-nextjs/apps/docs/.source/server.ts +3 -2
- package/dist/templates/web-nextjs/apps/docs/content/docs/decisions/meta.json +1 -1
- package/dist/templates/web-nextjs/apps/docs/content/docs/decisions/turbo-package-manager.mdx +70 -0
- package/dist/templates/web-nextjs/apps/docs/package.json +1 -1
- package/dist/templates/web-nextjs/apps/web/middleware.ts +6 -13
- package/dist/templates/web-nextjs/apps/web/package.json +26 -0
- package/dist/templates/web-nextjs/apps/web/src/app/[locale]/(auth)/login/page.tsx +87 -93
- package/dist/templates/web-nextjs/apps/web/src/app/[locale]/(auth)/signup/page.tsx +116 -98
- package/dist/templates/web-nextjs/apps/web/src/app/[locale]/(protected)/dashboard/page.tsx +38 -29
- package/dist/templates/web-nextjs/apps/web/src/app/[locale]/(protected)/layout.tsx +2 -5
- package/dist/templates/web-nextjs/apps/web/src/app/[locale]/layout.tsx +11 -8
- package/dist/templates/web-nextjs/apps/web/src/app/[locale]/privacy/page.tsx +23 -0
- package/dist/templates/web-nextjs/apps/web/src/app/[locale]/terms/page.tsx +23 -0
- package/dist/templates/web-nextjs/apps/web/src/app/route.ts +13 -0
- package/dist/templates/web-nextjs/apps/web/src/components/dashboard/app-sidebar.tsx +188 -0
- package/dist/templates/web-nextjs/apps/web/src/components/dashboard/chart-area-interactive.tsx +291 -0
- package/dist/templates/web-nextjs/apps/web/src/components/dashboard/data-table.tsx +807 -0
- package/dist/templates/web-nextjs/apps/web/src/components/dashboard/data.json +614 -0
- package/dist/templates/web-nextjs/apps/web/src/components/dashboard/nav-documents.tsx +92 -0
- package/dist/templates/web-nextjs/apps/web/src/components/dashboard/nav-main.tsx +58 -0
- package/dist/templates/web-nextjs/apps/web/src/components/dashboard/nav-secondary.tsx +42 -0
- package/dist/templates/web-nextjs/apps/web/src/components/dashboard/nav-user.tsx +118 -0
- package/dist/templates/web-nextjs/apps/web/src/components/dashboard/page.tsx +40 -0
- package/dist/templates/web-nextjs/apps/web/src/components/dashboard/section-cards.tsx +102 -0
- package/dist/templates/web-nextjs/apps/web/src/components/dashboard/site-header.tsx +30 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/alert-dialog.tsx +196 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/avatar.tsx +109 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/badge.tsx +48 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/breadcrumb.tsx +109 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/button.tsx +14 -2
- package/dist/templates/web-nextjs/apps/web/src/components/ui/card.tsx +92 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/chart.tsx +374 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/checkbox.tsx +32 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/collapsible.tsx +33 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/command.tsx +184 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/dialog.tsx +158 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/drawer.tsx +135 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/dropdown-menu.tsx +257 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/field.tsx +248 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/input-otp.tsx +77 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/pagination.tsx +127 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/popover.tsx +89 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/progress.tsx +31 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/radio-group.tsx +45 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/scroll-area.tsx +58 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/select.tsx +190 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/separator.tsx +29 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/sheet.tsx +143 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/sidebar.tsx +726 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/skeleton.tsx +13 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/slider.tsx +63 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/sonner.tsx +11 -25
- package/dist/templates/web-nextjs/apps/web/src/components/ui/switch.tsx +35 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/table.tsx +116 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/tabs.tsx +91 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/textarea.tsx +18 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/toggle-group.tsx +83 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/toggle.tsx +47 -0
- package/dist/templates/web-nextjs/apps/web/src/components/ui/tooltip.tsx +57 -0
- package/dist/templates/web-nextjs/apps/web/src/features/auth/server.ts +15 -0
- package/dist/templates/web-nextjs/apps/web/src/hooks/use-mobile.ts +21 -0
- package/dist/templates/web-nextjs/package.json +10 -1
- package/dist/templates/web-nextjs/packages/openspec-docs-sync/package.json +1 -3
- package/dist/templates/web-nextjs/pnpm-lock.yaml +1562 -100
- package/dist/templates/web-nextjs/pnpm-workspace.yaml +15 -0
- package/dist/templates/web-nextjs/turbo.json +1 -0
- package/package.json +2 -2
- /package/dist/templates/web-nextjs/{.env.example → apps/web/.env.example} +0 -0
package/dist/index.js
CHANGED
|
@@ -863,6 +863,55 @@ function checkVersion(cliVersion, minCliVersion, templateId) {
|
|
|
863
863
|
}
|
|
864
864
|
}
|
|
865
865
|
|
|
866
|
+
// package.json
|
|
867
|
+
var package_default;
|
|
868
|
+
var init_package = __esm(() => {
|
|
869
|
+
package_default = {
|
|
870
|
+
name: "@cogito.ai/cli",
|
|
871
|
+
version: "0.4.0",
|
|
872
|
+
type: "module",
|
|
873
|
+
description: "AgentDock CLI – scaffold projects for humans and AI agents",
|
|
874
|
+
publishConfig: {
|
|
875
|
+
access: "public"
|
|
876
|
+
},
|
|
877
|
+
bin: {
|
|
878
|
+
agentdock: "./dist/index.js"
|
|
879
|
+
},
|
|
880
|
+
main: "./dist/index.js",
|
|
881
|
+
files: [
|
|
882
|
+
"dist/"
|
|
883
|
+
],
|
|
884
|
+
engines: {
|
|
885
|
+
node: ">=18"
|
|
886
|
+
},
|
|
887
|
+
scripts: {
|
|
888
|
+
build: "pnpm run generate-registry && bun build bin/agentdock.ts --outfile dist/index.js --target node && cp src/registry.json dist/registry.json && rm -rf dist/templates && mkdir -p dist/templates && rsync -a --exclude='node_modules/' --exclude='.next/' --exclude='.turbo/' ../../templates/ dist/templates/",
|
|
889
|
+
"generate-registry": "tsx ../../scripts/generate-registry/index.ts",
|
|
890
|
+
"check-types": "tsc --noEmit",
|
|
891
|
+
test: "vitest run"
|
|
892
|
+
},
|
|
893
|
+
dependencies: {
|
|
894
|
+
citty: "^0.1.6",
|
|
895
|
+
"@clack/prompts": "^0.9.1",
|
|
896
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
897
|
+
giget: "^1.2.4"
|
|
898
|
+
},
|
|
899
|
+
devDependencies: {
|
|
900
|
+
"@cogito.ai/tsconfig": "workspace:*",
|
|
901
|
+
"@types/node": "^20.0.0",
|
|
902
|
+
bun: "latest",
|
|
903
|
+
vitest: "^4.1.8"
|
|
904
|
+
}
|
|
905
|
+
};
|
|
906
|
+
});
|
|
907
|
+
|
|
908
|
+
// src/version.ts
|
|
909
|
+
var VERSION;
|
|
910
|
+
var init_version = __esm(() => {
|
|
911
|
+
init_package();
|
|
912
|
+
VERSION = package_default.version;
|
|
913
|
+
});
|
|
914
|
+
|
|
866
915
|
// src/core/scaffold.ts
|
|
867
916
|
import {
|
|
868
917
|
cpSync,
|
|
@@ -874,6 +923,7 @@ import {
|
|
|
874
923
|
} from "fs";
|
|
875
924
|
import { join as join2, dirname as dirname2 } from "path";
|
|
876
925
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
926
|
+
import { execSync } from "child_process";
|
|
877
927
|
function getTemplateSourceDir(templateSource) {
|
|
878
928
|
const runtimeDir = dirname2(fileURLToPath2(import.meta.url));
|
|
879
929
|
const candidates = [
|
|
@@ -894,6 +944,7 @@ function rewritePackageJson(pkgJsonPath, name, resolvedDependencies) {
|
|
|
894
944
|
pkg["version"] = "0.1.0";
|
|
895
945
|
delete pkg["private"];
|
|
896
946
|
delete pkg["agentdock"];
|
|
947
|
+
delete pkg["packageManager"];
|
|
897
948
|
for (const key of ["dependencies", "devDependencies", "peerDependencies"]) {
|
|
898
949
|
const deps = pkg[key];
|
|
899
950
|
if (!deps)
|
|
@@ -907,10 +958,27 @@ function rewritePackageJson(pkgJsonPath, name, resolvedDependencies) {
|
|
|
907
958
|
writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, 2) + `
|
|
908
959
|
`, "utf-8");
|
|
909
960
|
}
|
|
961
|
+
function injectPackageManager(pkgJsonPath) {
|
|
962
|
+
if (!existsSync2(pkgJsonPath))
|
|
963
|
+
return;
|
|
964
|
+
try {
|
|
965
|
+
const pnpmVersion = execSync("pnpm --version", {
|
|
966
|
+
encoding: "utf-8",
|
|
967
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
968
|
+
}).trim();
|
|
969
|
+
if (!pnpmVersion)
|
|
970
|
+
return;
|
|
971
|
+
const raw = readFileSync2(pkgJsonPath, "utf-8");
|
|
972
|
+
const pkg = JSON.parse(raw);
|
|
973
|
+
pkg["packageManager"] = `pnpm@${pnpmVersion}`;
|
|
974
|
+
writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, 2) + `
|
|
975
|
+
`, "utf-8");
|
|
976
|
+
} catch {}
|
|
977
|
+
}
|
|
910
978
|
function scaffoldProject(options) {
|
|
911
979
|
const { targetDir, name, template, packageManager: _pm } = options;
|
|
912
980
|
try {
|
|
913
|
-
checkVersion(
|
|
981
|
+
checkVersion(VERSION, template.minCliVersion, template.id);
|
|
914
982
|
} catch (err) {
|
|
915
983
|
return {
|
|
916
984
|
ok: false,
|
|
@@ -933,6 +1001,7 @@ function scaffoldProject(options) {
|
|
|
933
1001
|
if (existsSync2(pkgJsonPath)) {
|
|
934
1002
|
rewritePackageJson(pkgJsonPath, name, template.resolvedDependencies);
|
|
935
1003
|
}
|
|
1004
|
+
injectPackageManager(pkgJsonPath);
|
|
936
1005
|
return {
|
|
937
1006
|
ok: true,
|
|
938
1007
|
targetDir,
|
|
@@ -947,8 +1016,9 @@ function scaffoldProject(options) {
|
|
|
947
1016
|
};
|
|
948
1017
|
}
|
|
949
1018
|
}
|
|
950
|
-
var
|
|
951
|
-
|
|
1019
|
+
var init_scaffold = __esm(() => {
|
|
1020
|
+
init_version();
|
|
1021
|
+
});
|
|
952
1022
|
|
|
953
1023
|
// src/adapters/agent.ts
|
|
954
1024
|
var exports_agent = {};
|
|
@@ -16316,7 +16386,7 @@ __export(exports_server, {
|
|
|
16316
16386
|
startMcpServer: () => startMcpServer
|
|
16317
16387
|
});
|
|
16318
16388
|
async function startMcpServer() {
|
|
16319
|
-
const server = new Server({ name: "agentdock", version:
|
|
16389
|
+
const server = new Server({ name: "agentdock", version: VERSION }, {
|
|
16320
16390
|
capabilities: {
|
|
16321
16391
|
tools: {}
|
|
16322
16392
|
}
|
|
@@ -16380,12 +16450,12 @@ async function startMcpServer() {
|
|
|
16380
16450
|
process.exit(0);
|
|
16381
16451
|
});
|
|
16382
16452
|
}
|
|
16383
|
-
var PKG_VERSION = "0.1.0";
|
|
16384
16453
|
var init_server3 = __esm(() => {
|
|
16385
16454
|
init_server2();
|
|
16386
16455
|
init_stdio2();
|
|
16387
16456
|
init_types();
|
|
16388
16457
|
init_tools();
|
|
16458
|
+
init_version();
|
|
16389
16459
|
});
|
|
16390
16460
|
|
|
16391
16461
|
// ../../node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/core.mjs
|
|
@@ -17854,11 +17924,12 @@ var mcpCommand = defineCommand({
|
|
|
17854
17924
|
});
|
|
17855
17925
|
|
|
17856
17926
|
// src/main.ts
|
|
17927
|
+
init_version();
|
|
17857
17928
|
var main = defineCommand({
|
|
17858
17929
|
meta: {
|
|
17859
17930
|
name: "agentdock",
|
|
17860
17931
|
description: "AgentDock CLI – scaffold projects for humans and AI agents",
|
|
17861
|
-
version:
|
|
17932
|
+
version: VERSION
|
|
17862
17933
|
},
|
|
17863
17934
|
subCommands: {
|
|
17864
17935
|
init: initCommand,
|
|
@@ -7,6 +7,6 @@ const create = browser<typeof Config, import("fumadocs-mdx/runtime/types").Inter
|
|
|
7
7
|
}
|
|
8
8
|
}>();
|
|
9
9
|
const browserCollections = {
|
|
10
|
-
docs: create.doc("docs", {"index.mdx": () => import("../content/docs/index.mdx?collection=docs"), "changelog/index.mdx": () => import("../content/docs/changelog/index.mdx?collection=docs"), "
|
|
10
|
+
docs: create.doc("docs", {"index.mdx": () => import("../content/docs/index.mdx?collection=docs"), "changelog/index.mdx": () => import("../content/docs/changelog/index.mdx?collection=docs"), "decisions/turbo-package-manager.mdx": () => import("../content/docs/decisions/turbo-package-manager.mdx?collection=docs"), "features/auth.mdx": () => import("../content/docs/features/auth.mdx?collection=docs"), "features/hello.mdx": () => import("../content/docs/features/hello.mdx?collection=docs"), "roadmap/index.mdx": () => import("../content/docs/roadmap/index.mdx?collection=docs"), }),
|
|
11
11
|
};
|
|
12
12
|
export default browserCollections;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
|
+
import * as __fd_glob_10 from "../content/docs/roadmap/index.mdx?collection=docs"
|
|
2
3
|
import * as __fd_glob_9 from "../content/docs/features/hello.mdx?collection=docs"
|
|
3
4
|
import * as __fd_glob_8 from "../content/docs/features/auth.mdx?collection=docs"
|
|
4
|
-
import * as __fd_glob_7 from "../content/docs/
|
|
5
|
+
import * as __fd_glob_7 from "../content/docs/decisions/turbo-package-manager.mdx?collection=docs"
|
|
5
6
|
import * as __fd_glob_6 from "../content/docs/changelog/index.mdx?collection=docs"
|
|
6
7
|
import * as __fd_glob_5 from "../content/docs/index.mdx?collection=docs"
|
|
7
8
|
import { default as __fd_glob_4 } from "../content/docs/roadmap/meta.json?collection=docs"
|
|
@@ -17,4 +18,4 @@ const create = server<typeof Config, import("fumadocs-mdx/runtime/types").Intern
|
|
|
17
18
|
}
|
|
18
19
|
}>({"doc":{"passthroughs":["extractedReferences"]}});
|
|
19
20
|
|
|
20
|
-
export const docs = await create.docs("docs", "content/docs", {"meta.json": __fd_glob_0, "changelog/meta.json": __fd_glob_1, "decisions/meta.json": __fd_glob_2, "features/meta.json": __fd_glob_3, "roadmap/meta.json": __fd_glob_4, }, {"index.mdx": __fd_glob_5, "changelog/index.mdx": __fd_glob_6, "
|
|
21
|
+
export const docs = await create.docs("docs", "content/docs", {"meta.json": __fd_glob_0, "changelog/meta.json": __fd_glob_1, "decisions/meta.json": __fd_glob_2, "features/meta.json": __fd_glob_3, "roadmap/meta.json": __fd_glob_4, }, {"index.mdx": __fd_glob_5, "changelog/index.mdx": __fd_glob_6, "decisions/turbo-package-manager.mdx": __fd_glob_7, "features/auth.mdx": __fd_glob_8, "features/hello.mdx": __fd_glob_9, "roadmap/index.mdx": __fd_glob_10, });
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Turbo & Package Manager"
|
|
3
|
+
description: "Why dangerouslyDisablePackageManagerCheck exists, its tradeoffs, and how to properly configure packageManager for your team."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Turborepo & Package Manager Configuration
|
|
7
|
+
|
|
8
|
+
## Why `dangerouslyDisablePackageManagerCheck` is enabled
|
|
9
|
+
|
|
10
|
+
This template ships with `dangerouslyDisablePackageManagerCheck: true` in `turbo.json` to avoid an out-of-the-box failure:
|
|
11
|
+
|
|
12
|
+
```json
|
|
13
|
+
// turbo.json
|
|
14
|
+
{
|
|
15
|
+
"dangerouslyDisablePackageManagerCheck": true
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Root cause:** Turborepo 2.0+ requires the `packageManager` field in `package.json` to identify your package manager and version. Without it, Turbo refuses to run:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
× Could not resolve workspaces.
|
|
23
|
+
╰─▶ Missing `packageManager` field in package.json
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Since users may have different pnpm versions installed, the template cannot hard-code a specific version without risking the same `Corepack PATH` error that plagues a pinned `packageManager` field. `dangerouslyDisablePackageManagerCheck` lets Turbo skip this validation so the template works on first `pnpm dev`.
|
|
27
|
+
|
|
28
|
+
## What `dangerouslyDisablePackageManagerCheck` actually disables
|
|
29
|
+
|
|
30
|
+
| What Turbo normally does | What is skipped |
|
|
31
|
+
| --- | --- |
|
|
32
|
+
| Reads `packageManager` to identify which lockfile to hash | Cache hashing falls back to a less-precise strategy |
|
|
33
|
+
| Validates that the running package manager matches the declared one | No mismatch detection (could build with wrong PM) |
|
|
34
|
+
| Optimizes workspace discovery per package manager | Slightly slower workspace graph resolution |
|
|
35
|
+
|
|
36
|
+
**In practice:** for most single-developer or small team projects, the only noticeable difference is that Turbo cache keys are slightly less precise — you might get a cache miss that would otherwise be a hit. This is a minor inconvenience, not a correctness issue.
|
|
37
|
+
|
|
38
|
+
## How to remove the flag (recommended for team projects)
|
|
39
|
+
|
|
40
|
+
**Step 1 — Find your installed pnpm version:**
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pnpm --version
|
|
44
|
+
# e.g. 11.5.1
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Step 2 — Add `packageManager` to your root `package.json`:**
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"packageManager": "pnpm@11.5.1"
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Step 3 — Remove `dangerouslyDisablePackageManagerCheck` from `turbo.json`:**
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"$schema": "https://turbo.build/schema.json",
|
|
60
|
+
"tasks": {
|
|
61
|
+
...
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Step 4 — Commit both files.** All developers cloning the repo will now use the same pnpm version enforced by Corepack, and Turbo's cache hashing is fully accurate.
|
|
67
|
+
|
|
68
|
+
## Automatic injection (CLI 0.3.6+)
|
|
69
|
+
|
|
70
|
+
Starting with `@cogito.ai/cli@0.3.6`, the `agentdock init` command automatically detects your installed pnpm version and injects `packageManager: "pnpm@X.Y.Z"` into the scaffolded project's root `package.json`. This means new projects are created with the correct field pre-filled, and you can immediately remove `dangerouslyDisablePackageManagerCheck` from `turbo.json` after scaffolding.
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"start": "next start",
|
|
9
9
|
"lint": "eslint .",
|
|
10
10
|
"check-types": "tsc --noEmit",
|
|
11
|
-
"docs:sync": "openspec-docs-sync",
|
|
11
|
+
"docs:sync": "pnpm --filter @cogito.ai/openspec-docs-sync run build && node ../../packages/openspec-docs-sync/dist/index.js",
|
|
12
12
|
"postinstall": "fumadocs-mdx"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
@@ -20,20 +20,13 @@ function copyCookies(from: NextResponse, to: NextResponse) {
|
|
|
20
20
|
export default async function middleware(request: NextRequest) {
|
|
21
21
|
const pathname = request.nextUrl.pathname
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
const url = request.nextUrl.clone()
|
|
25
|
-
url.pathname = `/${defaultLocale}`
|
|
26
|
-
return NextResponse.redirect(url)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Skip Supabase session refresh for the auth callback route
|
|
30
|
-
// (it's handled by the route handler itself)
|
|
23
|
+
// Auth callback is handled by its own route handler — skip all middleware processing
|
|
31
24
|
if (pathname.startsWith('/auth/')) {
|
|
32
25
|
return NextResponse.next()
|
|
33
26
|
}
|
|
34
27
|
|
|
35
|
-
// 1. Let next-intl
|
|
36
|
-
//
|
|
28
|
+
// 1. Let next-intl handle locale routing.
|
|
29
|
+
// With localePrefix: 'always' (default), this also redirects / → /${defaultLocale}.
|
|
37
30
|
const response = handleI18nRouting(request)
|
|
38
31
|
|
|
39
32
|
// 2. Refresh the Supabase session (keeps token alive, writes updated cookie)
|
|
@@ -54,7 +47,7 @@ export default async function middleware(request: NextRequest) {
|
|
|
54
47
|
return redirectResponse
|
|
55
48
|
}
|
|
56
49
|
|
|
57
|
-
// 4. Normalize unknown locale-like prefixes: /fr/hello
|
|
50
|
+
// 4. Normalize unknown locale-like prefixes: /fr/hello → /zh/hello
|
|
58
51
|
const segments = pathname.split('/').filter(Boolean)
|
|
59
52
|
const firstSegment = segments[0]
|
|
60
53
|
|
|
@@ -74,6 +67,6 @@ export default async function middleware(request: NextRequest) {
|
|
|
74
67
|
|
|
75
68
|
export const config = {
|
|
76
69
|
// Match all pathnames except Next.js internals, static files, and auth callback.
|
|
77
|
-
// The
|
|
78
|
-
matcher: ['/
|
|
70
|
+
// The regex also matches '/' so next-intl handles the root → /${defaultLocale} redirect.
|
|
71
|
+
matcher: ['/((?!_next|_vercel|auth/callback|.*\\..*).*)'],
|
|
79
72
|
}
|
|
@@ -12,21 +12,47 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@base-ui/react": "^1.5.0",
|
|
15
|
+
"@dnd-kit/core": "^6.3.1",
|
|
16
|
+
"@dnd-kit/modifiers": "^9.0.0",
|
|
17
|
+
"@dnd-kit/sortable": "^10.0.0",
|
|
18
|
+
"@dnd-kit/utilities": "^3.2.2",
|
|
15
19
|
"@hookform/resolvers": "^5.4.0",
|
|
20
|
+
"@radix-ui/react-avatar": "^1.1.11",
|
|
21
|
+
"@radix-ui/react-checkbox": "^1.3.3",
|
|
22
|
+
"@radix-ui/react-collapsible": "^1.1.12",
|
|
23
|
+
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
24
|
+
"@radix-ui/react-progress": "^1.1.8",
|
|
25
|
+
"@radix-ui/react-radio-group": "^1.3.8",
|
|
26
|
+
"@radix-ui/react-scroll-area": "^1.2.10",
|
|
27
|
+
"@radix-ui/react-select": "^2.2.6",
|
|
28
|
+
"@radix-ui/react-separator": "^1.1.8",
|
|
29
|
+
"@radix-ui/react-slider": "^1.3.6",
|
|
30
|
+
"@radix-ui/react-slot": "^1.2.4",
|
|
31
|
+
"@radix-ui/react-switch": "^1.2.6",
|
|
32
|
+
"@radix-ui/react-tabs": "^1.1.13",
|
|
33
|
+
"@radix-ui/react-toggle": "^1.1.10",
|
|
34
|
+
"@radix-ui/react-toggle-group": "^1.1.11",
|
|
16
35
|
"@supabase/ssr": "^0.10.3",
|
|
36
|
+
"@tabler/icons-react": "^3.44.0",
|
|
37
|
+
"@tanstack/react-table": "^8.21.3",
|
|
17
38
|
"class-variance-authority": "^0.7.1",
|
|
18
39
|
"clsx": "^2.1.1",
|
|
40
|
+
"cmdk": "^1.1.1",
|
|
41
|
+
"input-otp": "^1.4.2",
|
|
19
42
|
"lucide-react": "^1.17.0",
|
|
20
43
|
"next": "16",
|
|
21
44
|
"next-intl": "^4.13.0",
|
|
22
45
|
"next-themes": "^0.4.6",
|
|
46
|
+
"radix-ui": "^1.4.3",
|
|
23
47
|
"react": "19",
|
|
24
48
|
"react-dom": "19",
|
|
25
49
|
"react-hook-form": "^7.77.0",
|
|
50
|
+
"recharts": "^3.8.1",
|
|
26
51
|
"shadcn": "^4.10.0",
|
|
27
52
|
"sonner": "^2.0.7",
|
|
28
53
|
"tailwind-merge": "^3.6.0",
|
|
29
54
|
"tw-animate-css": "^1.4.0",
|
|
55
|
+
"vaul": "^1.1.2",
|
|
30
56
|
"zod": "^4.4.3"
|
|
31
57
|
},
|
|
32
58
|
"devDependencies": {
|
|
@@ -6,18 +6,18 @@ import Link from 'next/link'
|
|
|
6
6
|
import { useTranslations } from 'next-intl'
|
|
7
7
|
import { useForm } from 'react-hook-form'
|
|
8
8
|
import { zodResolver } from '@hookform/resolvers/zod'
|
|
9
|
-
import {
|
|
9
|
+
import { GalleryVerticalEnd } from 'lucide-react'
|
|
10
10
|
import { toast } from 'sonner'
|
|
11
11
|
import { Button } from '@/components/ui/button'
|
|
12
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
|
12
13
|
import { Input } from '@/components/ui/input'
|
|
13
14
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
} from '@/components/ui/form'
|
|
15
|
+
Field,
|
|
16
|
+
FieldDescription,
|
|
17
|
+
FieldGroup,
|
|
18
|
+
FieldLabel,
|
|
19
|
+
FieldSeparator,
|
|
20
|
+
} from '@/components/ui/field'
|
|
21
21
|
import { signIn, signInWithGithubForLocale } from '@/features/auth'
|
|
22
22
|
import { signInSchema, type SignInInput } from '@/lib/validations/auth'
|
|
23
23
|
import type { ActionResult } from '@/core/types/auth'
|
|
@@ -28,114 +28,108 @@ export default function LoginPage() {
|
|
|
28
28
|
const routeParams = useParams<{ locale: string }>()
|
|
29
29
|
const locale = routeParams.locale ?? 'en'
|
|
30
30
|
|
|
31
|
-
const
|
|
31
|
+
const { register, formState: { errors } } = useForm<SignInInput>({
|
|
32
32
|
resolver: zodResolver(signInSchema),
|
|
33
33
|
defaultValues: { email: '', password: '' },
|
|
34
34
|
})
|
|
35
35
|
|
|
36
|
-
const [state, formAction, isPending] = useActionState<ActionResult | null, FormData>(
|
|
37
|
-
signIn,
|
|
38
|
-
null,
|
|
39
|
-
)
|
|
36
|
+
const [state, formAction, isPending] = useActionState<ActionResult | null, FormData>(signIn, null)
|
|
40
37
|
|
|
41
38
|
useEffect(() => {
|
|
42
|
-
if (state?.error)
|
|
43
|
-
toast.error(state.error)
|
|
44
|
-
}
|
|
39
|
+
if (state?.error) toast.error(state.error)
|
|
45
40
|
}, [state])
|
|
46
41
|
|
|
47
42
|
async function handleGithub() {
|
|
48
43
|
const result = await signInWithGithubForLocale(locale)
|
|
49
|
-
if (result.error) {
|
|
50
|
-
|
|
51
|
-
return
|
|
52
|
-
}
|
|
53
|
-
if (result.data?.url) {
|
|
54
|
-
router.push(result.data.url)
|
|
55
|
-
}
|
|
44
|
+
if (result.error) { toast.error(result.error); return }
|
|
45
|
+
if (result.data?.url) router.push(result.data.url)
|
|
56
46
|
}
|
|
57
47
|
|
|
58
48
|
return (
|
|
59
|
-
<div className="flex min-h-
|
|
60
|
-
<div className="w-full max-w-sm
|
|
61
|
-
<
|
|
62
|
-
<
|
|
63
|
-
|
|
64
|
-
</div>
|
|
65
|
-
|
|
66
|
-
<Button
|
|
67
|
-
type="button"
|
|
68
|
-
variant="outline"
|
|
69
|
-
className="w-full"
|
|
70
|
-
onClick={handleGithub}
|
|
71
|
-
>
|
|
72
|
-
<GitBranch className="mr-2 h-4 w-4" />
|
|
73
|
-
{t('githubButton')}
|
|
74
|
-
</Button>
|
|
75
|
-
|
|
76
|
-
<div className="relative">
|
|
77
|
-
<div className="absolute inset-0 flex items-center">
|
|
78
|
-
<span className="w-full border-t" />
|
|
79
|
-
</div>
|
|
80
|
-
<div className="relative flex justify-center text-xs uppercase">
|
|
81
|
-
<span className="bg-background px-2 text-muted-foreground">{t('orContinueWith')}</span>
|
|
49
|
+
<div className="flex min-h-svh flex-col items-center justify-center gap-6 bg-muted p-6 md:p-10">
|
|
50
|
+
<div className="flex w-full max-w-sm flex-col gap-6">
|
|
51
|
+
<Link href={`/${locale}`} className="flex items-center gap-2 self-center font-medium">
|
|
52
|
+
<div className="flex size-6 items-center justify-center rounded-md bg-primary text-primary-foreground">
|
|
53
|
+
<GalleryVerticalEnd className="size-4" />
|
|
82
54
|
</div>
|
|
83
|
-
|
|
55
|
+
AgentDock
|
|
56
|
+
</Link>
|
|
84
57
|
|
|
85
|
-
<
|
|
86
|
-
<
|
|
87
|
-
<
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
58
|
+
<div className="flex flex-col gap-6">
|
|
59
|
+
<Card>
|
|
60
|
+
<CardHeader className="text-center">
|
|
61
|
+
<CardTitle className="text-xl">{t('loginTitle')}</CardTitle>
|
|
62
|
+
<CardDescription>{t('loginSubtitle')}</CardDescription>
|
|
63
|
+
</CardHeader>
|
|
64
|
+
<CardContent>
|
|
65
|
+
<form action={formAction}>
|
|
66
|
+
<input type="hidden" name="locale" value={locale} />
|
|
67
|
+
<FieldGroup>
|
|
68
|
+
<Field>
|
|
69
|
+
<Button
|
|
70
|
+
type="button"
|
|
71
|
+
variant="outline"
|
|
72
|
+
className="w-full"
|
|
73
|
+
onClick={handleGithub}
|
|
74
|
+
>
|
|
75
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" className="size-4">
|
|
76
|
+
<path
|
|
77
|
+
d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"
|
|
78
|
+
fill="currentColor"
|
|
79
|
+
/>
|
|
80
|
+
</svg>
|
|
81
|
+
{t('githubButton')}
|
|
82
|
+
</Button>
|
|
83
|
+
</Field>
|
|
84
|
+
<FieldSeparator>{t('orContinueWith')}</FieldSeparator>
|
|
85
|
+
<Field>
|
|
86
|
+
<FieldLabel htmlFor="email">{t('emailLabel')}</FieldLabel>
|
|
95
87
|
<Input
|
|
88
|
+
id="email"
|
|
96
89
|
type="email"
|
|
97
90
|
placeholder={t('emailPlaceholder')}
|
|
98
|
-
|
|
91
|
+
autoComplete="email"
|
|
92
|
+
{...register('email')}
|
|
99
93
|
/>
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
<FormItem>
|
|
111
|
-
<FormLabel>{t('passwordLabel')}</FormLabel>
|
|
112
|
-
<FormControl>
|
|
94
|
+
{errors.email && (
|
|
95
|
+
<FieldDescription className="text-destructive">
|
|
96
|
+
{errors.email.message}
|
|
97
|
+
</FieldDescription>
|
|
98
|
+
)}
|
|
99
|
+
</Field>
|
|
100
|
+
<Field>
|
|
101
|
+
<div className="flex items-center">
|
|
102
|
+
<FieldLabel htmlFor="password">{t('passwordLabel')}</FieldLabel>
|
|
103
|
+
</div>
|
|
113
104
|
<Input
|
|
105
|
+
id="password"
|
|
114
106
|
type="password"
|
|
115
107
|
placeholder={t('passwordPlaceholder')}
|
|
116
|
-
|
|
108
|
+
autoComplete="current-password"
|
|
109
|
+
{...register('password')}
|
|
117
110
|
/>
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
111
|
+
{errors.password && (
|
|
112
|
+
<FieldDescription className="text-destructive">
|
|
113
|
+
{errors.password.message}
|
|
114
|
+
</FieldDescription>
|
|
115
|
+
)}
|
|
116
|
+
</Field>
|
|
117
|
+
<Field>
|
|
118
|
+
<Button type="submit" className="w-full" disabled={isPending}>
|
|
119
|
+
{isPending ? '\u2026' : t('signInButton')}
|
|
120
|
+
</Button>
|
|
121
|
+
<FieldDescription className="text-center">
|
|
122
|
+
{t('noAccountText')}{' '}
|
|
123
|
+
<Link href={`/${locale}/signup`} className="underline underline-offset-4">
|
|
124
|
+
{t('signUpLink')}
|
|
125
|
+
</Link>
|
|
126
|
+
</FieldDescription>
|
|
127
|
+
</Field>
|
|
128
|
+
</FieldGroup>
|
|
129
|
+
</form>
|
|
130
|
+
</CardContent>
|
|
131
|
+
</Card>
|
|
132
|
+
</div>
|
|
139
133
|
</div>
|
|
140
134
|
</div>
|
|
141
135
|
)
|