@jaypie/mcp 0.3.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/createMcpServer.d.ts +7 -1
- package/dist/index.js +26 -3135
- package/dist/index.js.map +1 -1
- package/dist/suite.d.ts +1 -0
- package/dist/suite.js +2442 -0
- package/dist/suite.js.map +1 -0
- package/package.json +8 -3
- package/release-notes/constructs/1.2.17.md +11 -0
- package/release-notes/fabric/0.1.2.md +11 -0
- package/release-notes/fabric/0.1.3.md +25 -0
- package/release-notes/fabric/0.1.4.md +42 -0
- package/release-notes/mcp/0.3.3.md +12 -0
- package/release-notes/mcp/0.3.4.md +36 -0
- package/release-notes/mcp/0.4.0.md +27 -0
- package/release-notes/testkit/1.2.15.md +23 -0
- package/skills/agents.md +25 -0
- package/skills/aws.md +107 -0
- package/skills/cdk.md +141 -0
- package/skills/cicd.md +152 -0
- package/skills/datadog.md +129 -0
- package/skills/debugging.md +148 -0
- package/skills/dns.md +134 -0
- package/skills/dynamodb.md +140 -0
- package/skills/errors.md +142 -0
- package/skills/fabric.md +191 -0
- package/skills/index.md +7 -0
- package/skills/jaypie.md +100 -0
- package/skills/legacy.md +97 -0
- package/skills/logs.md +160 -0
- package/skills/mocks.md +174 -0
- package/skills/models.md +195 -0
- package/skills/releasenotes.md +94 -0
- package/skills/secrets.md +155 -0
- package/skills/services.md +175 -0
- package/skills/style.md +190 -0
- package/skills/tests.md +209 -0
- package/skills/tools.md +127 -0
- package/skills/topics.md +116 -0
- package/skills/variables.md +146 -0
- package/skills/writing.md +153 -0
- package/prompts/Branch_Management.md +0 -34
- package/prompts/Development_Process.md +0 -89
- package/prompts/Jaypie_Agent_Rules.md +0 -110
- package/prompts/Jaypie_Auth0_Express_Mongoose.md +0 -736
- package/prompts/Jaypie_Browser_and_Frontend_Web_Packages.md +0 -18
- package/prompts/Jaypie_CDK_Constructs_and_Patterns.md +0 -430
- package/prompts/Jaypie_CICD_with_GitHub_Actions.md +0 -371
- package/prompts/Jaypie_Commander_CLI_Package.md +0 -166
- package/prompts/Jaypie_Core_Errors_and_Logging.md +0 -39
- package/prompts/Jaypie_DynamoDB_Package.md +0 -774
- package/prompts/Jaypie_Eslint_NPM_Package.md +0 -78
- package/prompts/Jaypie_Express_Package.md +0 -630
- package/prompts/Jaypie_Fabric_Commander.md +0 -411
- package/prompts/Jaypie_Fabric_LLM.md +0 -312
- package/prompts/Jaypie_Fabric_Lambda.md +0 -308
- package/prompts/Jaypie_Fabric_MCP.md +0 -316
- package/prompts/Jaypie_Fabric_Package.md +0 -513
- package/prompts/Jaypie_Fabricator.md +0 -617
- package/prompts/Jaypie_Ideal_Project_Structure.md +0 -78
- package/prompts/Jaypie_Init_CICD_with_GitHub_Actions.md +0 -1186
- package/prompts/Jaypie_Init_Express_on_Lambda.md +0 -115
- package/prompts/Jaypie_Init_Jaypie_CDK_Package.md +0 -35
- package/prompts/Jaypie_Init_Lambda_Package.md +0 -505
- package/prompts/Jaypie_Init_Monorepo_Project.md +0 -44
- package/prompts/Jaypie_Init_Project_Subpackage.md +0 -65
- package/prompts/Jaypie_Legacy_Patterns.md +0 -15
- package/prompts/Jaypie_Llm_Calls.md +0 -449
- package/prompts/Jaypie_Llm_Tools.md +0 -155
- package/prompts/Jaypie_MCP_Package.md +0 -281
- package/prompts/Jaypie_Mocks_and_Testkit.md +0 -137
- package/prompts/Jaypie_Repokit.md +0 -103
- package/prompts/Jaypie_Scrub.md +0 -177
- package/prompts/Jaypie_Streaming.md +0 -467
- package/prompts/Templates_CDK_Subpackage.md +0 -115
- package/prompts/Templates_Express_Subpackage.md +0 -187
- package/prompts/Templates_Project_Monorepo.md +0 -326
- package/prompts/Templates_Project_Subpackage.md +0 -93
- package/prompts/Write_Efficient_Prompt_Guides.md +0 -48
- package/prompts/Write_and_Maintain_Engaging_Readme.md +0 -67
package/skills/fabric.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Fabric service patterns and adapters
|
|
3
|
+
related: services, errors, tools
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Fabric Services
|
|
7
|
+
|
|
8
|
+
Fabric provides a unified service pattern that works across CLI, Lambda, LLM tools, and MCP.
|
|
9
|
+
|
|
10
|
+
## Core Concept
|
|
11
|
+
|
|
12
|
+
Define a service once, deploy it anywhere:
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
import { fabricService } from "@jaypie/fabric";
|
|
16
|
+
|
|
17
|
+
const greetService = fabricService({
|
|
18
|
+
alias: "greet",
|
|
19
|
+
description: "Greet a user by name",
|
|
20
|
+
input: {
|
|
21
|
+
name: {
|
|
22
|
+
type: String,
|
|
23
|
+
required: true,
|
|
24
|
+
description: "Name to greet",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
service: async ({ name }) => {
|
|
28
|
+
return `Hello, ${name}!`;
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Adapters
|
|
34
|
+
|
|
35
|
+
### Lambda Handler
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { fabricLambdaHandler } from "@jaypie/fabric";
|
|
39
|
+
|
|
40
|
+
export const handler = fabricLambdaHandler(greetService);
|
|
41
|
+
// Invoked via Lambda with { name: "World" }
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### CLI Command
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { fabricCommand } from "@jaypie/fabric";
|
|
48
|
+
|
|
49
|
+
const program = new Command();
|
|
50
|
+
program.addCommand(fabricCommand(greetService));
|
|
51
|
+
// $ cli greet --name World
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### MCP Tool
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { fabricMcp, FabricMcpServer } from "@jaypie/fabric/mcp";
|
|
58
|
+
|
|
59
|
+
// Single service registration
|
|
60
|
+
fabricMcp({ service: greetService, server });
|
|
61
|
+
|
|
62
|
+
// Multi-service server (preferred)
|
|
63
|
+
const server = FabricMcpServer({
|
|
64
|
+
name: "my-server",
|
|
65
|
+
version: "1.0.0",
|
|
66
|
+
services: [greetService, searchService],
|
|
67
|
+
});
|
|
68
|
+
// Available as MCP tools "greet" and "search"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### LLM Tool
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
import { fabricLlmTool } from "@jaypie/fabric";
|
|
75
|
+
|
|
76
|
+
const tools = [fabricLlmTool(greetService)];
|
|
77
|
+
// Available to LLM as function call
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Service Suites
|
|
81
|
+
|
|
82
|
+
Group related services:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { createServiceSuite, fabricService } from "@jaypie/fabric";
|
|
86
|
+
|
|
87
|
+
const userService = fabricService({
|
|
88
|
+
alias: "user_get",
|
|
89
|
+
description: "Get user by ID",
|
|
90
|
+
input: { id: { type: String, required: true } },
|
|
91
|
+
service: async ({ id }) => User.findById(id),
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const userListService = fabricService({
|
|
95
|
+
alias: "user_list",
|
|
96
|
+
description: "List all users",
|
|
97
|
+
input: {},
|
|
98
|
+
service: async () => User.find(),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const suite = createServiceSuite({
|
|
102
|
+
name: "users",
|
|
103
|
+
version: "1.0.0",
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
suite.register(userService, "users");
|
|
107
|
+
suite.register(userListService, "users");
|
|
108
|
+
|
|
109
|
+
// Access services
|
|
110
|
+
suite.services; // ServiceMeta[] - metadata for listing
|
|
111
|
+
suite.getServiceFunctions(); // Service[] - actual functions
|
|
112
|
+
suite.execute("user_get", { id }); // Direct execution
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Suite to MCP Server
|
|
116
|
+
|
|
117
|
+
Connect suites directly to MCP:
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
import { createMcpServerFromSuite } from "@jaypie/fabric/mcp";
|
|
121
|
+
|
|
122
|
+
const server = createMcpServerFromSuite(suite, {
|
|
123
|
+
name: "users-api", // Optional override
|
|
124
|
+
version: "1.0.0",
|
|
125
|
+
});
|
|
126
|
+
// All suite services now available as MCP tools
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Input Validation
|
|
130
|
+
|
|
131
|
+
Fabric validates inputs automatically:
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
const service = fabricService({
|
|
135
|
+
input: {
|
|
136
|
+
email: {
|
|
137
|
+
type: String,
|
|
138
|
+
required: true,
|
|
139
|
+
description: "User email address",
|
|
140
|
+
},
|
|
141
|
+
count: {
|
|
142
|
+
type: Number,
|
|
143
|
+
required: false,
|
|
144
|
+
description: "Number of results",
|
|
145
|
+
},
|
|
146
|
+
status: {
|
|
147
|
+
type: ["active", "inactive"] as const,
|
|
148
|
+
required: false,
|
|
149
|
+
description: "Filter by status",
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
service: async ({ email, count, status }) => {
|
|
153
|
+
// email: string (validated)
|
|
154
|
+
// count: number | undefined
|
|
155
|
+
// status: "active" | "inactive" | undefined
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Error Handling
|
|
161
|
+
|
|
162
|
+
Fabric services use Jaypie errors:
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
import { fabricService } from "@jaypie/fabric";
|
|
166
|
+
import { NotFoundError, BadRequestError } from "jaypie";
|
|
167
|
+
|
|
168
|
+
const service = fabricService({
|
|
169
|
+
alias: "user_get",
|
|
170
|
+
input: { id: { type: String, required: true } },
|
|
171
|
+
service: async ({ id }) => {
|
|
172
|
+
if (!isValidId(id)) {
|
|
173
|
+
throw new BadRequestError("Invalid user ID format");
|
|
174
|
+
}
|
|
175
|
+
const user = await User.findById(id);
|
|
176
|
+
if (!user) {
|
|
177
|
+
throw new NotFoundError(`User ${id} not found`);
|
|
178
|
+
}
|
|
179
|
+
return user;
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Best Practices
|
|
185
|
+
|
|
186
|
+
1. **Single Responsibility**: Each service does one thing
|
|
187
|
+
2. **Descriptive Aliases**: Use `noun_verb` format (`user_get`, `order_create`)
|
|
188
|
+
3. **Clear Descriptions**: Write for AI tools that need context
|
|
189
|
+
4. **Input Documentation**: Describe what each input expects
|
|
190
|
+
5. **Return Types**: Return JSON-serializable data
|
|
191
|
+
|
package/skills/index.md
ADDED
package/skills/jaypie.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Jaypie overview and core concepts
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Introduction to Jaypie
|
|
6
|
+
|
|
7
|
+
Jaypie is a complete stack framework for building multi-environment cloud applications on AWS using TypeScript/Node.js.
|
|
8
|
+
|
|
9
|
+
## Core Packages
|
|
10
|
+
|
|
11
|
+
### Main Package: `jaypie`
|
|
12
|
+
|
|
13
|
+
The main package provides:
|
|
14
|
+
- **Secrets**: AWS Secrets Manager integration
|
|
15
|
+
- **Errors**: Structured error types (ConfigurationError, etc.)
|
|
16
|
+
- **Events**: Event parsing for Lambda handlers
|
|
17
|
+
- **Lifecycle**: Handler lifecycle management
|
|
18
|
+
- **Logging**: Structured logging with context
|
|
19
|
+
- **Queues**: SQS messaging utilities
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import {
|
|
23
|
+
getSecret,
|
|
24
|
+
log,
|
|
25
|
+
ConfigurationError,
|
|
26
|
+
HTTP,
|
|
27
|
+
PROJECT
|
|
28
|
+
} from "jaypie";
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Infrastructure: `@jaypie/constructs`
|
|
32
|
+
|
|
33
|
+
CDK constructs for AWS infrastructure:
|
|
34
|
+
- Lambda functions with best practices
|
|
35
|
+
- SQS queues with DLQ
|
|
36
|
+
- S3 buckets with encryption
|
|
37
|
+
- CloudFront distributions
|
|
38
|
+
- Secrets Manager secrets
|
|
39
|
+
|
|
40
|
+
### Testing: `@jaypie/testkit`
|
|
41
|
+
|
|
42
|
+
Testing utilities and mocks:
|
|
43
|
+
- Mock implementations for all Jaypie functions
|
|
44
|
+
- Vitest configuration helpers
|
|
45
|
+
- Test data fabrication
|
|
46
|
+
|
|
47
|
+
## Project Structure
|
|
48
|
+
|
|
49
|
+
Jaypie projects use npm workspaces:
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
project/
|
|
53
|
+
├── packages/ # npm packages
|
|
54
|
+
│ ├── api/ # Express API
|
|
55
|
+
│ └── lib/ # Shared library
|
|
56
|
+
├── stacks/ # CDK infrastructure
|
|
57
|
+
│ └── cdk/ # CDK app
|
|
58
|
+
└── package.json # Root workspace config
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Key Conventions
|
|
62
|
+
|
|
63
|
+
### Environment Variables
|
|
64
|
+
|
|
65
|
+
| Variable | Purpose |
|
|
66
|
+
|----------|---------|
|
|
67
|
+
| `PROJECT_ENV` | Environment: local, sandbox, production |
|
|
68
|
+
| `PROJECT_KEY` | Project identifier for logging |
|
|
69
|
+
| `PROJECT_NONCE` | Unique resource identifier |
|
|
70
|
+
| `LOG_LEVEL` | Log level: trace, debug, info, warn, error |
|
|
71
|
+
|
|
72
|
+
### Error Handling
|
|
73
|
+
|
|
74
|
+
Never throw vanilla `Error`. Use Jaypie errors:
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { ConfigurationError, NotFoundError } from "jaypie";
|
|
78
|
+
|
|
79
|
+
if (!config.required) {
|
|
80
|
+
throw new ConfigurationError("Missing required config");
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Logging
|
|
85
|
+
|
|
86
|
+
Use structured logging with context:
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import { log } from "jaypie";
|
|
90
|
+
|
|
91
|
+
log.info("Processing request", { userId, action });
|
|
92
|
+
log.error("Request failed", { error: error.message });
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Next Steps
|
|
96
|
+
|
|
97
|
+
- `skill("style")` - Code style conventions
|
|
98
|
+
- `skill("errors")` - Error handling patterns
|
|
99
|
+
- `skill("tests")` - Testing with Vitest
|
|
100
|
+
- `skill("cdk")` - Infrastructure with CDK
|
package/skills/legacy.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Legacy libraries and deprecated patterns
|
|
3
|
+
related: dynamodb, fabric, mocks
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Legacy Patterns
|
|
7
|
+
|
|
8
|
+
Deprecated libraries and patterns that may exist in older Jaypie projects.
|
|
9
|
+
|
|
10
|
+
## @jaypie/core (Deprecated)
|
|
11
|
+
|
|
12
|
+
Migrated to `@jaypie/kit`. Update imports:
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
// Old
|
|
16
|
+
import { someUtil } from "@jaypie/core";
|
|
17
|
+
|
|
18
|
+
// New
|
|
19
|
+
import { someUtil } from "@jaypie/kit";
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## @jaypie/mongoose (Legacy)
|
|
23
|
+
|
|
24
|
+
MongoDB/Mongoose integration. Consider DynamoDB for new projects.
|
|
25
|
+
|
|
26
|
+
### Connection
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { connectMongoose } from "@jaypie/mongoose";
|
|
30
|
+
|
|
31
|
+
export const handler = async (event) => {
|
|
32
|
+
await connectMongoose();
|
|
33
|
+
// Connection cached for Lambda warm starts
|
|
34
|
+
};
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Models
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import mongoose, { Schema, Document } from "mongoose";
|
|
41
|
+
|
|
42
|
+
interface IUser extends Document {
|
|
43
|
+
email: string;
|
|
44
|
+
name: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const userSchema = new Schema<IUser>({
|
|
48
|
+
email: { type: String, required: true },
|
|
49
|
+
name: { type: String, required: true },
|
|
50
|
+
}, { timestamps: true });
|
|
51
|
+
|
|
52
|
+
export const User = mongoose.model<IUser>("User", userSchema);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Mocking
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
vi.mock("@jaypie/mongoose", async () => {
|
|
59
|
+
const { mockMongoose } = await import("@jaypie/testkit");
|
|
60
|
+
return mockMongoose(vi);
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Migration Guides
|
|
65
|
+
|
|
66
|
+
### Mongoose to DynamoDB
|
|
67
|
+
|
|
68
|
+
1. Define DynamoDB item types (see `skill("dynamodb")`)
|
|
69
|
+
2. Update data access patterns for single-table design
|
|
70
|
+
3. Replace Mongoose queries with DynamoDB operations
|
|
71
|
+
4. Update tests to mock DynamoDB instead of Mongoose
|
|
72
|
+
|
|
73
|
+
### Core to Kit
|
|
74
|
+
|
|
75
|
+
Direct replacement - same exports, new package name:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npm uninstall @jaypie/core
|
|
79
|
+
npm install @jaypie/kit
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Update imports throughout codebase.
|
|
83
|
+
|
|
84
|
+
## When to Keep Legacy
|
|
85
|
+
|
|
86
|
+
Keep legacy patterns when:
|
|
87
|
+
- Existing production system is stable
|
|
88
|
+
- Migration cost outweighs benefits
|
|
89
|
+
- Team expertise is in legacy stack
|
|
90
|
+
- Database has significant existing data
|
|
91
|
+
|
|
92
|
+
Migrate when:
|
|
93
|
+
- Starting new features
|
|
94
|
+
- Performance issues arise
|
|
95
|
+
- Scaling requirements change
|
|
96
|
+
- Simplifying architecture
|
|
97
|
+
|
package/skills/logs.md
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Logging patterns and conventions
|
|
3
|
+
related: debugging, datadog, variables
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Logging Patterns
|
|
7
|
+
|
|
8
|
+
Jaypie provides structured logging for observability.
|
|
9
|
+
|
|
10
|
+
## Basic Usage
|
|
11
|
+
|
|
12
|
+
```typescript
|
|
13
|
+
import { log } from "jaypie";
|
|
14
|
+
|
|
15
|
+
log.trace("Detailed debug info");
|
|
16
|
+
log.debug("Debug information");
|
|
17
|
+
log.info("Informational message");
|
|
18
|
+
log.warn("Warning message");
|
|
19
|
+
log.error("Error message");
|
|
20
|
+
log.fatal("Fatal error");
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Structured Logging
|
|
24
|
+
|
|
25
|
+
Always include context as the second argument:
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
log.info("User logged in", {
|
|
29
|
+
userId: user.id,
|
|
30
|
+
email: user.email,
|
|
31
|
+
method: "oauth",
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
log.error("Payment failed", {
|
|
35
|
+
orderId: order.id,
|
|
36
|
+
amount: order.total,
|
|
37
|
+
error: error.message,
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Log Levels
|
|
42
|
+
|
|
43
|
+
| Level | Use For |
|
|
44
|
+
|-------|---------|
|
|
45
|
+
| trace | Very detailed debugging (loops, iterations) |
|
|
46
|
+
| debug | Development debugging |
|
|
47
|
+
| info | Normal operations, business events |
|
|
48
|
+
| warn | Unexpected but handled situations |
|
|
49
|
+
| error | Errors that need attention |
|
|
50
|
+
| fatal | Application cannot continue |
|
|
51
|
+
|
|
52
|
+
## Setting Log Level
|
|
53
|
+
|
|
54
|
+
Via environment variable:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
LOG_LEVEL=debug npm run dev
|
|
58
|
+
LOG_LEVEL=trace npm test
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
In production, typically `info` or `warn`.
|
|
62
|
+
|
|
63
|
+
## Request Context
|
|
64
|
+
|
|
65
|
+
Include request identifiers for tracing:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
log.info("Processing request", {
|
|
69
|
+
requestId: req.id,
|
|
70
|
+
path: req.path,
|
|
71
|
+
userId: req.user?.id,
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Error Logging
|
|
76
|
+
|
|
77
|
+
Log errors with full context:
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
try {
|
|
81
|
+
await riskyOperation();
|
|
82
|
+
} catch (error) {
|
|
83
|
+
log.error("Operation failed", {
|
|
84
|
+
error: error.message,
|
|
85
|
+
stack: error.stack,
|
|
86
|
+
input: sanitizedInput,
|
|
87
|
+
});
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Sensitive Data
|
|
93
|
+
|
|
94
|
+
Never log sensitive data:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
// BAD
|
|
98
|
+
log.info("User auth", { password: user.password });
|
|
99
|
+
|
|
100
|
+
// GOOD
|
|
101
|
+
log.info("User auth", { userId: user.id, hasPassword: !!user.password });
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Searching Logs
|
|
105
|
+
|
|
106
|
+
### Via MCP (Datadog)
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
# Search by requestId
|
|
110
|
+
datadog_logs --query "@requestId:abc-123"
|
|
111
|
+
|
|
112
|
+
# Search errors
|
|
113
|
+
datadog_logs --query "status:error" --from "now-1h"
|
|
114
|
+
|
|
115
|
+
# Search by user
|
|
116
|
+
datadog_logs --query "@userId:user-456"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Via MCP (CloudWatch)
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
aws_logs_filter_log_events \
|
|
123
|
+
--logGroupName "/aws/lambda/my-function" \
|
|
124
|
+
--filterPattern "ERROR"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Log Format
|
|
128
|
+
|
|
129
|
+
Jaypie logs are JSON-formatted for Datadog:
|
|
130
|
+
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"level": "info",
|
|
134
|
+
"message": "User logged in",
|
|
135
|
+
"timestamp": "2024-01-15T10:00:00.000Z",
|
|
136
|
+
"userId": "user-123",
|
|
137
|
+
"method": "oauth",
|
|
138
|
+
"dd": {
|
|
139
|
+
"trace_id": "abc123",
|
|
140
|
+
"span_id": "def456"
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Lambda Logging
|
|
146
|
+
|
|
147
|
+
Lambda handlers automatically add context:
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
import { lambdaHandler } from "@jaypie/lambda";
|
|
151
|
+
|
|
152
|
+
export const handler = lambdaHandler(async (event) => {
|
|
153
|
+
// Logs automatically include:
|
|
154
|
+
// - requestId
|
|
155
|
+
// - functionName
|
|
156
|
+
// - cold_start indicator
|
|
157
|
+
log.info("Processing", { customField: "value" });
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
package/skills/mocks.md
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Mock patterns via @jaypie/testkit
|
|
3
|
+
related: tests, errors
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Testing Mocks
|
|
7
|
+
|
|
8
|
+
`@jaypie/testkit` provides mocks for Jaypie packages in tests.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install -D @jaypie/testkit
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Setup
|
|
17
|
+
|
|
18
|
+
In your test setup file:
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
// vitest.setup.ts
|
|
22
|
+
import { vi } from "vitest";
|
|
23
|
+
|
|
24
|
+
vi.mock("jaypie", async () => {
|
|
25
|
+
const { mockJaypie } = await import("@jaypie/testkit");
|
|
26
|
+
return mockJaypie(vi);
|
|
27
|
+
});
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Configure in vitest.config.ts:
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
export default defineConfig({
|
|
34
|
+
test: {
|
|
35
|
+
setupFiles: ["./vitest.setup.ts"],
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Available Mocks
|
|
41
|
+
|
|
42
|
+
### Main Package (jaypie)
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
vi.mock("jaypie", async () => {
|
|
46
|
+
const { mockJaypie } = await import("@jaypie/testkit");
|
|
47
|
+
return mockJaypie(vi);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Mocked: log, getSecret, sendMessage, etc.
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Logger
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
vi.mock("@jaypie/logger", async () => {
|
|
57
|
+
const { mockLogger } = await import("@jaypie/testkit");
|
|
58
|
+
return mockLogger(vi);
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### AWS
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
vi.mock("@jaypie/aws", async () => {
|
|
66
|
+
const { mockAws } = await import("@jaypie/testkit");
|
|
67
|
+
return mockAws(vi);
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Legacy Mocks
|
|
72
|
+
|
|
73
|
+
For legacy packages, see `skill("legacy")`.
|
|
74
|
+
|
|
75
|
+
## Using Mocks in Tests
|
|
76
|
+
|
|
77
|
+
### Verify Logging
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import { log } from "jaypie";
|
|
81
|
+
|
|
82
|
+
it("logs the operation", async () => {
|
|
83
|
+
await myFunction();
|
|
84
|
+
|
|
85
|
+
expect(log.info).toHaveBeenCalledWith(
|
|
86
|
+
"Operation completed",
|
|
87
|
+
expect.objectContaining({ userId: "123" })
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Mock Secret Values
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { getSecret } from "jaypie";
|
|
96
|
+
|
|
97
|
+
beforeEach(() => {
|
|
98
|
+
vi.mocked(getSecret).mockResolvedValue("mock-api-key");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("uses the API key", async () => {
|
|
102
|
+
const result = await myFunction();
|
|
103
|
+
|
|
104
|
+
expect(getSecret).toHaveBeenCalledWith("api-key-name");
|
|
105
|
+
expect(result.authenticated).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Mock Errors
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
import { getSecret } from "jaypie";
|
|
113
|
+
import { ConfigurationError } from "jaypie";
|
|
114
|
+
|
|
115
|
+
it("handles missing secrets", async () => {
|
|
116
|
+
vi.mocked(getSecret).mockRejectedValue(
|
|
117
|
+
new ConfigurationError("Secret not found")
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
await expect(myFunction()).rejects.toThrow(ConfigurationError);
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Mock Matchers
|
|
125
|
+
|
|
126
|
+
### toBeJaypieError
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import { matchers } from "@jaypie/testkit";
|
|
130
|
+
|
|
131
|
+
expect.extend(matchers);
|
|
132
|
+
|
|
133
|
+
it("throws a Jaypie error", async () => {
|
|
134
|
+
await expect(myFunction()).rejects.toBeJaypieError();
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### toBeValidSchema
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
it("returns valid schema", () => {
|
|
142
|
+
const result = buildSchema();
|
|
143
|
+
expect(result).toBeValidSchema();
|
|
144
|
+
});
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Per-Test Mock Reset
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
beforeEach(() => {
|
|
151
|
+
vi.clearAllMocks();
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
afterEach(() => {
|
|
155
|
+
vi.resetAllMocks();
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Export Verification
|
|
160
|
+
|
|
161
|
+
When adding exports to packages, update testkit:
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
// packages/testkit/src/mocks/mockJaypie.ts
|
|
165
|
+
export function mockJaypie(vi) {
|
|
166
|
+
return {
|
|
167
|
+
log: mockLog(vi),
|
|
168
|
+
getSecret: vi.fn().mockResolvedValue("mock"),
|
|
169
|
+
// Add new exports here
|
|
170
|
+
newFunction: vi.fn(),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|