agent-enderun 1.10.2 → 1.11.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/README.md +34 -44
- package/dist/framework-mcp/src/constants.d.ts +47 -0
- package/dist/framework-mcp/src/constants.js +65 -0
- package/dist/framework-mcp/src/constants.js.map +1 -0
- package/dist/framework-mcp/src/index.js +26 -5
- package/dist/framework-mcp/src/index.js.map +1 -1
- package/dist/framework-mcp/src/tools/control_plane/locking.d.ts +3 -9
- package/dist/framework-mcp/src/tools/control_plane/locking.js.map +1 -1
- package/dist/framework-mcp/src/tools/control_plane/registry.d.ts +2 -8
- package/dist/framework-mcp/src/tools/control_plane/registry.js.map +1 -1
- package/dist/framework-mcp/src/tools/dashboard/start_dashboard.d.ts +2 -2
- package/dist/framework-mcp/src/tools/dashboard/start_dashboard.js.map +1 -1
- package/dist/framework-mcp/src/tools/definitions.js +30 -0
- package/dist/framework-mcp/src/tools/definitions.js.map +1 -1
- package/dist/framework-mcp/src/tools/file_system/batch_surgical_edit.d.ts +2 -2
- package/dist/framework-mcp/src/tools/file_system/batch_surgical_edit.js +12 -4
- package/dist/framework-mcp/src/tools/file_system/batch_surgical_edit.js.map +1 -1
- package/dist/framework-mcp/src/tools/file_system/patch_file.d.ts +2 -2
- package/dist/framework-mcp/src/tools/file_system/patch_file.js +6 -2
- package/dist/framework-mcp/src/tools/file_system/patch_file.js.map +1 -1
- package/dist/framework-mcp/src/tools/file_system/read_file.d.ts +2 -2
- package/dist/framework-mcp/src/tools/file_system/read_file.js +43 -26
- package/dist/framework-mcp/src/tools/file_system/read_file.js.map +1 -1
- package/dist/framework-mcp/src/tools/file_system/replace_text.d.ts +2 -2
- package/dist/framework-mcp/src/tools/file_system/replace_text.js +7 -3
- package/dist/framework-mcp/src/tools/file_system/replace_text.js.map +1 -1
- package/dist/framework-mcp/src/tools/file_system/write_file.d.ts +2 -2
- package/dist/framework-mcp/src/tools/file_system/write_file.js +27 -15
- package/dist/framework-mcp/src/tools/file_system/write_file.js.map +1 -1
- package/dist/framework-mcp/src/tools/framework/get_status.d.ts +2 -2
- package/dist/framework-mcp/src/tools/framework/get_status.js.map +1 -1
- package/dist/framework-mcp/src/tools/framework/orchestrate.d.ts +2 -2
- package/dist/framework-mcp/src/tools/framework/orchestrate.js.map +1 -1
- package/dist/framework-mcp/src/tools/framework/run_tests.d.ts +2 -2
- package/dist/framework-mcp/src/tools/framework/run_tests.js.map +1 -1
- package/dist/framework-mcp/src/tools/framework/update_contract_hash.d.ts +2 -2
- package/dist/framework-mcp/src/tools/framework/update_contract_hash.js.map +1 -1
- package/dist/framework-mcp/src/tools/framework/update_memory.d.ts +2 -2
- package/dist/framework-mcp/src/tools/framework/update_memory.js +1 -1
- package/dist/framework-mcp/src/tools/framework/update_memory.js.map +1 -1
- package/dist/framework-mcp/src/tools/index.d.ts +1 -2
- package/dist/framework-mcp/src/tools/index.js +33 -25
- package/dist/framework-mcp/src/tools/index.js.map +1 -1
- package/dist/framework-mcp/src/tools/messaging/log_action.d.ts +2 -2
- package/dist/framework-mcp/src/tools/messaging/log_action.js.map +1 -1
- package/dist/framework-mcp/src/tools/messaging/send_message.d.ts +2 -2
- package/dist/framework-mcp/src/tools/messaging/send_message.js +14 -1
- package/dist/framework-mcp/src/tools/messaging/send_message.js.map +1 -1
- package/dist/framework-mcp/src/tools/observability/check_ports.d.ts +2 -2
- package/dist/framework-mcp/src/tools/observability/check_ports.js.map +1 -1
- package/dist/framework-mcp/src/tools/quality/check_lint.d.ts +5 -0
- package/dist/framework-mcp/src/tools/quality/check_lint.js +29 -0
- package/dist/framework-mcp/src/tools/quality/check_lint.js.map +1 -0
- package/dist/framework-mcp/src/tools/search/get_gaps.d.ts +2 -2
- package/dist/framework-mcp/src/tools/search/get_gaps.js.map +1 -1
- package/dist/framework-mcp/src/tools/search/get_map.d.ts +2 -2
- package/dist/framework-mcp/src/tools/search/get_map.js +1 -1
- package/dist/framework-mcp/src/tools/search/get_map.js.map +1 -1
- package/dist/framework-mcp/src/tools/search/grep_search.d.ts +2 -2
- package/dist/framework-mcp/src/tools/search/grep_search.js +45 -28
- package/dist/framework-mcp/src/tools/search/grep_search.js.map +1 -1
- package/dist/framework-mcp/src/tools/search/list_dir.d.ts +2 -2
- package/dist/framework-mcp/src/tools/search/list_dir.js.map +1 -1
- package/dist/framework-mcp/src/tools/shell/run_command.d.ts +2 -0
- package/dist/framework-mcp/src/tools/shell/run_command.js +47 -0
- package/dist/framework-mcp/src/tools/shell/run_command.js.map +1 -0
- package/dist/framework-mcp/src/tools/types.d.ts +95 -28
- package/dist/framework-mcp/src/utils/metrics.d.ts +20 -0
- package/dist/framework-mcp/src/utils/metrics.js +24 -6
- package/dist/framework-mcp/src/utils/metrics.js.map +1 -1
- package/dist/framework-mcp/src/utils/security.d.ts +1 -3
- package/dist/framework-mcp/src/utils/security.js +21 -18
- package/dist/framework-mcp/src/utils/security.js.map +1 -1
- package/dist/framework-mcp/tests/tools/file_system/file_system_tools.test.js +19 -14
- package/dist/framework-mcp/tests/tools/file_system/file_system_tools.test.js.map +1 -1
- package/dist/framework-mcp/tests/tools/messaging/send_message.test.js +1 -1
- package/dist/framework-mcp/tests/tools/messaging/send_message.test.js.map +1 -1
- package/dist/framework-mcp/tests/tools/quality/check_lint.test.d.ts +1 -0
- package/dist/framework-mcp/tests/tools/quality/check_lint.test.js +36 -0
- package/dist/framework-mcp/tests/tools/quality/check_lint.test.js.map +1 -0
- package/dist/framework-mcp/tests/tools/shell/run_command.test.d.ts +1 -0
- package/dist/framework-mcp/tests/tools/shell/run_command.test.js +43 -0
- package/dist/framework-mcp/tests/tools/shell/run_command.test.js.map +1 -0
- package/dist/src/cli/adapters/core.d.ts +1 -1
- package/dist/src/cli/adapters/core.js +4 -0
- package/dist/src/cli/adapters/core.js.map +1 -1
- package/dist/src/cli/adapters/index.d.ts +1 -0
- package/dist/src/cli/adapters/index.js +1 -0
- package/dist/src/cli/adapters/index.js.map +1 -1
- package/dist/src/cli/adapters/paths.d.ts +15 -0
- package/dist/src/cli/adapters/paths.js +101 -0
- package/dist/src/cli/adapters/paths.js.map +1 -0
- package/dist/src/cli/adapters/scaffold.d.ts +1 -1
- package/dist/src/cli/adapters/scaffold.js +10 -7
- package/dist/src/cli/adapters/scaffold.js.map +1 -1
- package/dist/src/cli/commands/check.js +15 -36
- package/dist/src/cli/commands/check.js.map +1 -1
- package/dist/src/cli/commands/dashboard/data-service.d.ts +8 -0
- package/dist/src/cli/commands/dashboard/data-service.js +37 -0
- package/dist/src/cli/commands/dashboard/data-service.js.map +1 -1
- package/dist/src/cli/commands/init/scaffold-core.d.ts +5 -2
- package/dist/src/cli/commands/init/scaffold-core.js +28 -6
- package/dist/src/cli/commands/init/scaffold-core.js.map +1 -1
- package/dist/src/cli/commands/init/scaffold-standards.js +6 -1
- package/dist/src/cli/commands/init/scaffold-standards.js.map +1 -1
- package/dist/src/cli/commands/init.js +30 -6
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/orchestrate.d.ts +11 -6
- package/dist/src/cli/commands/orchestrate.js +148 -128
- package/dist/src/cli/commands/orchestrate.js.map +1 -1
- package/dist/src/cli/commands/plan.d.ts +3 -1
- package/dist/src/cli/commands/plan.js +79 -22
- package/dist/src/cli/commands/plan.js.map +1 -1
- package/dist/src/cli/index.js +11 -15
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/cli/utils/compliance.js +0 -1
- package/dist/src/cli/utils/compliance.js.map +1 -1
- package/dist/src/cli/utils/config-schema.d.ts +7 -7
- package/dist/src/cli/utils/fs.js +1 -1
- package/dist/src/cli/utils/fs.js.map +1 -1
- package/dist/src/cli/utils/memory.d.ts +1 -1
- package/dist/src/cli/utils/memory.js +28 -8
- package/dist/src/cli/utils/memory.js.map +1 -1
- package/dist/src/cli/utils/pkg.d.ts +19 -0
- package/dist/src/cli/utils/pkg.js +29 -5
- package/dist/src/cli/utils/pkg.js.map +1 -1
- package/dist/src/modules/adapters/definitions.js +3 -3
- package/dist/src/modules/adapters/definitions.js.map +1 -1
- package/dist/src/modules/agents/definitions.js +2 -1
- package/dist/src/modules/agents/definitions.js.map +1 -1
- package/dist/src/modules/agents/registry/analyst.js +1 -1
- package/dist/src/modules/agents/registry/analyst.js.map +1 -1
- package/dist/src/modules/agents/registry/architect.js +1 -0
- package/dist/src/modules/agents/registry/architect.js.map +1 -1
- package/dist/src/modules/agents/registry/backend.js +7 -6
- package/dist/src/modules/agents/registry/backend.js.map +1 -1
- package/dist/src/modules/agents/registry/database.js +4 -3
- package/dist/src/modules/agents/registry/database.js.map +1 -1
- package/dist/src/modules/agents/registry/devops.js +1 -1
- package/dist/src/modules/agents/registry/devops.js.map +1 -1
- package/dist/src/modules/agents/registry/git.js +1 -1
- package/dist/src/modules/agents/registry/git.js.map +1 -1
- package/dist/src/modules/agents/registry/manager.js +3 -2
- package/dist/src/modules/agents/registry/manager.js.map +1 -1
- package/dist/src/modules/agents/registry/native.js +1 -1
- package/dist/src/modules/agents/registry/native.js.map +1 -1
- package/dist/src/modules/agents/registry/quality.js +1 -0
- package/dist/src/modules/agents/registry/quality.js.map +1 -1
- package/dist/src/modules/agents/registry/security.js +1 -0
- package/dist/src/modules/agents/registry/security.js.map +1 -1
- package/dist/src/shared/constants.d.ts +113 -0
- package/dist/src/shared/constants.js +178 -0
- package/dist/src/shared/constants.js.map +1 -0
- package/dist/tests/adapters/paths.test.d.ts +1 -0
- package/dist/tests/adapters/paths.test.js +63 -0
- package/dist/tests/adapters/paths.test.js.map +1 -0
- package/dist/tests/approve.test.js +5 -9
- package/dist/tests/approve.test.js.map +1 -1
- package/dist/tests/cli/init/unified_init.test.d.ts +1 -0
- package/dist/tests/cli/init/unified_init.test.js +47 -0
- package/dist/tests/cli/init/unified_init.test.js.map +1 -0
- package/dist/tests/fs-utils.test.js +1 -1
- package/dist/tests/fs-utils.test.js.map +1 -1
- package/dist/tests/memory-utils.test.js +1 -1
- package/dist/tests/memory-utils.test.js.map +1 -1
- package/dist/tests/shared/constants.test.d.ts +1 -0
- package/dist/tests/shared/constants.test.js +17 -0
- package/dist/tests/shared/constants.test.js.map +1 -0
- package/dist/tests/trace.test.js +2 -2
- package/dist/tests/trace.test.js.map +1 -1
- package/framework-mcp/dist/constants.js +64 -0
- package/framework-mcp/dist/index.js +109 -0
- package/framework-mcp/dist/tools/control_plane/locking.js +64 -0
- package/framework-mcp/dist/tools/control_plane/registry.js +34 -0
- package/framework-mcp/dist/tools/dashboard/start_dashboard.js +29 -0
- package/framework-mcp/dist/tools/definitions.js +300 -0
- package/framework-mcp/dist/tools/file_system/batch_surgical_edit.js +59 -0
- package/framework-mcp/dist/tools/file_system/patch_file.js +25 -0
- package/framework-mcp/dist/tools/file_system/read_file.js +51 -0
- package/framework-mcp/dist/tools/file_system/replace_text.js +43 -0
- package/framework-mcp/dist/tools/file_system/write_file.js +38 -0
- package/framework-mcp/dist/tools/framework/audit_deps.js +41 -0
- package/framework-mcp/dist/tools/framework/get_status.js +5 -0
- package/framework-mcp/dist/tools/framework/orchestrate.js +5 -0
- package/framework-mcp/dist/tools/framework/run_tests.js +25 -0
- package/framework-mcp/dist/tools/framework/update_contract_hash.js +5 -0
- package/framework-mcp/dist/tools/framework/update_memory.js +8 -0
- package/framework-mcp/dist/tools/index.js +62 -0
- package/framework-mcp/dist/tools/memory/get_insights.js +34 -0
- package/framework-mcp/dist/tools/memory/read_memory.js +28 -0
- package/framework-mcp/dist/tools/messaging/log_action.js +22 -0
- package/framework-mcp/dist/tools/messaging/send_message.js +87 -0
- package/framework-mcp/dist/tools/observability/check_ports.js +26 -0
- package/framework-mcp/dist/tools/observability/get_health.js +19 -0
- package/framework-mcp/dist/tools/quality/check_lint.js +28 -0
- package/framework-mcp/dist/tools/search/get_gaps.js +48 -0
- package/framework-mcp/dist/tools/search/get_map.js +43 -0
- package/framework-mcp/dist/tools/search/grep_search.js +76 -0
- package/framework-mcp/dist/tools/search/list_dir.js +28 -0
- package/framework-mcp/dist/tools/shell/run_command.js +46 -0
- package/framework-mcp/dist/tools/types.js +1 -0
- package/framework-mcp/dist/utils/cli.js +20 -0
- package/framework-mcp/dist/utils/compliance.js +29 -0
- package/framework-mcp/dist/utils/fs.js +44 -0
- package/framework-mcp/dist/utils/metrics.js +56 -0
- package/framework-mcp/dist/utils/security.js +60 -0
- package/framework-mcp/package.json +19 -0
- package/framework-mcp/src/constants.ts +78 -0
- package/framework-mcp/src/declarations.d.ts +17 -0
- package/framework-mcp/src/index.ts +132 -0
- package/framework-mcp/src/tools/control_plane/locking.ts +71 -0
- package/framework-mcp/src/tools/control_plane/registry.ts +38 -0
- package/framework-mcp/src/tools/dashboard/start_dashboard.ts +33 -0
- package/framework-mcp/src/tools/definitions.ts +302 -0
- package/framework-mcp/src/tools/file_system/batch_surgical_edit.ts +79 -0
- package/framework-mcp/src/tools/file_system/patch_file.ts +33 -0
- package/framework-mcp/src/tools/file_system/read_file.ts +58 -0
- package/framework-mcp/src/tools/file_system/replace_text.ts +52 -0
- package/framework-mcp/src/tools/file_system/write_file.ts +45 -0
- package/framework-mcp/src/tools/framework/audit_deps.ts +49 -0
- package/framework-mcp/src/tools/framework/get_status.ts +7 -0
- package/framework-mcp/src/tools/framework/orchestrate.ts +7 -0
- package/framework-mcp/src/tools/framework/run_tests.ts +28 -0
- package/framework-mcp/src/tools/framework/update_contract_hash.ts +7 -0
- package/framework-mcp/src/tools/framework/update_memory.ts +10 -0
- package/framework-mcp/src/tools/index.ts +66 -0
- package/framework-mcp/src/tools/memory/get_insights.ts +41 -0
- package/framework-mcp/src/tools/memory/read_memory.ts +31 -0
- package/framework-mcp/src/tools/messaging/log_action.ts +28 -0
- package/framework-mcp/src/tools/messaging/send_message.ts +89 -0
- package/framework-mcp/src/tools/observability/check_ports.ts +30 -0
- package/framework-mcp/src/tools/observability/get_health.ts +24 -0
- package/framework-mcp/src/tools/quality/check_lint.ts +33 -0
- package/framework-mcp/src/tools/search/get_gaps.ts +54 -0
- package/framework-mcp/src/tools/search/get_map.ts +48 -0
- package/framework-mcp/src/tools/search/grep_search.ts +76 -0
- package/framework-mcp/src/tools/search/list_dir.ts +34 -0
- package/framework-mcp/src/tools/shell/run_command.ts +56 -0
- package/framework-mcp/src/tools/types.ts +89 -0
- package/framework-mcp/src/utils/cli.ts +20 -0
- package/framework-mcp/src/utils/compliance.ts +37 -0
- package/framework-mcp/src/utils/fs.ts +45 -0
- package/framework-mcp/src/utils/metrics.ts +73 -0
- package/framework-mcp/src/utils/security.ts +66 -0
- package/framework-mcp/tests/tools/file_system/file_system_tools.test.ts +212 -0
- package/framework-mcp/tests/tools/messaging/send_message.test.ts +136 -0
- package/framework-mcp/tests/tools/quality/check_lint.test.ts +46 -0
- package/framework-mcp/tests/tools/shell/run_command.test.ts +55 -0
- package/framework-mcp/tsconfig.json +14 -0
- package/package.json +9 -7
- package/src/cli/adapters/core.ts +7 -1
- package/src/cli/adapters/index.ts +1 -0
- package/src/cli/adapters/paths.ts +134 -0
- package/src/cli/adapters/scaffold.ts +17 -7
- package/src/cli/commands/check.ts +16 -38
- package/src/cli/commands/dashboard/data-service.ts +48 -0
- package/src/cli/commands/init/scaffold-core.ts +45 -6
- package/src/cli/commands/init/scaffold-standards.ts +6 -1
- package/src/cli/commands/init.ts +32 -6
- package/src/cli/commands/orchestrate.ts +151 -127
- package/src/cli/commands/plan.ts +89 -23
- package/src/cli/index.ts +14 -19
- package/src/cli/utils/compliance.ts +8 -9
- package/src/cli/utils/fs.ts +1 -1
- package/src/cli/utils/memory.ts +32 -7
- package/src/cli/utils/pkg.ts +42 -13
- package/src/modules/adapters/definitions.ts +4 -3
- package/src/modules/agents/definitions.ts +2 -1
- package/src/modules/agents/registry/analyst.ts +1 -1
- package/src/modules/agents/registry/architect.ts +1 -0
- package/src/modules/agents/registry/backend.ts +7 -6
- package/src/modules/agents/registry/database.ts +4 -3
- package/src/modules/agents/registry/devops.ts +1 -1
- package/src/modules/agents/registry/git.ts +1 -1
- package/src/modules/agents/registry/manager.ts +3 -2
- package/src/modules/agents/registry/native.ts +1 -1
- package/src/modules/agents/registry/quality.ts +1 -0
- package/src/modules/agents/registry/security.ts +1 -0
- package/src/shared/constants.ts +212 -0
- package/templates/prompts/bug-fix-recipe.md +20 -0
- package/templates/prompts/contract-design-recipe.md +21 -0
- package/templates/prompts/db-management-recipe.md +25 -0
- package/templates/prompts/deployment-recipe.md +23 -0
- package/templates/prompts/new-feature-recipe.md +19 -0
- package/templates/prompts/performance-optimization-recipe.md +23 -0
- package/templates/prompts/pull-request-template.md +21 -0
- package/templates/prompts/refactoring-recipe.md +21 -0
- package/templates/prompts/security-audit-recipe.md +20 -0
- package/templates/standards/architecture-standards.md +23 -0
- package/templates/standards/auth-standards.md +125 -0
- package/templates/standards/crud-governance.md +21 -0
- package/templates/standards/deployment-standards.md +21 -0
- package/templates/standards/frontend-standards.md +37 -0
- package/templates/standards/github-actions-standards.md +43 -0
- package/templates/standards/i18n-standards.md +17 -0
- package/templates/standards/kysely-standards.md +47 -0
- package/templates/standards/llm-governance.md +15 -0
- package/templates/standards/logging-and-secrets.md +34 -0
- package/templates/standards/mobile-standards.md +23 -0
- package/templates/standards/observability-standards.md +15 -0
- package/templates/standards/performance-standards.md +15 -0
- package/templates/standards/pino-standards.md +46 -0
- package/templates/standards/playwright-standards.md +54 -0
- package/templates/standards/quality-standards.md +31 -0
- package/templates/standards/react-query-standards.md +72 -0
- package/templates/standards/react-router-standards.md +62 -0
- package/templates/standards/security-audit-standards.md +16 -0
- package/templates/standards/security-standards.md +21 -0
- package/templates/standards/swagger-standards.md +50 -0
- package/templates/standards/tailwind-standards.md +20 -0
- package/templates/standards/testing-standards.md +31 -0
- package/templates/standards/typeorm-standards.md +49 -0
- package/templates/standards/vitest-standards.md +110 -0
- package/bin/validate-agent-army.js +0 -148
- package/src/cli/commands/app.ts +0 -56
- package/src/cli/utils/app-backend.ts +0 -257
- package/src/cli/utils/app-docs.ts +0 -83
- package/src/cli/utils/app-frontend.ts +0 -263
- package/src/cli/utils/app-inferrer.ts +0 -63
- package/src/cli/utils/app-mobile.ts +0 -113
- package/src/cli/utils/app-types.ts +0 -248
- package/src/cli/utils/app.ts +0 -6
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# TypeORM Standards
|
|
2
|
+
|
|
3
|
+
> Full-featured ORM with decorator-based entity definitions.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { DataSource } from "typeorm";
|
|
9
|
+
|
|
10
|
+
export const AppDataSource = new DataSource({
|
|
11
|
+
type: "sqlite",
|
|
12
|
+
database: process.env.DATABASE_PATH || "./dev.db",
|
|
13
|
+
synchronize: process.env.NODE_ENV === "development",
|
|
14
|
+
logging: process.env.NODE_ENV === "development",
|
|
15
|
+
entities: ["src/database/typeorm/entities/*.ts"],
|
|
16
|
+
migrations: ["src/database/typeorm/migrations/*.ts"],
|
|
17
|
+
});
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Entity Pattern
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { Entity, PrimaryColumn, Column, CreateDateColumn, UpdateDateColumn, DeleteDateColumn } from "typeorm";
|
|
24
|
+
|
|
25
|
+
@Entity("users")
|
|
26
|
+
export class UserEntity {
|
|
27
|
+
@PrimaryColumn()
|
|
28
|
+
id!: string;
|
|
29
|
+
@Column({ unique: true })
|
|
30
|
+
email!: string;
|
|
31
|
+
@Column()
|
|
32
|
+
fullName!: string;
|
|
33
|
+
@Column({ default: "VIEWER" })
|
|
34
|
+
role!: string;
|
|
35
|
+
@CreateDateColumn()
|
|
36
|
+
createdAt!: Date;
|
|
37
|
+
@UpdateDateColumn()
|
|
38
|
+
updatedAt!: Date;
|
|
39
|
+
@DeleteDateColumn()
|
|
40
|
+
deletedAt?: Date;
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Best Practices
|
|
45
|
+
1. Use `@DeleteDateColumn()` for soft deletes
|
|
46
|
+
2. Set `synchronize: false` in production
|
|
47
|
+
3. Use `@ManyToOne` / `@OneToMany` for relations
|
|
48
|
+
4. Import `reflect-metadata` at entry point
|
|
49
|
+
5. Generate migrations, don't rely on synchronize
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Testing Standards
|
|
2
|
+
|
|
3
|
+
> Unit and integration testing with Vitest for Node.js applications.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Vitest is a blazing-fast unit test framework compatible with Jest API. It is used for both unit tests and API integration tests.
|
|
8
|
+
|
|
9
|
+
## Setup
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install -D vitest
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Configuration
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
// vitest.config.ts
|
|
19
|
+
import { defineConfig } from "vitest/config";
|
|
20
|
+
|
|
21
|
+
export default defineConfig({
|
|
22
|
+
test: {
|
|
23
|
+
globals: true,
|
|
24
|
+
environment: "node",
|
|
25
|
+
include: ["src/tests/**/*.test.ts"],
|
|
26
|
+
coverage: {
|
|
27
|
+
provider: "v8",
|
|
28
|
+
reporter: ["text", "json", "html"],
|
|
29
|
+
thresholds: {
|
|
30
|
+
lines: 80,
|
|
31
|
+
functions: 80,
|
|
32
|
+
branches: 80,
|
|
33
|
+
statements: 80,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Test Structure
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
src/tests/
|
|
44
|
+
├── auth.test.ts # Authentication tests
|
|
45
|
+
├── customers.test.ts # Customer CRUD tests
|
|
46
|
+
├── helpers/
|
|
47
|
+
│ ├── setup.ts # Test setup & teardown
|
|
48
|
+
│ └── factories.ts # Test data factories
|
|
49
|
+
└── integration/
|
|
50
|
+
└── api.test.ts # Full API integration tests
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Unit Test Example
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { describe, it, expect } from "vitest";
|
|
57
|
+
import { createCustomerSchema } from "../validators/schemas.js";
|
|
58
|
+
|
|
59
|
+
describe("Customer Validation", () => {
|
|
60
|
+
it("should validate create customer schema", () => {
|
|
61
|
+
const result = createCustomerSchema.parse({
|
|
62
|
+
name: "Test Corp",
|
|
63
|
+
status: "LEAD",
|
|
64
|
+
annualValue: 50000,
|
|
65
|
+
});
|
|
66
|
+
expect(result.name).toBe("Test Corp");
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("should reject invalid data", () => {
|
|
70
|
+
expect(() => createCustomerSchema.parse({ name: "" })).toThrow();
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## API Integration Test Example
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import { describe, it, expect, beforeAll, afterAll } from "vitest";
|
|
79
|
+
import Fastify from "fastify";
|
|
80
|
+
|
|
81
|
+
describe("Auth API", () => {
|
|
82
|
+
const app = Fastify();
|
|
83
|
+
|
|
84
|
+
beforeAll(async () => {
|
|
85
|
+
await app.register(publicRoutes, { prefix: "/api/v1" });
|
|
86
|
+
await app.ready();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
afterAll(async () => await app.close());
|
|
90
|
+
|
|
91
|
+
it("should reject invalid login", async () => {
|
|
92
|
+
const response = await app.inject({
|
|
93
|
+
method: "POST",
|
|
94
|
+
url: "/api/v1/auth/login",
|
|
95
|
+
payload: { email: "invalid", password: "test" },
|
|
96
|
+
});
|
|
97
|
+
expect(response.statusCode).toBe(400);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Best Practices
|
|
103
|
+
|
|
104
|
+
1. Use `describe`/`it` blocks for organized test suites
|
|
105
|
+
2. Test both success and failure scenarios
|
|
106
|
+
3. Use `app.inject()` for API tests (no server needed)
|
|
107
|
+
4. Keep tests isolated — clean state between tests
|
|
108
|
+
5. Aim for >80% coverage on business logic
|
|
109
|
+
6. Use factories for test data generation
|
|
110
|
+
7. Follow Given-When-Then pattern in all test suites
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import fs from "fs";
|
|
4
|
-
import path from "path";
|
|
5
|
-
import yaml from "js-yaml";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* AL-compatible agent folder names across all adapters (after init).
|
|
9
|
-
*/
|
|
10
|
-
const AGENT_FOLDER_NAMES = ["agents", "skills", "plugins"];
|
|
11
|
-
const FRAMEWORK_CANDIDATES = [
|
|
12
|
-
".enderun",
|
|
13
|
-
".cursor",
|
|
14
|
-
".claude",
|
|
15
|
-
".github",
|
|
16
|
-
".grok",
|
|
17
|
-
".windsurf",
|
|
18
|
-
".antigravity",
|
|
19
|
-
".agent",
|
|
20
|
-
".gemini/antigravity-cli",
|
|
21
|
-
".gemini",
|
|
22
|
-
".agents",
|
|
23
|
-
"antigravity-cli"
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
function detectFrameworkDir() {
|
|
27
|
-
const projectRoot = process.cwd();
|
|
28
|
-
for (const dir of FRAMEWORK_CANDIDATES) {
|
|
29
|
-
const dirPath = path.resolve(projectRoot, dir);
|
|
30
|
-
if (!fs.existsSync(dirPath)) continue;
|
|
31
|
-
|
|
32
|
-
for (const folderName of AGENT_FOLDER_NAMES) {
|
|
33
|
-
const agentsPath = path.join(dirPath, folderName);
|
|
34
|
-
if (fs.existsSync(agentsPath)) {
|
|
35
|
-
return { frameworkDir: dir, agentsDir: agentsPath };
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Helper to parse YAML-like Frontmatter from Markdown.
|
|
44
|
-
*/
|
|
45
|
-
function parseFrontmatter(content) {
|
|
46
|
-
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
47
|
-
if (match) {
|
|
48
|
-
try {
|
|
49
|
-
const fm = yaml.load(match[1]);
|
|
50
|
-
return fm || {};
|
|
51
|
-
} catch (e) {
|
|
52
|
-
// Fallback to simpler parsing or handle error
|
|
53
|
-
console.error("Error parsing YAML frontmatter:", e);
|
|
54
|
-
return {};
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
// Also parse from HTML comments in the body as fallback to bypass strict frontmatter checks
|
|
58
|
-
const commentMatches = content.matchAll(/<!--\s*(\w+)\s*:\s*(.*?)\s*-->/g);
|
|
59
|
-
const fmFromComments = {};
|
|
60
|
-
for (const m of commentMatches) {
|
|
61
|
-
let value = m[2].trim();
|
|
62
|
-
if (value.startsWith("[") && value.endsWith("]")) {
|
|
63
|
-
value = value.slice(1, -1).split(",").map(s => s.trim().replace(/"/g, "").replace(/'/g, ""));
|
|
64
|
-
} else if (value.startsWith("\"") && value.endsWith("\"")) {
|
|
65
|
-
value = value.slice(1, -1);
|
|
66
|
-
}
|
|
67
|
-
fmFromComments[m[1]] = value;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return Object.keys(fmFromComments).length > 0 ? fmFromComments : null;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const detected = detectFrameworkDir();
|
|
75
|
-
if (!detected) {
|
|
76
|
-
process.stderr.write("ℹ️ No framework agents/ dir found for AL validation. Skipping.");
|
|
77
|
-
process.exit(0);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const { agentsDir } = detected;
|
|
81
|
-
|
|
82
|
-
try {
|
|
83
|
-
const files = [];
|
|
84
|
-
const walk = (dir) => {
|
|
85
|
-
if (!fs.existsSync(dir)) return;
|
|
86
|
-
const list = fs.readdirSync(dir);
|
|
87
|
-
for (const item of list) {
|
|
88
|
-
const fullPath = path.join(dir, item);
|
|
89
|
-
if (fs.statSync(fullPath).isDirectory()) {
|
|
90
|
-
walk(fullPath);
|
|
91
|
-
} else if (item.endsWith(".json") || item.endsWith(".md")) {
|
|
92
|
-
files.push({ name: item, path: fullPath });
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
walk(agentsDir);
|
|
97
|
-
|
|
98
|
-
let totalFailed = 0;
|
|
99
|
-
|
|
100
|
-
process.stderr.write(`🛡️ STARTING AGENT ARMY AL VALIDATION (${detected.frameworkDir})...`);
|
|
101
|
-
process.stderr.write("--------------------------------------------------");
|
|
102
|
-
process.stderr.write("| Agent ID | Format | Status | Category |");
|
|
103
|
-
process.stderr.write("--------------------------------------------------");
|
|
104
|
-
|
|
105
|
-
for (const file of files) {
|
|
106
|
-
const fileName = file.name;
|
|
107
|
-
const filePath = file.path;
|
|
108
|
-
if (fileName === "agent_army_schema.json" || fileName === "schema") continue;
|
|
109
|
-
|
|
110
|
-
const content = fs.readFileSync(filePath, "utf8");
|
|
111
|
-
const isMd = fileName.endsWith(".md");
|
|
112
|
-
|
|
113
|
-
let agent;
|
|
114
|
-
try {
|
|
115
|
-
agent = isMd ? parseFrontmatter(content) : JSON.parse(content);
|
|
116
|
-
if (!agent && isMd) throw new Error("Missing Frontmatter");
|
|
117
|
-
} catch (e) {
|
|
118
|
-
process.stderr.write(`| ${fileName.padEnd(9)} | ${isMd ? "MD " : "JSON"} | ❌ INVALID | ${String(e.message).slice(0, 14)} |`);
|
|
119
|
-
totalFailed++;
|
|
120
|
-
continue;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Validate AL compliance fields
|
|
124
|
-
const missing = [];
|
|
125
|
-
if (!agent.name) missing.push("name");
|
|
126
|
-
if (agent.capability === undefined) missing.push("capability");
|
|
127
|
-
if (!agent.tags) missing.push("tags");
|
|
128
|
-
|
|
129
|
-
if (missing.length > 0) {
|
|
130
|
-
process.stderr.write(`| ${fileName.padEnd(9)} | ${isMd ? "MD " : "JSON"} | ❌ FAILED | ${missing.join(",").slice(0, 14)} |`);
|
|
131
|
-
totalFailed++;
|
|
132
|
-
} else {
|
|
133
|
-
const cat = Array.isArray(agent.tags) ? agent.tags[0] : "core";
|
|
134
|
-
process.stderr.write(`| ${agent.name.padEnd(9)} | ${isMd ? "MD " : "JSON"} | ✅ PASSED | ${cat.padEnd(14)} |`);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
process.stderr.write("--------------------------------------------------");
|
|
139
|
-
if (totalFailed > 0) {
|
|
140
|
-
process.stderr.write(`❌ Validation failed! Detected ${totalFailed} invalid agent configurations.\n`);
|
|
141
|
-
process.exit(1);
|
|
142
|
-
} else {
|
|
143
|
-
process.stderr.write("🎉 SUCCESS: All core agents are AL-Compliant!");
|
|
144
|
-
}
|
|
145
|
-
} catch (e) {
|
|
146
|
-
process.stderr.write(`❌ Critical error during validation: ${e}\n`);
|
|
147
|
-
process.exit(1);
|
|
148
|
-
}
|
package/src/cli/commands/app.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
|
|
3
|
-
import { updateMemoryForGeneratedApp, collectCreateAppDescription, inferAppSpec, createBackendFiles, createWebFiles, createMobileFiles, updateProjectDocs } from "../utils/app.js";
|
|
4
|
-
import { traceNewCommand } from "./trace.js";
|
|
5
|
-
import { getMemoryPath } from "../utils/memory.js";
|
|
6
|
-
|
|
7
|
-
import { ValidationError } from "../../shared/errors.js";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Generate a new application based on natural language input.
|
|
11
|
-
*/
|
|
12
|
-
export async function createAppCommand(args: string[]) {
|
|
13
|
-
if (!fs.existsSync("apps")) {
|
|
14
|
-
throw new ValidationError(
|
|
15
|
-
"The 'apps/' directory is missing.",
|
|
16
|
-
null,
|
|
17
|
-
"Ensure you are in the project root and the 'apps/' folder exists. Run 'mkdir apps' if needed."
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
|
-
const description = await collectCreateAppDescription(args);
|
|
21
|
-
const spec = inferAppSpec(description);
|
|
22
|
-
|
|
23
|
-
console.warn(`🚀 Generating Enterprise App: ${spec.title} (Platform: ${spec.platform})...`);
|
|
24
|
-
|
|
25
|
-
if (spec.platform === "full-stack") {
|
|
26
|
-
createBackendFiles(spec);
|
|
27
|
-
createWebFiles(spec);
|
|
28
|
-
} else if (spec.platform === "web") {
|
|
29
|
-
createWebFiles(spec);
|
|
30
|
-
} else if (spec.platform === "mobile") {
|
|
31
|
-
createMobileFiles(spec);
|
|
32
|
-
} else if (spec.platform === "backend") {
|
|
33
|
-
createBackendFiles(spec);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
updateProjectDocs(spec);
|
|
37
|
-
|
|
38
|
-
const memoryPath = getMemoryPath();
|
|
39
|
-
let traceId = "01HGT8J5E2N0W0W0W0W0W0W0W0"; // default fallback
|
|
40
|
-
|
|
41
|
-
if (fs.existsSync(memoryPath)) {
|
|
42
|
-
const memory = fs.readFileSync(memoryPath, "utf8");
|
|
43
|
-
const match = memory.match(/- Trace ID: (.*)/);
|
|
44
|
-
if (match) traceId = match[1].trim();
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const activeTraceId = (await traceNewCommand(`Generate ${spec.title} from natural language request`, "manager", "P1")) || traceId;
|
|
48
|
-
updateMemoryForGeneratedApp(spec, activeTraceId);
|
|
49
|
-
|
|
50
|
-
console.warn("\n✨ Application scaffolded successfully!");
|
|
51
|
-
console.warn("📜 Updated project docs and app-local types contract");
|
|
52
|
-
console.warn("\nNext commands:");
|
|
53
|
-
console.warn(" npm install");
|
|
54
|
-
console.warn(" npm run enderun:build");
|
|
55
|
-
console.warn(" agent-enderun frontend:dev\n");
|
|
56
|
-
}
|
|
@@ -1,257 +0,0 @@
|
|
|
1
|
-
import path from "path";
|
|
2
|
-
import type { AppSpec } from "./app-inferrer.js";
|
|
3
|
-
import { createBaseTypeFiles } from "./app-types.js";
|
|
4
|
-
import { ensureDir, writeJsonFile, writeTextFile } from "./fs.js";
|
|
5
|
-
import { getConfiguredPaths } from "./memory.js";
|
|
6
|
-
import { getDependencyVersions } from "./pkg.js";
|
|
7
|
-
|
|
8
|
-
const targetDir = process.cwd();
|
|
9
|
-
|
|
10
|
-
export function createBackendFiles(spec: AppSpec): void {
|
|
11
|
-
const pathsMap = getConfiguredPaths();
|
|
12
|
-
const backendDir = pathsMap.backend;
|
|
13
|
-
const { fastify, "@fastify/cors": fastifyCors, zod, "@types/node": typesNode, tsx, typescript, "vitest-backend": vitest } = getDependencyVersions();
|
|
14
|
-
|
|
15
|
-
createBaseTypeFiles(path.join(targetDir, backendDir, "src"));
|
|
16
|
-
writeJsonFile(path.join(targetDir, backendDir, "contract.version.json"), {
|
|
17
|
-
"contract_hash": "initial_hash_placeholder",
|
|
18
|
-
"last_updated": new Date().toISOString()
|
|
19
|
-
});
|
|
20
|
-
writeJsonFile(path.join(targetDir, backendDir, "package.json"), {
|
|
21
|
-
name: "@agent-enderun/backend",
|
|
22
|
-
version: "0.1.0",
|
|
23
|
-
private: true,
|
|
24
|
-
type: "module",
|
|
25
|
-
scripts: {
|
|
26
|
-
dev: "tsx src/server.ts",
|
|
27
|
-
build: "tsc -p tsconfig.json",
|
|
28
|
-
start: "node dist/server.js",
|
|
29
|
-
test: "vitest run",
|
|
30
|
-
},
|
|
31
|
-
dependencies: {
|
|
32
|
-
"@fastify/cors": fastifyCors,
|
|
33
|
-
fastify: fastify,
|
|
34
|
-
zod: zod,
|
|
35
|
-
},
|
|
36
|
-
devDependencies: {
|
|
37
|
-
"@types/node": typesNode,
|
|
38
|
-
tsx: tsx,
|
|
39
|
-
typescript: typescript,
|
|
40
|
-
vitest: vitest,
|
|
41
|
-
},
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
writeJsonFile(path.join(targetDir, backendDir, "tsconfig.json"), {
|
|
45
|
-
extends: "../../tsconfig.json",
|
|
46
|
-
compilerOptions: {
|
|
47
|
-
outDir: "dist",
|
|
48
|
-
rootDir: "src",
|
|
49
|
-
module: "NodeNext",
|
|
50
|
-
moduleResolution: "NodeNext",
|
|
51
|
-
target: "ES2022",
|
|
52
|
-
strict: true,
|
|
53
|
-
skipLibCheck: true,
|
|
54
|
-
},
|
|
55
|
-
include: ["src/**/*.ts"],
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
const srcDir = path.join(targetDir, backendDir, "src");
|
|
59
|
-
ensureDir(path.join(srcDir, "database"));
|
|
60
|
-
ensureDir(path.join(srcDir, "repositories"));
|
|
61
|
-
ensureDir(path.join(srcDir, "services"));
|
|
62
|
-
|
|
63
|
-
writeTextFile(path.join(srcDir, "database/memoryDb.ts"), [
|
|
64
|
-
"import type { Customer, ReportMetric, Role, User } from \"../types/index.js\";",
|
|
65
|
-
"",
|
|
66
|
-
"const now = new Date().toISOString();",
|
|
67
|
-
"",
|
|
68
|
-
"export const rolesDb: Role[] = [",
|
|
69
|
-
" { id: \"role_admin\" as Role[\"id\"], name: \"Admin\", permissions: [\"users:manage\", \"reports:view\", \"customers:manage\"] },",
|
|
70
|
-
" { id: \"role_manager\" as Role[\"id\"], name: \"Manager\", permissions: [\"reports:view\", \"customers:manage\"] },",
|
|
71
|
-
" { id: \"role_viewer\" as Role[\"id\"], name: \"Viewer\", permissions: [\"reports:view\"] },",
|
|
72
|
-
"];",
|
|
73
|
-
"",
|
|
74
|
-
"export const usersDb: User[] = [",
|
|
75
|
-
" { id: \"user_1\" as User[\"id\"], email: \"admin@example.com\", fullName: \"Admin User\", role: \"ADMIN\", createdAt: now, updatedAt: now },",
|
|
76
|
-
" { id: \"user_2\" as User[\"id\"], email: \"manager@example.com\", fullName: \"Sales Manager\", role: \"DEVELOPER\", createdAt: now, updatedAt: now },",
|
|
77
|
-
"];",
|
|
78
|
-
"",
|
|
79
|
-
"export const customersDb: Customer[] = [",
|
|
80
|
-
" { id: \"customer_1\" as Customer[\"id\"], name: \"Northwind\", ownerId: usersDb[1].id, status: \"ACTIVE\", annualValue: 125000, createdAt: now, updatedAt: now },",
|
|
81
|
-
" { id: \"customer_2\" as Customer[\"id\"], name: \"Acme Corp\", ownerId: usersDb[1].id, status: \"LEAD\", annualValue: 82000, createdAt: now, updatedAt: now },",
|
|
82
|
-
" { id: \"customer_3\" as Customer[\"id\"], name: \"Globex\", ownerId: usersDb[0].id, status: \"AT_RISK\", annualValue: 54000, createdAt: now, updatedAt: now },",
|
|
83
|
-
"];",
|
|
84
|
-
"",
|
|
85
|
-
"export const reportsDb: ReportMetric[] = [",
|
|
86
|
-
" { id: \"report_pipeline\" as ReportMetric[\"id\"], label: \"Pipeline\", value: 261000, trend: \"UP\" },",
|
|
87
|
-
" { id: \"report_active_customers\" as ReportMetric[\"id\"], label: \"Active Customers\", value: 1, trend: \"FLAT\" },",
|
|
88
|
-
" { id: \"report_risk\" as ReportMetric[\"id\"], label: \"At Risk\", value: 1, trend: \"DOWN\" },",
|
|
89
|
-
"];",
|
|
90
|
-
].join("\n"));
|
|
91
|
-
|
|
92
|
-
writeTextFile(path.join(srcDir, "repositories/user.repository.ts"), [
|
|
93
|
-
"import { usersDb } from \"../database/memoryDb.js\";",
|
|
94
|
-
"import type { User } from \"../types/index.js\";",
|
|
95
|
-
"",
|
|
96
|
-
"export class UserRepository {",
|
|
97
|
-
" async findAll(): Promise<User[]> {",
|
|
98
|
-
" return usersDb.filter(u => !u.deletedAt);",
|
|
99
|
-
" }",
|
|
100
|
-
"",
|
|
101
|
-
" async findByEmail(email: string): Promise<User | null> {",
|
|
102
|
-
" return usersDb.find(u => u.email === email && !u.deletedAt) || null;",
|
|
103
|
-
" }",
|
|
104
|
-
"}",
|
|
105
|
-
].join("\n"));
|
|
106
|
-
|
|
107
|
-
writeTextFile(path.join(srcDir, "repositories/customer.repository.ts"), [
|
|
108
|
-
"import { customersDb } from \"../database/memoryDb.js\";",
|
|
109
|
-
"import type { Customer } from \"../types/index.js\";",
|
|
110
|
-
"",
|
|
111
|
-
"export class CustomerRepository {",
|
|
112
|
-
" async findAll(): Promise<Customer[]> {",
|
|
113
|
-
" return customersDb.filter(c => !c.deletedAt);",
|
|
114
|
-
" }",
|
|
115
|
-
"}",
|
|
116
|
-
].join("\n"));
|
|
117
|
-
|
|
118
|
-
writeTextFile(path.join(srcDir, "repositories/role.repository.ts"), [
|
|
119
|
-
"import { rolesDb } from \"../database/memoryDb.js\";",
|
|
120
|
-
"import type { Role } from \"../types/index.js\";",
|
|
121
|
-
"",
|
|
122
|
-
"export class RoleRepository {",
|
|
123
|
-
" async findAll(): Promise<Role[]> {",
|
|
124
|
-
" return rolesDb;",
|
|
125
|
-
" }",
|
|
126
|
-
"}",
|
|
127
|
-
].join("\n"));
|
|
128
|
-
|
|
129
|
-
writeTextFile(path.join(srcDir, "repositories/report.repository.ts"), [
|
|
130
|
-
"import { reportsDb } from \"../database/memoryDb.js\";",
|
|
131
|
-
"import type { ReportMetric } from \"../types/index.js\";",
|
|
132
|
-
"",
|
|
133
|
-
"export class ReportRepository {",
|
|
134
|
-
" async findAll(): Promise<ReportMetric[]> {",
|
|
135
|
-
" return reportsDb;",
|
|
136
|
-
" }",
|
|
137
|
-
"}",
|
|
138
|
-
].join("\n"));
|
|
139
|
-
|
|
140
|
-
writeTextFile(path.join(srcDir, "services/dashboard.service.ts"), [
|
|
141
|
-
"import { UserRepository } from \"../repositories/user.repository.js\";",
|
|
142
|
-
"import { CustomerRepository } from \"../repositories/customer.repository.js\";",
|
|
143
|
-
"import { RoleRepository } from \"../repositories/role.repository.js\";",
|
|
144
|
-
"import { ReportRepository } from \"../repositories/report.repository.js\";",
|
|
145
|
-
"import type { DashboardSummary } from \"../types/index.js\";",
|
|
146
|
-
"",
|
|
147
|
-
"export class DashboardService {",
|
|
148
|
-
" private userRepo = new UserRepository();",
|
|
149
|
-
" private customerRepo = new CustomerRepository();",
|
|
150
|
-
" private roleRepo = new RoleRepository();",
|
|
151
|
-
" private reportRepo = new ReportRepository();",
|
|
152
|
-
"",
|
|
153
|
-
" async getSummary(): Promise<DashboardSummary> {",
|
|
154
|
-
" const [users, customers, roles, reports] = await Promise.all([",
|
|
155
|
-
" this.userRepo.findAll(),",
|
|
156
|
-
" this.customerRepo.findAll(),",
|
|
157
|
-
" this.roleRepo.findAll(),",
|
|
158
|
-
" this.reportRepo.findAll(),",
|
|
159
|
-
" ]);",
|
|
160
|
-
"",
|
|
161
|
-
" return { users, customers, roles, reports };",
|
|
162
|
-
" }",
|
|
163
|
-
"}",
|
|
164
|
-
].join("\n"));
|
|
165
|
-
|
|
166
|
-
writeTextFile(path.join(targetDir, backendDir, "src/server.ts"), [
|
|
167
|
-
"import Fastify from \"fastify\";",
|
|
168
|
-
"import cors from \"@fastify/cors\";",
|
|
169
|
-
"import { z } from \"zod\";",
|
|
170
|
-
"import { UserRepository } from \"./repositories/user.repository.js\";",
|
|
171
|
-
"import { CustomerRepository } from \"./repositories/customer.repository.js\";",
|
|
172
|
-
"import { RoleRepository } from \"./repositories/role.repository.js\";",
|
|
173
|
-
"import { ReportRepository } from \"./repositories/report.repository.js\";",
|
|
174
|
-
"import { DashboardService } from \"./services/dashboard.service.js\";",
|
|
175
|
-
"",
|
|
176
|
-
"const app = Fastify({ logger: true });",
|
|
177
|
-
"await app.register(cors, { origin: true });",
|
|
178
|
-
"",
|
|
179
|
-
"const userRepo = new UserRepository();",
|
|
180
|
-
"const customerRepo = new CustomerRepository();",
|
|
181
|
-
"const roleRepo = new RoleRepository();",
|
|
182
|
-
"const reportRepo = new ReportRepository();",
|
|
183
|
-
"const dashboardService = new DashboardService();",
|
|
184
|
-
"",
|
|
185
|
-
"app.get(\"/health\", async () => ({ ok: true, service: \"agent-enderun-backend\" }));",
|
|
186
|
-
"app.get(\"/api/v1/dashboard\", async () => {",
|
|
187
|
-
" const summary = await dashboardService.getSummary();",
|
|
188
|
-
" return { data: summary };",
|
|
189
|
-
"});",
|
|
190
|
-
"app.get(\"/api/v1/users\", async () => {",
|
|
191
|
-
" const users = await userRepo.findAll();",
|
|
192
|
-
" return { data: users };",
|
|
193
|
-
"});",
|
|
194
|
-
"app.get(\"/api/v1/roles\", async () => {",
|
|
195
|
-
" const roles = await roleRepo.findAll();",
|
|
196
|
-
" return { data: roles };",
|
|
197
|
-
"});",
|
|
198
|
-
"app.get(\"/api/v1/customers\", async () => {",
|
|
199
|
-
" const customers = await customerRepo.findAll();",
|
|
200
|
-
" return { data: customers };",
|
|
201
|
-
"});",
|
|
202
|
-
"app.get(\"/api/v1/reports\", async (request, reply) => {",
|
|
203
|
-
" interface QueryParams {",
|
|
204
|
-
" page?: number;",
|
|
205
|
-
" limit?: number;",
|
|
206
|
-
" }",
|
|
207
|
-
" const { page = 1, limit = 10 } = request.query as QueryParams;",
|
|
208
|
-
" const reports = await reportRepo.findAll();",
|
|
209
|
-
" const startIndex = (Number(page) - 1) * Number(limit);",
|
|
210
|
-
" const endIndex = startIndex + Number(limit);",
|
|
211
|
-
" const paginatedReports = reports.slice(startIndex, endIndex);",
|
|
212
|
-
" reply.send({",
|
|
213
|
-
" data: paginatedReports,",
|
|
214
|
-
" meta: {",
|
|
215
|
-
" total: reports.length,",
|
|
216
|
-
" page: Number(page),",
|
|
217
|
-
" limit: Number(limit),",
|
|
218
|
-
" },",
|
|
219
|
-
" });",
|
|
220
|
-
"});",
|
|
221
|
-
"",
|
|
222
|
-
"app.post(\"/api/v1/auth/login\", async (request, reply) => {",
|
|
223
|
-
" const body = z.object({ email: z.string().email(), password: z.string().min(1) }).safeParse(request.body);",
|
|
224
|
-
" if (!body.success) return reply.code(400).send({ error: { code: \"VALIDATION_ERROR\", message: \"Invalid login payload\" } });",
|
|
225
|
-
"",
|
|
226
|
-
" const user = await userRepo.findByEmail(body.data.email);",
|
|
227
|
-
" if (!user) {",
|
|
228
|
-
" const allUsers = await userRepo.findAll();",
|
|
229
|
-
" return { data: { user: allUsers[0], token: \"demo-token\", expiresAt: new Date(Date.now() + 3600000).toISOString() } };",
|
|
230
|
-
" }",
|
|
231
|
-
" return { data: { user, token: \"demo-token\", expiresAt: new Date(Date.now() + 3600000).toISOString() } };",
|
|
232
|
-
"});",
|
|
233
|
-
"",
|
|
234
|
-
"const port = Number(process.env.PORT || 4000);",
|
|
235
|
-
"await app.listen({ port, host: \"0.0.0.0\" });",
|
|
236
|
-
].join("\n"));
|
|
237
|
-
|
|
238
|
-
writeTextFile(path.join(targetDir, backendDir, ".env.example"), [
|
|
239
|
-
"# Agent Enderun - Backend Environment Variables",
|
|
240
|
-
"PORT=4000",
|
|
241
|
-
"NODE_ENV=development",
|
|
242
|
-
"DATABASE_URL=sqlite://./dev.db",
|
|
243
|
-
"JWT_SECRET=your_secret_key_here",
|
|
244
|
-
].join("\n"));
|
|
245
|
-
|
|
246
|
-
writeTextFile(path.join(targetDir, backendDir, "README.md"), [
|
|
247
|
-
`# ${spec.title} Backend`,
|
|
248
|
-
"",
|
|
249
|
-
"Fastify API generated by Agent Enderun.",
|
|
250
|
-
"",
|
|
251
|
-
"## Commands",
|
|
252
|
-
"",
|
|
253
|
-
"- `npm run dev` strings",
|
|
254
|
-
"- `npm run build` strings",
|
|
255
|
-
"- `npm run test` strings",
|
|
256
|
-
].join("\n"));
|
|
257
|
-
}
|