@skyf0xx/hedgehog-core-full-stack-app 1.0.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/CLAUDE.core.md +147 -0
- package/LICENSE +21 -0
- package/README.md +41 -0
- package/agents/backend-eng.md +189 -0
- package/agents/front-end-eng.md +176 -0
- package/agents/ux-planner.md +174 -0
- package/hedgehog-core.yaml +20 -0
- package/package.json +41 -0
- package/skills/hedgehog-bootstrap/SKILL.md +324 -0
- package/skills/hedgehog-bootstrap-full-stack-app-core/SKILL.md +411 -0
- package/skills/hedgehog-loop/SKILL.md +643 -0
- package/skills/link-workspace-packages/SKILL.md +41 -0
- package/skills/nx-generate/SKILL.md +165 -0
- package/skills/nx-run-tasks/SKILL.md +52 -0
- package/skills/nx-workspace/SKILL.md +261 -0
- package/skills/nx-workspace/references/AFFECTED.md +27 -0
- package/vendor-skills/GSAP/ATTRIBUTION.md +30 -0
- package/vendor-skills/GSAP/LICENSE +21 -0
- package/vendor-skills/GSAP/gsap-core/SKILL.md +254 -0
- package/vendor-skills/GSAP/gsap-frameworks/SKILL.md +266 -0
- package/vendor-skills/GSAP/gsap-performance/SKILL.md +79 -0
- package/vendor-skills/GSAP/gsap-plugins/SKILL.md +433 -0
- package/vendor-skills/GSAP/gsap-react/SKILL.md +136 -0
- package/vendor-skills/GSAP/gsap-scrolltrigger/SKILL.md +296 -0
- package/vendor-skills/GSAP/gsap-timeline/SKILL.md +107 -0
- package/vendor-skills/GSAP/gsap-utils/SKILL.md +284 -0
- package/vendor-skills/GSAP/llms.txt +39 -0
- package/workspace/.env.example +5 -0
- package/workspace/.github/workflows/phase-gate.yml +17 -0
- package/workspace/.prettierignore +5 -0
- package/workspace/.prettierrc +3 -0
- package/workspace/.vscode/extensions.json +3 -0
- package/workspace/apps/api/eslint.config.mjs +3 -0
- package/workspace/apps/api/package.json +117 -0
- package/workspace/apps/api/src/app/app.module.spec.ts +15 -0
- package/workspace/apps/api/src/app/app.module.ts +15 -0
- package/workspace/apps/api/src/app/feature-modules.ts +8 -0
- package/workspace/apps/api/src/app/health.controller.ts +9 -0
- package/workspace/apps/api/src/assets/.gitkeep +0 -0
- package/workspace/apps/api/src/main.ts +32 -0
- package/workspace/apps/api/tsconfig.app.json +22 -0
- package/workspace/apps/api/tsconfig.json +13 -0
- package/workspace/apps/api/tsconfig.spec.json +36 -0
- package/workspace/apps/api/vitest.config.mts +18 -0
- package/workspace/apps/api/webpack.config.cjs +25 -0
- package/workspace/apps/api-e2e/eslint.config.mjs +3 -0
- package/workspace/apps/api-e2e/package.json +28 -0
- package/workspace/apps/api-e2e/src/api/api.spec.ts +11 -0
- package/workspace/apps/api-e2e/src/support/global-setup.ts +17 -0
- package/workspace/apps/api-e2e/src/support/test-setup.ts +6 -0
- package/workspace/apps/api-e2e/tsconfig.json +10 -0
- package/workspace/apps/api-e2e/tsconfig.spec.json +28 -0
- package/workspace/apps/api-e2e/vitest.config.mts +20 -0
- package/workspace/apps/web/.env.example +12 -0
- package/workspace/apps/web/.prettierrc.js +10 -0
- package/workspace/apps/web/.swcrc +30 -0
- package/workspace/apps/web/components.json +21 -0
- package/workspace/apps/web/eslint.config.mjs +12 -0
- package/workspace/apps/web/index.d.ts +7 -0
- package/workspace/apps/web/next-env.d.ts +7 -0
- package/workspace/apps/web/next.config.js +9 -0
- package/workspace/apps/web/package.json +38 -0
- package/workspace/apps/web/postcss.config.mjs +7 -0
- package/workspace/apps/web/public/.gitkeep +0 -0
- package/workspace/apps/web/public/favicon.ico +0 -0
- package/workspace/apps/web/src/app/global.css +83 -0
- package/workspace/apps/web/src/app/layout.tsx +34 -0
- package/workspace/apps/web/src/app/module-routes.ts +13 -0
- package/workspace/apps/web/src/app/page.tsx +34 -0
- package/workspace/apps/web/src/app/providers.tsx +12 -0
- package/workspace/apps/web/src/components/theme-toggle.spec.tsx +20 -0
- package/workspace/apps/web/src/components/theme-toggle.tsx +32 -0
- package/workspace/apps/web/src/components/ui/button.tsx +60 -0
- package/workspace/apps/web/src/lib/utils.ts +6 -0
- package/workspace/apps/web/src/test-setup.ts +1 -0
- package/workspace/apps/web/tsconfig.json +62 -0
- package/workspace/apps/web/tsconfig.spec.json +37 -0
- package/workspace/apps/web/vitest.config.mts +27 -0
- package/workspace/apps/web-e2e/eslint.config.mjs +12 -0
- package/workspace/apps/web-e2e/package.json +10 -0
- package/workspace/apps/web-e2e/playwright.config.mts +75 -0
- package/workspace/apps/web-e2e/src/example.spec.ts +7 -0
- package/workspace/apps/web-e2e/tsconfig.json +26 -0
- package/workspace/commitlint.config.cjs +3 -0
- package/workspace/core.yaml +68 -0
- package/workspace/docker-compose.yml +14 -0
- package/workspace/eslint.config.mjs +15 -0
- package/workspace/gitignore.template +24 -0
- package/workspace/lefthook.yml +52 -0
- package/workspace/nx.json +90 -0
- package/workspace/package.json +99 -0
- package/workspace/packages/config/eslint-base.js +205 -0
- package/workspace/packages/config/package.json +28 -0
- package/workspace/packages/config/prettier.js +13 -0
- package/workspace/packages/config/src/env.schema.spec.ts +38 -0
- package/workspace/packages/config/src/env.schema.ts +18 -0
- package/workspace/packages/config/src/index.ts +1 -0
- package/workspace/packages/config/tsconfig.json +13 -0
- package/workspace/packages/config/tsconfig.lib.json +27 -0
- package/workspace/packages/config/tsconfig.spec.json +34 -0
- package/workspace/packages/config/vitest.config.mts +18 -0
- package/workspace/packages/db/package.json +27 -0
- package/workspace/packages/db/src/index.ts +2 -0
- package/workspace/packages/db/src/lib/db.spec.ts +48 -0
- package/workspace/packages/db/src/lib/db.ts +54 -0
- package/workspace/packages/db/src/schema/index.ts +4 -0
- package/workspace/packages/db/tsconfig.json +13 -0
- package/workspace/packages/db/tsconfig.lib.json +27 -0
- package/workspace/packages/db/tsconfig.spec.json +34 -0
- package/workspace/packages/db/vitest.config.mts +18 -0
- package/workspace/pnpm-lock.yaml +23719 -0
- package/workspace/pnpm-workspace.yaml +7 -0
- package/workspace/tools/generate-feature-modules.cjs +104 -0
- package/workspace/tools/generate-module-routes.cjs +89 -0
- package/workspace/tools/generators/contract/generator.ts +336 -0
- package/workspace/tools/generators/contract/schema.json +24 -0
- package/workspace/tools/generators/controller/generator.ts +390 -0
- package/workspace/tools/generators/controller/schema.json +24 -0
- package/workspace/tools/generators/fields.ts +160 -0
- package/workspace/tools/generators/generators.json +42 -0
- package/workspace/tools/generators/hook/generator.ts +291 -0
- package/workspace/tools/generators/hook/schema.json +19 -0
- package/workspace/tools/generators/lib-shell.ts +124 -0
- package/workspace/tools/generators/naming.ts +84 -0
- package/workspace/tools/generators/package.json +6 -0
- package/workspace/tools/generators/repository/generator.ts +298 -0
- package/workspace/tools/generators/repository/schema.json +15 -0
- package/workspace/tools/generators/schema/generator.ts +169 -0
- package/workspace/tools/generators/schema/schema.json +20 -0
- package/workspace/tools/generators/screen/generator.ts +218 -0
- package/workspace/tools/generators/screen/schema.json +15 -0
- package/workspace/tools/generators/service/generator.ts +270 -0
- package/workspace/tools/generators/service/schema.json +19 -0
- package/workspace/tools/phase-gate.cjs +77 -0
- package/workspace/tsconfig.base.json +21 -0
- package/workspace/tsconfig.json +25 -0
- package/workspace/vitest.workspace.ts +4 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"jsx": "preserve",
|
|
5
|
+
"noEmit": true,
|
|
6
|
+
"emitDeclarationOnly": false,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"module": "esnext",
|
|
9
|
+
"moduleResolution": "bundler",
|
|
10
|
+
"resolveJsonModule": true,
|
|
11
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
12
|
+
"allowJs": true,
|
|
13
|
+
"allowSyntheticDefaultImports": true,
|
|
14
|
+
"forceConsistentCasingInFileNames": true,
|
|
15
|
+
"incremental": true,
|
|
16
|
+
"plugins": [
|
|
17
|
+
{
|
|
18
|
+
"name": "next"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"paths": {
|
|
22
|
+
"@/*": ["./src/*"]
|
|
23
|
+
},
|
|
24
|
+
"outDir": "dist",
|
|
25
|
+
"rootDir": "src",
|
|
26
|
+
"tsBuildInfoFile": "dist/tsconfig.tsbuildinfo"
|
|
27
|
+
},
|
|
28
|
+
"include": [
|
|
29
|
+
"src/**/*.ts",
|
|
30
|
+
"src/**/*.tsx",
|
|
31
|
+
"src/**/*.js",
|
|
32
|
+
"src/**/*.jsx",
|
|
33
|
+
"../../apps/web/.next/types/**/*.ts",
|
|
34
|
+
"../../dist/apps/web/.next/types/**/*.ts",
|
|
35
|
+
"index.d.ts",
|
|
36
|
+
"next-env.d.ts"
|
|
37
|
+
],
|
|
38
|
+
"exclude": [
|
|
39
|
+
"out-tsc",
|
|
40
|
+
"dist",
|
|
41
|
+
"node_modules",
|
|
42
|
+
"jest.config.ts",
|
|
43
|
+
"jest.config.cts",
|
|
44
|
+
"src/test-setup.ts",
|
|
45
|
+
"src/**/*.spec.ts",
|
|
46
|
+
"src/**/*.test.ts",
|
|
47
|
+
"src/**/*.spec.tsx",
|
|
48
|
+
"src/**/*.test.tsx",
|
|
49
|
+
".next",
|
|
50
|
+
"eslint.config.js",
|
|
51
|
+
"eslint.config.cjs",
|
|
52
|
+
"eslint.config.mjs"
|
|
53
|
+
],
|
|
54
|
+
"references": [
|
|
55
|
+
{
|
|
56
|
+
"path": "../../packages/config"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"path": "./tsconfig.spec.json"
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "./out-tsc/vitest",
|
|
5
|
+
"jsx": "preserve",
|
|
6
|
+
"types": [
|
|
7
|
+
"vitest/globals",
|
|
8
|
+
"vitest/importMeta",
|
|
9
|
+
"vite/client",
|
|
10
|
+
"node",
|
|
11
|
+
"vitest",
|
|
12
|
+
"@testing-library/jest-dom"
|
|
13
|
+
],
|
|
14
|
+
"forceConsistentCasingInFileNames": true
|
|
15
|
+
},
|
|
16
|
+
"include": [
|
|
17
|
+
"vite.config.ts",
|
|
18
|
+
"vite.config.mts",
|
|
19
|
+
"vitest.config.ts",
|
|
20
|
+
"vitest.config.mts",
|
|
21
|
+
"src/test-setup.ts",
|
|
22
|
+
"src/**/*.test.ts",
|
|
23
|
+
"src/**/*.spec.ts",
|
|
24
|
+
"src/**/*.test.tsx",
|
|
25
|
+
"src/**/*.spec.tsx",
|
|
26
|
+
"src/**/*.test.js",
|
|
27
|
+
"src/**/*.spec.js",
|
|
28
|
+
"src/**/*.test.jsx",
|
|
29
|
+
"src/**/*.spec.jsx",
|
|
30
|
+
"src/**/*.d.ts"
|
|
31
|
+
],
|
|
32
|
+
"references": [
|
|
33
|
+
{
|
|
34
|
+
"path": "../../packages/config"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { defineConfig } from 'vitest/config';
|
|
2
|
+
import react from '@vitejs/plugin-react';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
export default defineConfig(() => ({
|
|
6
|
+
root: __dirname,
|
|
7
|
+
cacheDir: '../../node_modules/.vite/apps/web',
|
|
8
|
+
plugins: [react()],
|
|
9
|
+
resolve: {
|
|
10
|
+
alias: {
|
|
11
|
+
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
test: {
|
|
15
|
+
name: 'web',
|
|
16
|
+
watch: false,
|
|
17
|
+
globals: true,
|
|
18
|
+
environment: 'jsdom',
|
|
19
|
+
setupFiles: ['./src/test-setup.ts'],
|
|
20
|
+
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
|
21
|
+
reporters: ['default'],
|
|
22
|
+
coverage: {
|
|
23
|
+
reportsDirectory: './test-output/vitest/coverage',
|
|
24
|
+
provider: 'v8' as const,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
}));
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import playwright from 'eslint-plugin-playwright';
|
|
2
|
+
import baseConfig from '../../eslint.config.mjs';
|
|
3
|
+
|
|
4
|
+
export default [
|
|
5
|
+
playwright.configs['flat/recommended'],
|
|
6
|
+
...baseConfig,
|
|
7
|
+
{
|
|
8
|
+
files: ['**/*.ts', '**/*.js'],
|
|
9
|
+
// Override or add rules here
|
|
10
|
+
rules: {},
|
|
11
|
+
},
|
|
12
|
+
];
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { defineConfig, devices } from '@playwright/test';
|
|
2
|
+
import { nxE2EPreset } from '@nx/playwright/preset';
|
|
3
|
+
import { workspaceRoot } from '@nx/devkit';
|
|
4
|
+
|
|
5
|
+
// For CI, you may want to set BASE_URL to the deployed application.
|
|
6
|
+
const baseURL = process.env['BASE_URL'] || 'http://localhost:3000';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Read environment variables from file.
|
|
10
|
+
* https://github.com/motdotla/dotenv
|
|
11
|
+
*/
|
|
12
|
+
// import 'dotenv/config';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* See https://playwright.dev/docs/test-configuration.
|
|
16
|
+
*
|
|
17
|
+
* Generated as a .mts file so Node forces ESM regardless of workspace
|
|
18
|
+
* `type`. Playwright routes `.mts` through its ESM loader (dynamic import,
|
|
19
|
+
* bypassing the pirates CJS-compile path), and Nx's native TS strip loads
|
|
20
|
+
* `.mts` directly. Playwright's configLoader auto-discovers
|
|
21
|
+
* `playwright.config.mts` via its extension list
|
|
22
|
+
* (.ts/.js/.mts/.mjs/.cts/.cjs).
|
|
23
|
+
*/
|
|
24
|
+
export default defineConfig({
|
|
25
|
+
...nxE2EPreset(import.meta.dirname, { testDir: './src' }),
|
|
26
|
+
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
|
27
|
+
use: {
|
|
28
|
+
baseURL,
|
|
29
|
+
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
|
30
|
+
trace: 'on-first-retry',
|
|
31
|
+
},
|
|
32
|
+
/* Run your local dev server before starting the tests */
|
|
33
|
+
webServer: {
|
|
34
|
+
command: 'pnpm exec nx run web:dev',
|
|
35
|
+
url: 'http://localhost:3000',
|
|
36
|
+
reuseExistingServer: true,
|
|
37
|
+
cwd: workspaceRoot,
|
|
38
|
+
},
|
|
39
|
+
projects: [
|
|
40
|
+
{
|
|
41
|
+
name: 'chromium',
|
|
42
|
+
use: { ...devices['Desktop Chrome'] },
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
{
|
|
46
|
+
name: 'firefox',
|
|
47
|
+
use: { ...devices['Desktop Firefox'] },
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
{
|
|
51
|
+
name: 'webkit',
|
|
52
|
+
use: { ...devices['Desktop Safari'] },
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
// Uncomment for mobile browsers support
|
|
56
|
+
/* {
|
|
57
|
+
name: 'Mobile Chrome',
|
|
58
|
+
use: { ...devices['Pixel 5'] },
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'Mobile Safari',
|
|
62
|
+
use: { ...devices['iPhone 12'] },
|
|
63
|
+
}, */
|
|
64
|
+
|
|
65
|
+
// Uncomment for branded browsers
|
|
66
|
+
/* {
|
|
67
|
+
name: 'Microsoft Edge',
|
|
68
|
+
use: { ...devices['Desktop Edge'], channel: 'msedge' },
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'Google Chrome',
|
|
72
|
+
use: { ...devices['Desktop Chrome'], channel: 'chrome' },
|
|
73
|
+
} */
|
|
74
|
+
],
|
|
75
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"allowJs": true,
|
|
5
|
+
"outDir": "out-tsc/playwright",
|
|
6
|
+
"sourceMap": false,
|
|
7
|
+
"types": ["node"]
|
|
8
|
+
},
|
|
9
|
+
"include": [
|
|
10
|
+
"**/*.ts",
|
|
11
|
+
"**/*.js",
|
|
12
|
+
"playwright.config.mts",
|
|
13
|
+
"src/**/*.spec.ts",
|
|
14
|
+
"src/**/*.spec.js",
|
|
15
|
+
"src/**/*.test.ts",
|
|
16
|
+
"src/**/*.test.js",
|
|
17
|
+
"src/**/*.d.ts"
|
|
18
|
+
],
|
|
19
|
+
"exclude": [
|
|
20
|
+
"out-tsc",
|
|
21
|
+
"test-output",
|
|
22
|
+
"eslint.config.js",
|
|
23
|
+
"eslint.config.mjs",
|
|
24
|
+
"eslint.config.cjs"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Shipped core definition for full-stack-app. Layer order, scope, and
|
|
2
|
+
# verify commands are the same shape this package's skills/hedgehog-loop
|
|
3
|
+
# Domain Module step tables describe in prose — this file is their data form.
|
|
4
|
+
# {module} is filled in by the compiler with the domain module name a
|
|
5
|
+
# task is generated for.
|
|
6
|
+
#
|
|
7
|
+
# Every per-module layer's scope carries {module} — module-disjoint by
|
|
8
|
+
# construction, so two modules' tasks never touch the same file
|
|
9
|
+
# (src/db/core.mjs's validateCore enforces this: a module-axis core
|
|
10
|
+
# rejects any non-exclusive layer whose scope omits {module}). schema and
|
|
11
|
+
# hook run Vitest anchored to their own module's directory (`nx test db
|
|
12
|
+
# -- src/schema/{module}/`), a distinct Nx target from typecheck under
|
|
13
|
+
# this workspace's target inference (nx.json), so the command's real
|
|
14
|
+
# radius is exactly its scope — no wider declaration to make. Cross-module
|
|
15
|
+
# type/integration breakage isn't caught at the task that caused it; join
|
|
16
|
+
# is exclusive: true and scoped to everything, running full typecheck and
|
|
17
|
+
# every test once after every module's layers land, in exchange for those
|
|
18
|
+
# layers running in parallel.
|
|
19
|
+
id: full-stack-app
|
|
20
|
+
layers:
|
|
21
|
+
- id: schema
|
|
22
|
+
scope: ["packages/db/src/schema/{module}/**", "packages/db/src/schema/index.ts"]
|
|
23
|
+
verify: "pnpm nx test db -- src/schema/{module}/"
|
|
24
|
+
commit: "feat({module}): schema"
|
|
25
|
+
- id: contract
|
|
26
|
+
depends_on: schema
|
|
27
|
+
scope: ["packages/contracts/src/{module}/**"]
|
|
28
|
+
verify: "pnpm nx test contracts -- src/{module}/"
|
|
29
|
+
commit: "feat({module}): contract"
|
|
30
|
+
- id: repository
|
|
31
|
+
depends_on: contract
|
|
32
|
+
scope: ["libs/{module}/repository/**"]
|
|
33
|
+
verify: "pnpm nx test {module}-repository"
|
|
34
|
+
commit: "feat({module}): repository"
|
|
35
|
+
- id: service
|
|
36
|
+
depends_on: repository
|
|
37
|
+
scope: ["libs/{module}/service/**"]
|
|
38
|
+
verify: "pnpm nx test {module}-service"
|
|
39
|
+
commit: "feat({module}): service"
|
|
40
|
+
- id: controller
|
|
41
|
+
depends_on: service
|
|
42
|
+
scope: ["apps/api/src/app/{module}/**"]
|
|
43
|
+
verify: "pnpm nx test api -- src/app/{module}/"
|
|
44
|
+
commit: "feat({module}): api"
|
|
45
|
+
- id: hook
|
|
46
|
+
depends_on: controller
|
|
47
|
+
scope: ["packages/hooks/src/{module}/**"]
|
|
48
|
+
verify: "pnpm nx test hooks -- src/{module}/"
|
|
49
|
+
commit: "feat({module}): hooks"
|
|
50
|
+
# Web only, because apps/mobile only exists when the Mobile add-on is
|
|
51
|
+
# on. A layer scoped to a project that was never scaffolded fails its
|
|
52
|
+
# own verify on every module, so the Mobile clause is added by
|
|
53
|
+
# hedgehog-bootstrap's Expo step — which is also what creates the Nx
|
|
54
|
+
# project the extra verify target needs — rather than shipped here and
|
|
55
|
+
# broken by default.
|
|
56
|
+
- id: screen
|
|
57
|
+
depends_on: hook
|
|
58
|
+
scope: ["apps/web/src/app/{module}/**"]
|
|
59
|
+
verify: "pnpm nx test web -- src/app/{module}/"
|
|
60
|
+
commit: "feat({module}): screen-web"
|
|
61
|
+
# Workspace-wide by design: the only gate that can see cross-module
|
|
62
|
+
# breakage, since every layer above is parallel and module-scoped.
|
|
63
|
+
- id: join
|
|
64
|
+
depends_on: screen
|
|
65
|
+
scope: ["**"]
|
|
66
|
+
verify: "pnpm nx run-many -t typecheck && pnpm nx run-many -t test"
|
|
67
|
+
exclusive: true
|
|
68
|
+
commit: "chore({module}): join"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
services:
|
|
2
|
+
postgres:
|
|
3
|
+
image: postgres:16-alpine
|
|
4
|
+
environment:
|
|
5
|
+
POSTGRES_USER: postgres
|
|
6
|
+
POSTGRES_PASSWORD: postgres
|
|
7
|
+
POSTGRES_DB: app
|
|
8
|
+
ports:
|
|
9
|
+
- '5432:5432'
|
|
10
|
+
volumes:
|
|
11
|
+
- postgres-data:/var/lib/postgresql/data
|
|
12
|
+
|
|
13
|
+
volumes:
|
|
14
|
+
postgres-data:
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import baseConfig from './packages/config/eslint-base.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Root flat ESLint config. Extends the locked shared base from
|
|
5
|
+
* `packages/config/eslint-base.js` (module boundaries, TypeScript/JS
|
|
6
|
+
* rules). Every app/lib in the workspace resolves through this file —
|
|
7
|
+
* don't add per-project overrides here; fix the base config at its
|
|
8
|
+
* source instead.
|
|
9
|
+
*/
|
|
10
|
+
export default [
|
|
11
|
+
...baseConfig,
|
|
12
|
+
{
|
|
13
|
+
ignores: ['**/vitest.config.*.timestamp*', '**/test-output'],
|
|
14
|
+
},
|
|
15
|
+
];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
node_modules
|
|
2
|
+
dist
|
|
3
|
+
tmp
|
|
4
|
+
out-tsc
|
|
5
|
+
.env
|
|
6
|
+
.env.local
|
|
7
|
+
*.log
|
|
8
|
+
.DS_Store
|
|
9
|
+
.hedgehog/graph-server.json
|
|
10
|
+
.hedgehog/hedgehog.db
|
|
11
|
+
.hedgehog/hedgehog.db-*
|
|
12
|
+
.hedgehog/commit.lock
|
|
13
|
+
|
|
14
|
+
.nx/cache
|
|
15
|
+
.nx/workspace-data
|
|
16
|
+
.nx/polygraph
|
|
17
|
+
.claude/worktrees
|
|
18
|
+
.claude/settings.local.json
|
|
19
|
+
vitest.config.*.timestamp*
|
|
20
|
+
|
|
21
|
+
# Next.js
|
|
22
|
+
.next
|
|
23
|
+
out
|
|
24
|
+
test-output
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# The commit gate. Two things in here are load-bearing and read like
|
|
2
|
+
# noise if you don't know what they're for — don't "clean them up".
|
|
3
|
+
#
|
|
4
|
+
# `assert_lefthook_installed: true` is what makes the gate fail CLOSED.
|
|
5
|
+
# It is consumed by `lefthook install`, which bakes a refusing branch
|
|
6
|
+
# into the generated .git/hooks/* scripts. Without it, a repo whose
|
|
7
|
+
# node_modules has been cleared — a workspace clean, a fresh clone
|
|
8
|
+
# before install, a core switch — prints "Can't find lefthook in PATH"
|
|
9
|
+
# and exits 0, so the commit lands with no typecheck, no lint and no
|
|
10
|
+
# test while .git/hooks and this file both still look like a gate.
|
|
11
|
+
# There is nothing in the output that distinguishes "passed the gate"
|
|
12
|
+
# from "there was no gate". With it, the hook refuses the commit and
|
|
13
|
+
# names the escape hatch (`git commit --no-verify`, or `LEFTHOOK=0`).
|
|
14
|
+
# Restore enforcement with `pnpm install` — lefthook's own postinstall
|
|
15
|
+
# re-runs `lefthook install -f` — or with `pnpm dlx lefthook install`
|
|
16
|
+
# on its own. `hedgehog status` reports whether the gate is live.
|
|
17
|
+
#
|
|
18
|
+
# Because the assertion is written into the hook at install time, this
|
|
19
|
+
# flag only protects hooks generated after it was set. `pnpm install`
|
|
20
|
+
# regenerates them, so any project that has installed once since is
|
|
21
|
+
# covered.
|
|
22
|
+
#
|
|
23
|
+
# The `git rev-parse --verify --quiet HEAD` guard on each command is
|
|
24
|
+
# there because `--base=HEAD` cannot resolve in a repo with no commits:
|
|
25
|
+
# on the very first commit of a fresh install every command dies with
|
|
26
|
+
# "fatal: ambiguous argument 'HEAD': unknown revision", the commit is
|
|
27
|
+
# rejected, and `git commit --no-verify` becomes the only way through —
|
|
28
|
+
# which is exactly the habit this gate exists to prevent. The fallback
|
|
29
|
+
# is `run-many`, not a skip: with no history there is no diff to narrow
|
|
30
|
+
# by, every project is new, and running the whole workspace is both the
|
|
31
|
+
# honest answer and the strongest one. Silencing the gate on the one
|
|
32
|
+
# commit that introduces the entire codebase would be the worst
|
|
33
|
+
# possible place to do it.
|
|
34
|
+
assert_lefthook_installed: true
|
|
35
|
+
|
|
36
|
+
pre-commit:
|
|
37
|
+
parallel: true
|
|
38
|
+
commands:
|
|
39
|
+
typecheck:
|
|
40
|
+
glob: '*.{ts,tsx}'
|
|
41
|
+
run: if git rev-parse --verify --quiet HEAD >/dev/null 2>&1; then npx nx affected -t typecheck --base=HEAD; else npx nx run-many -t typecheck; fi
|
|
42
|
+
lint:
|
|
43
|
+
glob: '*.{ts,tsx}'
|
|
44
|
+
run: if git rev-parse --verify --quiet HEAD >/dev/null 2>&1; then npx nx affected -t lint --base=HEAD; else npx nx run-many -t lint; fi
|
|
45
|
+
test:
|
|
46
|
+
glob: '*.{ts,tsx}'
|
|
47
|
+
run: if git rev-parse --verify --quiet HEAD >/dev/null 2>&1; then npx nx affected -t test --base=HEAD; else npx nx run-many -t test; fi
|
|
48
|
+
|
|
49
|
+
commit-msg:
|
|
50
|
+
commands:
|
|
51
|
+
commitlint:
|
|
52
|
+
run: npx commitlint --edit {1}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./node_modules/nx/schemas/nx-schema.json",
|
|
3
|
+
"targetDefaults": {
|
|
4
|
+
"build": {
|
|
5
|
+
"cache": true,
|
|
6
|
+
"dependsOn": ["generate-module-routes"]
|
|
7
|
+
},
|
|
8
|
+
"dev": {
|
|
9
|
+
"dependsOn": ["generate-module-routes"]
|
|
10
|
+
},
|
|
11
|
+
"test": {
|
|
12
|
+
"cache": true,
|
|
13
|
+
"dependsOn": ["^build", "generate-feature-modules", "generate-module-routes"]
|
|
14
|
+
},
|
|
15
|
+
"typecheck": {
|
|
16
|
+
"dependsOn": ["generate-feature-modules", "generate-module-routes"]
|
|
17
|
+
},
|
|
18
|
+
"lint": {
|
|
19
|
+
"cache": true
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"defaultBase": "master",
|
|
23
|
+
"plugins": [
|
|
24
|
+
{
|
|
25
|
+
"plugin": "@nx/js/typescript",
|
|
26
|
+
"options": {
|
|
27
|
+
"typecheck": {
|
|
28
|
+
"targetName": "typecheck"
|
|
29
|
+
},
|
|
30
|
+
"build": {
|
|
31
|
+
"targetName": "build",
|
|
32
|
+
"configName": "tsconfig.lib.json",
|
|
33
|
+
"buildDepsName": "build-deps",
|
|
34
|
+
"watchDepsName": "watch-deps"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"plugin": "@nx/vitest",
|
|
40
|
+
"options": {
|
|
41
|
+
"testTargetName": "test",
|
|
42
|
+
"ciTargetName": "test-ci",
|
|
43
|
+
"testMode": "watch"
|
|
44
|
+
},
|
|
45
|
+
"exclude": ["apps/api-e2e/**"]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"plugin": "@nx/eslint/plugin",
|
|
49
|
+
"options": {
|
|
50
|
+
"targetName": "lint"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"plugin": "@nx/webpack/plugin",
|
|
55
|
+
"options": {
|
|
56
|
+
"buildTargetName": "build",
|
|
57
|
+
"serveTargetName": "serve",
|
|
58
|
+
"previewTargetName": "preview",
|
|
59
|
+
"buildDepsTargetName": "build-deps",
|
|
60
|
+
"watchDepsTargetName": "watch-deps",
|
|
61
|
+
"serveStaticTargetName": "serve-static"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"plugin": "@nx/next/plugin",
|
|
66
|
+
"options": {
|
|
67
|
+
"startTargetName": "start",
|
|
68
|
+
"buildTargetName": "build",
|
|
69
|
+
"devTargetName": "dev",
|
|
70
|
+
"serveStaticTargetName": "serve-static",
|
|
71
|
+
"buildDepsTargetName": "build-deps",
|
|
72
|
+
"watchDepsTargetName": "watch-deps"
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"plugin": "@nx/playwright/plugin",
|
|
77
|
+
"options": {
|
|
78
|
+
"targetName": "e2e"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
],
|
|
82
|
+
"generators": {
|
|
83
|
+
"@nx/next": {
|
|
84
|
+
"application": {
|
|
85
|
+
"style": "css",
|
|
86
|
+
"linter": "eslint"
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "app",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"packageManager": "pnpm@9.0.0",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "docker compose up -d && nx run-many --target=serve,dev --projects=api,web --parallel"
|
|
8
|
+
},
|
|
9
|
+
"devDependencies": {
|
|
10
|
+
"@commitlint/cli": "^21.2.1",
|
|
11
|
+
"@commitlint/config-conventional": "^21.2.0",
|
|
12
|
+
"@eslint/js": "^10.0.1",
|
|
13
|
+
"@nestjs/schematics": "^11.0.0",
|
|
14
|
+
"@nestjs/testing": "^11.0.0",
|
|
15
|
+
"@next/eslint-plugin-next": "^16.1.6",
|
|
16
|
+
"@nx/devkit": "23.1.0",
|
|
17
|
+
"@nx/eslint": "^23.1.0",
|
|
18
|
+
"@nx/eslint-plugin": "^23.1.0",
|
|
19
|
+
"@nx/js": "^23.1.0",
|
|
20
|
+
"@nx/nest": "23.1.0",
|
|
21
|
+
"@nx/next": "23.1.0",
|
|
22
|
+
"@nx/node": "23.1.0",
|
|
23
|
+
"@nx/playwright": "23.1.0",
|
|
24
|
+
"@nx/vitest": "23.1.0",
|
|
25
|
+
"@nx/web": "23.1.0",
|
|
26
|
+
"@nx/webpack": "23.1.0",
|
|
27
|
+
"@playwright/test": "^1.37.0",
|
|
28
|
+
"@swc-node/register": "~1.11.1",
|
|
29
|
+
"@swc/cli": "~0.8.1",
|
|
30
|
+
"@swc/core": "~1.15.5",
|
|
31
|
+
"@swc/helpers": "~0.5.18",
|
|
32
|
+
"@testing-library/jest-dom": "^7.0.1",
|
|
33
|
+
"@testing-library/react": "^16.3.2",
|
|
34
|
+
"@testing-library/user-event": "^14.6.4",
|
|
35
|
+
"@types/node": "^22.0.0",
|
|
36
|
+
"@types/pg": "^8.20.0",
|
|
37
|
+
"@types/react": "^19.0.0",
|
|
38
|
+
"@types/react-dom": "^19.0.0",
|
|
39
|
+
"@typescript-eslint/eslint-plugin": "^8.65.0",
|
|
40
|
+
"@typescript-eslint/parser": "^8.65.0",
|
|
41
|
+
"@vitejs/plugin-react": "^6.0.5",
|
|
42
|
+
"@vitest/coverage-v8": "~4.1.0",
|
|
43
|
+
"drizzle-kit": "^0.31.10",
|
|
44
|
+
"drizzle-zod": "^0.8.3",
|
|
45
|
+
"eslint": "^10.7.0",
|
|
46
|
+
"eslint-config-next": "^16.1.6",
|
|
47
|
+
"eslint-plugin-import": "2.31.0",
|
|
48
|
+
"eslint-plugin-jsx-a11y": "6.10.1",
|
|
49
|
+
"eslint-plugin-playwright": "^1.6.2",
|
|
50
|
+
"eslint-plugin-react": "^7.35.0",
|
|
51
|
+
"eslint-plugin-react-hooks": "5.0.0",
|
|
52
|
+
"jsdom": "^30.0.1",
|
|
53
|
+
"lefthook": "^2.1.10",
|
|
54
|
+
"nx": "23.1.0",
|
|
55
|
+
"prettier": "~3.6.2",
|
|
56
|
+
"tslib": "^2.3.0",
|
|
57
|
+
"typescript": "~6.0.3",
|
|
58
|
+
"typescript-eslint": "^8.65.0",
|
|
59
|
+
"vite": "^8.0.0",
|
|
60
|
+
"vitest": "~4.1.0",
|
|
61
|
+
"webpack": "^5.101.3",
|
|
62
|
+
"webpack-cli": "^7.0.0",
|
|
63
|
+
"webpack-dev-server": "^5.2.1"
|
|
64
|
+
},
|
|
65
|
+
"dependencies": {
|
|
66
|
+
"@nestjs/common": "^11.0.0",
|
|
67
|
+
"@nestjs/core": "^11.0.0",
|
|
68
|
+
"@nestjs/platform-express": "^11.0.0",
|
|
69
|
+
"axios": "^1.18.0",
|
|
70
|
+
"drizzle-orm": "^0.45.2",
|
|
71
|
+
"nestjs-pino": "^4.6.1",
|
|
72
|
+
"next": "~16.3.0",
|
|
73
|
+
"pg": "^8.22.0",
|
|
74
|
+
"pino-http": "^11.0.0",
|
|
75
|
+
"react": "^19.0.0",
|
|
76
|
+
"react-dom": "^19.0.0",
|
|
77
|
+
"reflect-metadata": "^0.2.0",
|
|
78
|
+
"rxjs": "^7.8.0",
|
|
79
|
+
"zod": "^4.4.3"
|
|
80
|
+
},
|
|
81
|
+
"pnpm": {
|
|
82
|
+
"onlyBuiltDependencies": [
|
|
83
|
+
"lefthook"
|
|
84
|
+
],
|
|
85
|
+
"overrides": {
|
|
86
|
+
"esbuild": "0.25.12",
|
|
87
|
+
"axios": "^1.18.0",
|
|
88
|
+
"brace-expansion@1": "^1.1.18",
|
|
89
|
+
"brace-expansion@2": "^2.1.4",
|
|
90
|
+
"brace-expansion@5": "^5.0.9",
|
|
91
|
+
"fast-uri": "^3.1.5",
|
|
92
|
+
"js-yaml@3": "^3.15.1",
|
|
93
|
+
"js-yaml@4": "^4.3.1",
|
|
94
|
+
"nanoid": "^3.3.17",
|
|
95
|
+
"sharp": "^0.35.0",
|
|
96
|
+
"uuid@8": "^11.1.1"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|