teamshare-bridge 0.3.0 → 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.
Files changed (123) hide show
  1. package/dist/bridge/daemon.js +36 -0
  2. package/dist/bridge/daemon.js.map +1 -1
  3. package/dist/bridge/local-server.d.ts +1 -1
  4. package/dist/bridge/spawn.d.ts +2 -0
  5. package/dist/bridge/spawn.js +17 -0
  6. package/dist/bridge/spawn.js.map +1 -1
  7. package/dist/cli/commands/audit.d.ts +1 -0
  8. package/dist/cli/commands/audit.js +75 -0
  9. package/dist/cli/commands/audit.js.map +1 -0
  10. package/dist/cli/commands/build.js +9 -6
  11. package/dist/cli/commands/build.js.map +1 -1
  12. package/dist/cli/commands/doc.js +1 -1
  13. package/dist/cli/commands/doc.js.map +1 -1
  14. package/dist/cli/commands/run.js +3 -2
  15. package/dist/cli/commands/run.js.map +1 -1
  16. package/dist/cli/commands/scaffold.d.ts +1 -0
  17. package/dist/cli/commands/scaffold.js +111 -0
  18. package/dist/cli/commands/scaffold.js.map +1 -0
  19. package/dist/cli/commands/worker.d.ts +2 -0
  20. package/dist/cli/commands/worker.js +110 -0
  21. package/dist/cli/commands/worker.js.map +1 -0
  22. package/dist/cli/index.js +16 -0
  23. package/dist/cli/index.js.map +1 -1
  24. package/dist/lib/api.d.ts +22 -3
  25. package/dist/lib/api.js +9 -2
  26. package/dist/lib/api.js.map +1 -1
  27. package/dist/lib/audit/docs.d.ts +5 -0
  28. package/dist/lib/audit/docs.js +52 -0
  29. package/dist/lib/audit/docs.js.map +1 -0
  30. package/dist/lib/audit/errors.d.ts +15 -0
  31. package/dist/lib/audit/errors.js +154 -0
  32. package/dist/lib/audit/errors.js.map +1 -0
  33. package/dist/lib/audit/gates.d.ts +2 -0
  34. package/dist/lib/audit/gates.js +57 -0
  35. package/dist/lib/audit/gates.js.map +1 -0
  36. package/dist/lib/audit/modularity.d.ts +13 -0
  37. package/dist/lib/audit/modularity.js +200 -0
  38. package/dist/lib/audit/modularity.js.map +1 -0
  39. package/dist/lib/audit/quality.d.ts +9 -0
  40. package/dist/lib/audit/quality.js +128 -0
  41. package/dist/lib/audit/quality.js.map +1 -0
  42. package/dist/lib/audit/rbac.d.ts +14 -0
  43. package/dist/lib/audit/rbac.js +139 -0
  44. package/dist/lib/audit/rbac.js.map +1 -0
  45. package/dist/lib/audit/reporter.d.ts +5 -0
  46. package/dist/lib/audit/reporter.js +107 -0
  47. package/dist/lib/audit/reporter.js.map +1 -0
  48. package/dist/lib/audit/runner.d.ts +2 -0
  49. package/dist/lib/audit/runner.js +150 -0
  50. package/dist/lib/audit/runner.js.map +1 -0
  51. package/dist/lib/audit/security.d.ts +9 -0
  52. package/dist/lib/audit/security.js +151 -0
  53. package/dist/lib/audit/security.js.map +1 -0
  54. package/dist/lib/audit/types.d.ts +67 -0
  55. package/dist/lib/audit/types.js +26 -0
  56. package/dist/lib/audit/types.js.map +1 -0
  57. package/dist/lib/audit/ux.d.ts +9 -0
  58. package/dist/lib/audit/ux.js +112 -0
  59. package/dist/lib/audit/ux.js.map +1 -0
  60. package/dist/lib/config.d.ts +1 -1
  61. package/dist/lib/config.js +1 -1
  62. package/dist/lib/llm.js +1 -0
  63. package/dist/lib/llm.js.map +1 -1
  64. package/dist/lib/lock.d.ts +1 -1
  65. package/dist/lib/scaffold/renderer.d.ts +7 -0
  66. package/dist/lib/scaffold/renderer.js +37 -0
  67. package/dist/lib/scaffold/renderer.js.map +1 -0
  68. package/dist/lib/scaffold/structure.d.ts +3 -0
  69. package/dist/lib/scaffold/structure.js +73 -0
  70. package/dist/lib/scaffold/structure.js.map +1 -0
  71. package/dist/lib/scaffold/types.d.ts +34 -0
  72. package/dist/lib/scaffold/types.js +6 -0
  73. package/dist/lib/scaffold/types.js.map +1 -0
  74. package/dist/lib/scaffold/verify.d.ts +9 -0
  75. package/dist/lib/scaffold/verify.js +48 -0
  76. package/dist/lib/scaffold/verify.js.map +1 -0
  77. package/dist/lib/skills.d.ts +2 -2
  78. package/dist/lib/skills.js +2 -1
  79. package/dist/lib/skills.js.map +1 -1
  80. package/package.json +3 -2
  81. package/skills/teamshare-orchestrator-ask/SKILL.md +14 -0
  82. package/skills/teamshare-scaffold/SKILL.md +133 -0
  83. package/templates/backend/.env.example.tpl +13 -0
  84. package/templates/backend/nest-cli.json.tpl +8 -0
  85. package/templates/backend/package.json.tpl +41 -0
  86. package/templates/backend/prisma/schema.prisma.tpl +39 -0
  87. package/templates/backend/src/app.module.ts.tpl +24 -0
  88. package/templates/backend/src/common/filters/all-exceptions.filter.ts.tpl +59 -0
  89. package/templates/backend/src/common/guards/jwt-auth.guard.ts.tpl +27 -0
  90. package/templates/backend/src/common/guards/rbac.guard.ts.tpl +48 -0
  91. package/templates/backend/src/common/interceptors/transform.interceptor.ts.tpl +44 -0
  92. package/templates/backend/src/common/pipes/zod-validation.pipe.ts.tpl +29 -0
  93. package/templates/backend/src/common/swagger/envelope.schemas.ts.tpl +53 -0
  94. package/templates/backend/src/common/swagger/error.schemas.ts.tpl +62 -0
  95. package/templates/backend/src/main.ts.tpl +27 -0
  96. package/templates/backend/src/modules/example/example.controller.ts.tpl +102 -0
  97. package/templates/backend/src/modules/example/example.dto.ts.tpl +14 -0
  98. package/templates/backend/src/modules/example/example.module.ts.tpl +10 -0
  99. package/templates/backend/src/modules/example/example.service.ts.tpl +45 -0
  100. package/templates/backend/tsconfig.json.tpl +26 -0
  101. package/templates/common/.gitignore.tpl +42 -0
  102. package/templates/common/AGENTS.md.tpl +58 -0
  103. package/templates/common/docs/adr/README.md +25 -0
  104. package/templates/common/docs/api-contract.md.tpl +72 -0
  105. package/templates/web/next.config.ts.tpl +7 -0
  106. package/templates/web/package.json.tpl +37 -0
  107. package/templates/web/src/app/globals.css.tpl +48 -0
  108. package/templates/web/src/app/layout.tsx.tpl +25 -0
  109. package/templates/web/src/components/shared/app-button.tsx.tpl +59 -0
  110. package/templates/web/src/components/shared/app-empty-state.tsx.tpl +39 -0
  111. package/templates/web/src/components/shared/app-list-toolbar.tsx.tpl +63 -0
  112. package/templates/web/src/components/shared/app-skeleton.tsx.tpl +14 -0
  113. package/templates/web/src/components/shared/app-table.tsx.tpl +128 -0
  114. package/templates/web/src/components/shared/index.ts.tpl +5 -0
  115. package/templates/web/src/hooks/use-list-state.ts.tpl +72 -0
  116. package/templates/web/src/hooks/use-url-tab.ts.tpl +25 -0
  117. package/templates/web/src/lib/api/client.ts.tpl +123 -0
  118. package/templates/web/src/lib/providers.tsx.tpl +35 -0
  119. package/templates/web/src/lib/query-keys.ts.tpl +21 -0
  120. package/templates/web/src/lib/utils.ts.tpl +7 -0
  121. package/templates/web/src/lib/validation/schemas.ts.tpl +15 -0
  122. package/templates/web/src/modules/example/views/example-list-view.tsx.tpl +98 -0
  123. package/templates/web/tsconfig.json.tpl +23 -0
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.verifyScaffold = verifyScaffold;
4
+ /**
5
+ * Scaffold verification — runs build/typecheck on the scaffolded project.
6
+ */
7
+ const node_child_process_1 = require("node:child_process");
8
+ function verifyScaffold(rootPath, type) {
9
+ const steps = [];
10
+ // Install dependencies
11
+ steps.push(runStep(rootPath, 'npm install', 'install'));
12
+ // Type-specific verification
13
+ if (type === 'web' || type === 'full') {
14
+ steps.push(runStep(rootPath, 'npm run build', 'next-build'));
15
+ }
16
+ if (type === 'backend' || type === 'full') {
17
+ steps.push(runStep(rootPath, 'npx prisma generate', 'prisma-generate'));
18
+ steps.push(runStep(rootPath, 'npm run build', 'nest-build'));
19
+ }
20
+ if (type === 'mobile') {
21
+ steps.push(runStep(rootPath, 'npx expo export --dump-sourcemap', 'expo-export'));
22
+ }
23
+ return {
24
+ passed: steps.every((s) => s.passed),
25
+ steps,
26
+ };
27
+ }
28
+ function runStep(cwd, command, name) {
29
+ try {
30
+ (0, node_child_process_1.execSync)(command, {
31
+ cwd,
32
+ timeout: 120_000,
33
+ encoding: 'utf-8',
34
+ stdio: ['pipe', 'pipe', 'pipe'],
35
+ env: { ...process.env, CI: 'true' },
36
+ });
37
+ return { name, passed: true };
38
+ }
39
+ catch (err) {
40
+ const e = err;
41
+ return {
42
+ name,
43
+ passed: false,
44
+ error: (e.stderr ?? e.message ?? 'Unknown error').slice(0, 1000),
45
+ };
46
+ }
47
+ }
48
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../../src/lib/scaffold/verify.ts"],"names":[],"mappings":";;AAUA,wCAsBC;AAhCD;;GAEG;AACH,2DAA8C;AAO9C,SAAgB,cAAc,CAAC,QAAgB,EAAE,IAAY;IAC3D,MAAM,KAAK,GAAwD,EAAE,CAAC;IAEtE,uBAAuB;IACvB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC;IAExD,6BAA6B;IAC7B,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,qBAAqB,EAAE,iBAAiB,CAAC,CAAC,CAAC;QACxE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,kCAAkC,EAAE,aAAa,CAAC,CAAC,CAAC;IACnF,CAAC;IAED,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QACpC,KAAK;KACN,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,GAAW,EAAE,OAAe,EAAE,IAAY;IACzD,IAAI,CAAC;QACH,IAAA,6BAAQ,EAAC,OAAO,EAAE;YAChB,GAAG;YACH,OAAO,EAAE,OAAO;YAChB,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE;SACpC,CAAC,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAChC,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,GAA4C,CAAC;QACvD,OAAO;YACL,IAAI;YACJ,MAAM,EAAE,KAAK;YACb,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,OAAO,IAAI,eAAe,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;SACjE,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -1,5 +1,5 @@
1
- /** The four skills shipped with the bridge (source of truth: ./skills). */
2
- export declare const SHIPPED_SKILLS: readonly ["teamshare-cdd", "teamshare-modularity", "teamshare-auth-rbac", "teamshare-orchestrator-ask"];
1
+ /** The five skills shipped with the bridge (source of truth: ./skills). */
2
+ export declare const SHIPPED_SKILLS: readonly ["teamshare-cdd", "teamshare-modularity", "teamshare-auth-rbac", "teamshare-orchestrator-ask", "teamshare-scaffold"];
3
3
  /** Source: <package>/skills (ships in the npm tarball via package.json files). */
4
4
  export declare function skillsSourceDir(): string;
5
5
  /** Target: ~/.agents/skills (opencode convention) unless overridden. */
@@ -16,12 +16,13 @@ exports.uninstallSkills = uninstallSkills;
16
16
  const node_fs_1 = require("node:fs");
17
17
  const node_os_1 = require("node:os");
18
18
  const node_path_1 = require("node:path");
19
- /** The four skills shipped with the bridge (source of truth: ./skills). */
19
+ /** The five skills shipped with the bridge (source of truth: ./skills). */
20
20
  exports.SHIPPED_SKILLS = [
21
21
  'teamshare-cdd',
22
22
  'teamshare-modularity',
23
23
  'teamshare-auth-rbac',
24
24
  'teamshare-orchestrator-ask',
25
+ 'teamshare-scaffold',
25
26
  ];
26
27
  /** Source: <package>/skills (ships in the npm tarball via package.json files). */
27
28
  function skillsSourceDir() {
@@ -1 +1 @@
1
- {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/lib/skills.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/lib/skills.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
- {
1
+ {
2
2
  "name": "teamshare-bridge",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Local bridge for TeamShare agents - CLI session runner, auto-wake WebSocket daemon, and teamshare:// protocol handler.",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
@@ -19,6 +19,7 @@
19
19
  "files": [
20
20
  "dist",
21
21
  "skills",
22
+ "templates",
22
23
  "tools",
23
24
  "README.md"
24
25
  ],
@@ -61,3 +61,17 @@ Humans can answer from two places:
61
61
  2. **#agent-questions chat**: answer in the project's agent-questions channel
62
62
 
63
63
  Both surfaces trigger the same `question.answered` wake event.
64
+
65
+ ## Merge conflicts (IMP-810)
66
+
67
+ When two agents edit the same file and their branches conflict during merge:
68
+ 1. The orchestrator blocks the task (`status: 'blocked'`, `workerStatus: 'blocked'`)
69
+ 2. A `[question]` comment is posted on the linked task listing the conflicting files
70
+ 3. The OT transitions to `question_pending`
71
+ 4. A human resolves the conflicts (manually or by telling an agent what to do)
72
+ 5. When the question is answered, the OT requeues and the worker retries
73
+
74
+ If you are the worker agent and see a merge conflict:
75
+ - Do NOT force-push or overwrite the integration branch
76
+ - Wait for the human to resolve or give you instructions
77
+ - When re-dispatched, pull the latest integration branch and re-apply your changes
@@ -0,0 +1,133 @@
1
+ ---
2
+ name: teamshare-scaffold
3
+ description: "Enforce TeamShare standards when scaffolding new codebases, auditing existing ones, or cleaning up code. Covers stack decisions, folder layouts, view recipes, RBAC guards, loading states, safety patterns (no lint-disable unless worse), and the audit report format."
4
+ ---
5
+
6
+ # teamshare-scaffold
7
+
8
+ Standards enforcement for TeamShare codebases. Use when scaffolding a new repo, auditing an existing codebase, or cleaning up code.
9
+
10
+ ## Stack Decisions
11
+
12
+ | Layer | Stack |
13
+ |-------|-------|
14
+ | Web | Next.js App Router + TS + Tailwind v4 + shadcn (radix-nova) + TS* wrappers |
15
+ | Icons | iconsax-react (variant+color always, no emoji) |
16
+ | Tables | @tanstack/react-table v8 (NOT v9) |
17
+ | Forms | TSForm + zodResolver + zod schemas mirroring backend |
18
+ | State | useListState + useUrlTab (URL-driven) |
19
+ | Backend | NestJS 11 + Prisma 6 + zod-first DTOs + envelope |
20
+ | Mobile | Expo SDK 57 + NativeWind v4 + reusables |
21
+
22
+ ## Frontend Layout
23
+
24
+ - `src/components/ui/` = VENDOR shadcn. DO NOT EDIT. DO NOT IMPORT from app code.
25
+ - `src/components/shared/` = Shared wrappers (AppButton, AppTable, etc). Barrel index.ts.
26
+ - `src/modules/<feature>/{views,components,columns,hooks,utils}`
27
+ - `src/lib/api/<feature>.ts` + `src/lib/query-keys.ts` + `src/lib/validation/schemas.ts`
28
+ - Pages stay thin. Views do the work.
29
+
30
+ ## Backend Layout
31
+
32
+ - `src/modules/<feature>/{controller,service,dto,module}`
33
+ - `src/common/{guards,filters,interceptors,pipes,swagger,constants,utils,prisma,logging}`
34
+ - Prisma schema.prisma is canonical. `npx prisma migrate deploy` only.
35
+
36
+ ## View Recipe (every list view)
37
+
38
+ 1. `useListState({ pageSize })` - URL-driven
39
+ 2. `useQuery({ queryKey: qkList(qk.x, list.query), queryFn: () => api.list(token, list.query) })`
40
+ 3. Loading: `AppSkeleton` rows (3-6)
41
+ 4. Empty: `AppTable` with emptyTitle + emptyDescription + emptyAction (create CTA)
42
+ 5. Error: `ErrorState` with retry
43
+ 6. Toolbar: `AppListToolbar` with actions slot (create button always visible)
44
+ 7. Mutations: `useMutation` + toast success/error + `queryClient.invalidateQueries`
45
+
46
+ Every view MUST handle loading, error, and empty states. Never show white screen.
47
+
48
+ ## RBAC Guard Table
49
+
50
+ | Who | Guard stack |
51
+ |-----|-------------|
52
+ | Human only | `@Permissions('entity.action')` |
53
+ | Agent + human | `@Public()` + `AgentsDualAuthGuard` + `@ApiKeyScopes` |
54
+ | Truly public | `@Public()` only |
55
+ | MCP | `ApiKeyGuard` + `canUseTool()` |
56
+
57
+ Never combine @Permissions with AgentsDualAuthGuard on same route.
58
+
59
+ Three enforcement layers: capability + key scope + project access. Never less than two.
60
+
61
+ ## IconSax Rules
62
+
63
+ Every icon instance MUST pass `variant` and `color` props. Default variant="Outline".
64
+ - Bold for active nav
65
+ - TwoTone for empty-state illustrations
66
+ - Broken for destructive confirmations
67
+ - Sizes: 16/20/24/32
68
+
69
+ ## Safety Patterns
70
+
71
+ 1. **eslint-disable only when fix is worse.** Add `// eslint-disable-next-line <rule> -- <reason>`. Inventoried for revert.
72
+ 2. **Never hand-edit generated/ or vendor ui/.**
73
+ 3. **Build/typecheck verified.** Failed fixes reverted + noted.
74
+ 4. **Cleanup in worktrees/branches.**
75
+ 5. **Secrets never in code/logs/messages.**
76
+ 6. **Existing repos: additive fixes only.** Never restructure.
77
+ 7. **Max 120 chars per line.**
78
+
79
+ ## Audit Report Format
80
+
81
+ When running an audit, produce findings in this structure:
82
+
83
+ ```
84
+ # Audit Report — [repo-name]
85
+
86
+ **Date:** YYYY-MM-DD
87
+ **Scope:** [files scanned]
88
+
89
+ ## Critical / Security
90
+ - [finding] [file:line] [evidence] [suggested fix]
91
+
92
+ ## Modularity
93
+ - [finding] [file:line] [evidence] [suggested fix]
94
+
95
+ ## Quality
96
+ - [finding] [file:line] [evidence] [suggested fix]
97
+
98
+ ## Advisory (existing code)
99
+ - [finding] [file:line] [note]
100
+
101
+ ## Summary
102
+ - Total findings: N (Critical: X, Security: Y, Modularity: Z, Quality: W)
103
+ - Gate status: build [pass/fail], typecheck [pass/fail]
104
+ ```
105
+
106
+ Severity levels: Critical (security, data loss), High (broken patterns, missing guards),
107
+ Medium (quality, missing states), Low (style, naming), Advisory (existing code deviations).
108
+
109
+ ## Scaffold Task Flow
110
+
111
+ When asked to scaffold a new codebase:
112
+ 1. Ask questions first (stack, auth provider, DB, package manager) if --ask
113
+ 2. Write plan.md before generating
114
+ 3. Create folder tree from template
115
+ 4. Write AGENTS.md + docs/ skeleton
116
+ 5. Generate module skeletons with full guard stack + loading states
117
+ 6. Run build/typecheck gates
118
+ 7. Write summary.md with what was built
119
+
120
+ When asked to audit an existing codebase:
121
+ 1. Scan all dimensions (security, modularity, rbac, errors, quality, ux, docs, gates)
122
+ 2. Existing code deviations = Advisory only (never force restructure)
123
+ 3. New code deviations = High/Critical findings
124
+ 4. Produce detailed markdown report with file:line evidence
125
+ 5. Suggest fixes for each finding
126
+
127
+ When asked to clean up code:
128
+ 1. Run audit first
129
+ 2. Group findings into fix tasks
130
+ 3. Apply mechanical fixes (line length, naming, imports)
131
+ 4. For complex fixes: ask_human or route to orchestrator
132
+ 5. Every fix verified by build/typecheck
133
+ 6. Failed fixes reverted + noted in report
@@ -0,0 +1,13 @@
1
+ # Database
2
+ DATABASE_URL="postgresql://user:password@localhost:5432/{{slug}}?schema=public"
3
+
4
+ # JWT
5
+ JWT_SECRET="change-me-to-a-random-secret"
6
+ JWT_EXPIRES_IN="7d"
7
+
8
+ # Server
9
+ PORT={{apiPort}}
10
+ NODE_ENV=development
11
+
12
+ # CORS
13
+ CORS_ORIGIN="http://localhost:{{port}}"
@@ -0,0 +1,8 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/nest-cli",
3
+ "collection": "@nestjs/schematics",
4
+ "sourceRoot": "src",
5
+ "compilerOptions": {
6
+ "deleteOutDir": true
7
+ }
8
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "{{packageName}}",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "description": "{{description}}",
6
+ "scripts": {
7
+ "build": "nest build",
8
+ "start": "nest start",
9
+ "start:dev": "nest start --watch",
10
+ "prisma:generate": "prisma generate",
11
+ "prisma:migrate": "prisma migrate dev",
12
+ "lint": "eslint src"
13
+ },
14
+ "dependencies": {
15
+ "@nestjs/common": "^11.0.0",
16
+ "@nestjs/config": "^4.0.0",
17
+ "@nestjs/core": "^11.0.0",
18
+ "@nestjs/passport": "^11.0.0",
19
+ "@nestjs/platform-express": "^11.0.0",
20
+ "@nestjs/swagger": "^11.0.0",
21
+ "@prisma/client": "^6.0.0",
22
+ "argon2": "^0.41.0",
23
+ "class-transformer": "^0.5.1",
24
+ "class-validator": "^0.14.0",
25
+ "passport": "^0.7.0",
26
+ "passport-jwt": "^4.0.1",
27
+ "prisma-zod-generator": "^0.9.0",
28
+ "reflect-metadata": "^0.2.0",
29
+ "rxjs": "^7.8.0",
30
+ "socket.io": "^4.8.0",
31
+ "zod": "^3.23.0"
32
+ },
33
+ "devDependencies": {
34
+ "@nestjs/cli": "^11.0.0",
35
+ "@nestjs/schematics": "^11.0.0",
36
+ "@types/node": "^22.0.0",
37
+ "@types/passport-jwt": "^4.0.0",
38
+ "prisma": "^6.0.0",
39
+ "typescript": "^5.6.0"
40
+ }
41
+ }
@@ -0,0 +1,39 @@
1
+ generator client {
2
+ provider = "prisma-client-js"
3
+ }
4
+
5
+ generator zod {
6
+ provider = "prisma-zod-generator"
7
+ output = "../src/generated/zod"
8
+ }
9
+
10
+ datasource db {
11
+ provider = "postgresql"
12
+ url = env("DATABASE_URL")
13
+ }
14
+
15
+ model User {
16
+ id String @id @default(uuid()) @db.Uuid
17
+ email String @unique
18
+ name String?
19
+ password String
20
+ createdAt DateTime @default(now()) @map("created_at")
21
+ updatedAt DateTime @updatedAt @map("updated_at")
22
+
23
+ apiKey ApiKey[]
24
+
25
+ @@map("users")
26
+ }
27
+
28
+ model ApiKey {
29
+ id String @id @default(uuid()) @db.Uuid
30
+ key String @unique
31
+ name String
32
+ userId String @map("user_id") @db.Uuid
33
+ createdAt DateTime @default(now()) @map("created_at")
34
+ lastUsed DateTime? @map("last_used")
35
+
36
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
37
+
38
+ @@map("api_keys")
39
+ }
@@ -0,0 +1,24 @@
1
+ import { Module } from "@nestjs/common";
2
+ import { ConfigModule } from "@nestjs/config";
3
+ import { APP_GUARD, APP_FILTER, APP_INTERCEPTOR } from "@nestjs/core";
4
+ import { AuthGuard } from "./common/guards/jwt-auth.guard";
5
+ import { RbacGuard } from "./common/guards/rbac.guard";
6
+ import { AllExceptionsFilter } from "./common/filters/all-exceptions.filter";
7
+ import { TransformInterceptor } from "./common/interceptors/transform.interceptor";
8
+ import { PrismaModule } from "./prisma/prisma.module";
9
+ import { ExampleModule } from "./modules/example/example.module";
10
+
11
+ @Module({
12
+ imports: [
13
+ ConfigModule.forRoot({ isGlobal: true }),
14
+ PrismaModule,
15
+ ExampleModule,
16
+ ],
17
+ providers: [
18
+ { provide: APP_GUARD, useClass: AuthGuard },
19
+ { provide: APP_GUARD, useClass: RbacGuard },
20
+ { provide: APP_FILTER, useClass: AllExceptionsFilter },
21
+ { provide: APP_INTERCEPTOR, useClass: TransformInterceptor },
22
+ ],
23
+ })
24
+ export class AppModule {}
@@ -0,0 +1,59 @@
1
+ import {
2
+ ExceptionFilter,
3
+ Catch,
4
+ ArgumentsHost,
5
+ HttpException,
6
+ HttpStatus,
7
+ } from "@nestjs/common";
8
+ import { Response } from "express";
9
+
10
+ @Catch()
11
+ export class AllExceptionsFilter implements ExceptionFilter {
12
+ catch(exception: unknown, host: ArgumentsHost) {
13
+ const ctx = host.switchToHttp();
14
+ const response = ctx.getResponse<Response>();
15
+
16
+ let status = HttpStatus.INTERNAL_SERVER_ERROR;
17
+ let code = "INTERNAL_ERROR";
18
+ let message = "An unexpected error occurred";
19
+ let details: unknown = undefined;
20
+
21
+ if (exception instanceof HttpException) {
22
+ status = exception.getStatus();
23
+ const res = exception.getResponse();
24
+ if (typeof res === "string") {
25
+ message = res;
26
+ } else if (typeof res === "object" && res !== null) {
27
+ const obj = res as Record<string, unknown>;
28
+ message = (obj.message as string) ?? message;
29
+ code = (obj.error as string) ?? code;
30
+ details = obj.details;
31
+ }
32
+ code = this.codeFromStatus(status);
33
+ } else if (exception instanceof Error) {
34
+ message = exception.message;
35
+ }
36
+
37
+ response.status(status).json({
38
+ success: false,
39
+ error: {
40
+ code,
41
+ message,
42
+ details,
43
+ },
44
+ });
45
+ }
46
+
47
+ private codeFromStatus(status: number): string {
48
+ const map: Record<number, string> = {
49
+ 400: "BAD_REQUEST",
50
+ 401: "UNAUTHORIZED",
51
+ 403: "FORBIDDEN",
52
+ 404: "NOT_FOUND",
53
+ 409: "CONFLICT",
54
+ 422: "UNPROCESSABLE_ENTITY",
55
+ 429: "TOO_MANY_REQUESTS",
56
+ };
57
+ return map[status] ?? "INTERNAL_ERROR";
58
+ }
59
+ }
@@ -0,0 +1,27 @@
1
+ import { ExecutionContext, Injectable, UnauthorizedException } from "@nestjs/common";
2
+ import { Reflector } from "@nestjs/core";
3
+ import { AuthGuard as PassportAuthGuard } from "@nestjs/passport";
4
+ import { IS_PUBLIC_KEY } from "../decorators/public.decorator";
5
+
6
+ @Injectable()
7
+ export class AuthGuard extends PassportAuthGuard("jwt") {
8
+ constructor(private reflector: Reflector) {
9
+ super();
10
+ }
11
+
12
+ canActivate(context: ExecutionContext) {
13
+ const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
14
+ context.getHandler(),
15
+ context.getClass(),
16
+ ]);
17
+ if (isPublic) return true;
18
+ return super.canActivate(context);
19
+ }
20
+
21
+ handleRequest(err: unknown, user: unknown) {
22
+ if (err || !user) {
23
+ throw err ?? new UnauthorizedException("Invalid or missing token");
24
+ }
25
+ return user;
26
+ }
27
+ }
@@ -0,0 +1,48 @@
1
+ import {
2
+ CanActivate,
3
+ ExecutionContext,
4
+ ForbiddenException,
5
+ Injectable,
6
+ } from "@nestjs/common";
7
+ import { Reflector } from "@nestjs/core";
8
+ import { PERMISSIONS_KEY } from "../decorators/permissions.decorator";
9
+ import { IS_PUBLIC_KEY } from "../decorators/public.decorator";
10
+
11
+ @Injectable()
12
+ export class RbacGuard implements CanActivate {
13
+ constructor(private reflector: Reflector) {}
14
+
15
+ canActivate(context: ExecutionContext): boolean {
16
+ const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
17
+ context.getHandler(),
18
+ context.getClass(),
19
+ ]);
20
+ if (isPublic) return true;
21
+
22
+ const requiredPermissions = this.reflector.getAllAndOverride<string[]>(
23
+ PERMISSIONS_KEY,
24
+ [context.getHandler(), context.getClass()]
25
+ );
26
+ if (!requiredPermissions || requiredPermissions.length === 0) return true;
27
+
28
+ const request = context.switchToHttp().getRequest();
29
+ const user = request.user;
30
+
31
+ if (!user) {
32
+ throw new ForbiddenException("Authentication required");
33
+ }
34
+
35
+ const userPermissions: string[] = user.permissions ?? [];
36
+ const hasPermission = requiredPermissions.every((p) =>
37
+ userPermissions.includes(p)
38
+ );
39
+
40
+ if (!hasPermission) {
41
+ throw new ForbiddenException(
42
+ `Missing required permissions: ${requiredPermissions.join(", ")}`
43
+ );
44
+ }
45
+
46
+ return true;
47
+ }
48
+ }
@@ -0,0 +1,44 @@
1
+ import {
2
+ Injectable,
3
+ NestInterceptor,
4
+ ExecutionContext,
5
+ CallHandler,
6
+ } from "@nestjs/common";
7
+ import { Observable, map } from "rxjs";
8
+
9
+ export interface SuccessResponse<T> {
10
+ success: true;
11
+ data: T;
12
+ pagination?: {
13
+ page: number;
14
+ limit: number;
15
+ total: number;
16
+ totalPages: number;
17
+ };
18
+ }
19
+
20
+ @Injectable()
21
+ export class TransformInterceptor<T>
22
+ implements NestInterceptor<T, SuccessResponse<T>>
23
+ {
24
+ intercept(
25
+ context: ExecutionContext,
26
+ next: CallHandler
27
+ ): Observable<SuccessResponse<T>> {
28
+ return next.handle().pipe(
29
+ map((data) => {
30
+ if (data && typeof data === "object" && "data" in data && "pagination" in data) {
31
+ return {
32
+ success: true as const,
33
+ data: data.data,
34
+ pagination: data.pagination,
35
+ };
36
+ }
37
+ return {
38
+ success: true as const,
39
+ data,
40
+ };
41
+ })
42
+ );
43
+ }
44
+ }
@@ -0,0 +1,29 @@
1
+ import {
2
+ PipeTransform,
3
+ Injectable,
4
+ BadRequestException,
5
+ } from "@nestjs/common";
6
+ import { ZodSchema } from "zod";
7
+
8
+ @Injectable()
9
+ export class ZodValidationPipe implements PipeTransform {
10
+ constructor(
11
+ private schema: ZodSchema,
12
+ private source: "body" | "query" | "params" = "body"
13
+ ) {}
14
+
15
+ transform(value: unknown) {
16
+ const result = this.schema.safeParse(value);
17
+ if (!result.success) {
18
+ const issues = result.error.issues.map((i) => ({
19
+ path: i.path.join("."),
20
+ message: i.message,
21
+ }));
22
+ throw new BadRequestException({
23
+ message: "Validation failed",
24
+ details: issues,
25
+ });
26
+ }
27
+ return result.data;
28
+ }
29
+ }
@@ -0,0 +1,53 @@
1
+
2
+ export function successSchema(dataSchema: Record<string, unknown>) {
3
+ return {
4
+ type: "object",
5
+ properties: {
6
+ success: { type: "boolean", example: true },
7
+ data: dataSchema,
8
+ },
9
+ required: ["success", "data"],
10
+ };
11
+ }
12
+
13
+ export function paginatedSchema(dataSchema: Record<string, unknown>) {
14
+ return {
15
+ type: "object",
16
+ properties: {
17
+ success: { type: "boolean", example: true },
18
+ data: {
19
+ type: "array",
20
+ items: dataSchema,
21
+ },
22
+ pagination: {
23
+ type: "object",
24
+ properties: {
25
+ page: { type: "number", example: 1 },
26
+ limit: { type: "number", example: 20 },
27
+ total: { type: "number", example: 100 },
28
+ totalPages: { type: "number", example: 5 },
29
+ },
30
+ },
31
+ },
32
+ required: ["success", "data", "pagination"],
33
+ };
34
+ }
35
+
36
+ export function errorSchema() {
37
+ return {
38
+ type: "object",
39
+ properties: {
40
+ success: { type: "boolean", example: false },
41
+ error: {
42
+ type: "object",
43
+ properties: {
44
+ code: { type: "string", example: "NOT_FOUND" },
45
+ message: { type: "string", example: "Resource not found" },
46
+ details: {},
47
+ },
48
+ required: ["code", "message"],
49
+ },
50
+ },
51
+ required: ["success", "error"],
52
+ };
53
+ }