@jaypie/mcp 0.3.4 → 0.4.1
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 +22 -2088
- package/dist/index.js.map +1 -1
- package/dist/suite.js +1197 -7
- package/dist/suite.js.map +1 -1
- package/package.json +1 -2
- package/release-notes/constructs/1.2.18.md +12 -0
- package/release-notes/fabric/0.1.3.md +25 -0
- package/release-notes/fabric/0.1.4.md +42 -0
- package/release-notes/llm/1.2.5.md +25 -0
- package/release-notes/llm/1.2.6.md +55 -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 +18 -8
- package/skills/aws.md +232 -60
- package/skills/datadog.md +98 -64
- package/skills/dynamodb.md +37 -28
- package/skills/fabric.md +30 -3
- package/skills/issues.md +55 -0
- package/skills/llm.md +381 -0
- package/skills/secrets.md +74 -18
- package/skills/skills.md +23 -0
- package/skills/tools-aws.md +148 -0
- package/skills/tools-datadog.md +190 -0
- package/skills/tools-dynamodb.md +140 -0
- package/skills/tools.md +19 -54
- package/skills/vocabulary.md +25 -0
- package/dist/aws-B3dW_-bD.js +0 -1202
- package/dist/aws-B3dW_-bD.js.map +0 -1
- 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 -599
- 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/topics.md +0 -116
- /package/skills/{writing.md → documentation.md} +0 -0
package/package.json
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.2.18
|
|
3
|
+
date: 2025-01-21
|
|
4
|
+
summary: JaypieNextJs supports domain-less CloudFront-only deployment
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Changes
|
|
8
|
+
|
|
9
|
+
- Added `domainProps: false` option to `JaypieNextJs` to deploy without a custom domain
|
|
10
|
+
- When `domainProps: false`, the application is accessible only via CloudFront URL
|
|
11
|
+
- `NEXT_PUBLIC_SITE_URL` is automatically set to the CloudFront distribution URL when no domain is configured
|
|
12
|
+
- Cache policy names use construct ID instead of domain name for domain-less deployments
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 0.1.3
|
|
3
|
+
date: 2025-01-20
|
|
4
|
+
summary: Added FabricMcpServer for multi-service MCP tool registration
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Changes
|
|
8
|
+
|
|
9
|
+
- Added `FabricMcpServer` function for creating MCP servers with multiple services registered as tools
|
|
10
|
+
- Added `isFabricMcpServer` type guard for runtime type checking
|
|
11
|
+
- Added `isService` export from main package for checking if a value is a fabricated service
|
|
12
|
+
- New types: `FabricMcpServerConfig`, `FabricMcpServerServiceEntry`, `FabricMcpServerToolConfig`, `RegisteredTool`
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { fabricService } from "@jaypie/fabric";
|
|
18
|
+
import { FabricMcpServer } from "@jaypie/fabric/mcp";
|
|
19
|
+
|
|
20
|
+
const server = FabricMcpServer({
|
|
21
|
+
name: "my-server",
|
|
22
|
+
version: "1.0.0",
|
|
23
|
+
services: [greetService, echoService],
|
|
24
|
+
});
|
|
25
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 0.1.4
|
|
3
|
+
date: 2025-01-20
|
|
4
|
+
summary: Added ServiceSuite bridge for MCP servers
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Changes
|
|
8
|
+
|
|
9
|
+
- Added `getServiceFunctions()` method to `ServiceSuite` - returns all registered service functions for transport adapters
|
|
10
|
+
- Added `getServiceFunction(name)` method to `ServiceSuite` - returns a specific service function by name
|
|
11
|
+
- Added `createMcpServerFromSuite()` function in `@jaypie/fabric/mcp` - creates FabricMcpServer from a ServiceSuite
|
|
12
|
+
- New type: `CreateMcpServerFromSuiteConfig`
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
ServiceSuites now connect directly to MCP servers:
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { createServiceSuite, fabricService } from "@jaypie/fabric";
|
|
20
|
+
import { createMcpServerFromSuite } from "@jaypie/fabric/mcp";
|
|
21
|
+
|
|
22
|
+
const suite = createServiceSuite({ name: "my-suite", version: "1.0.0" });
|
|
23
|
+
suite.register(myService, "category");
|
|
24
|
+
|
|
25
|
+
// Create MCP server from suite
|
|
26
|
+
const server = createMcpServerFromSuite(suite);
|
|
27
|
+
// All suite services are now registered as MCP tools
|
|
28
|
+
|
|
29
|
+
// Access service functions directly
|
|
30
|
+
const functions = suite.getServiceFunctions();
|
|
31
|
+
const specific = suite.getServiceFunction("my-service");
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Architecture
|
|
35
|
+
|
|
36
|
+
This enables a pattern where services are defined once and deployed to multiple transports:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
fabricService() → ServiceSuite → createMcpServerFromSuite() → MCP Server
|
|
40
|
+
→ FabricHttpServer → HTTP/Lambda
|
|
41
|
+
→ FabricRouter → Express
|
|
42
|
+
```
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.2.5
|
|
3
|
+
date: 2025-01-21
|
|
4
|
+
summary: Preserve original error details in BadGatewayError thrown by RetryExecutor
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Changes
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **Preserve original error message in BadGatewayError**: When `RetryExecutor` encounters a non-retryable error or exhausts retries, it now preserves the original error message in the thrown `BadGatewayError`. Previously, the original error details (e.g., "Quota exceeded for metric X, limit: 0") were lost, making debugging difficult.
|
|
12
|
+
|
|
13
|
+
### Before
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
JaypieError: An unexpected error occurred on an upstream resource
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### After
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
JaypieError: You exceeded your current quota... limit: 0
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This fix improves debugging by preserving context from LLM provider errors (like Gemini's 429 quota exceeded responses).
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.2.6
|
|
3
|
+
date: 2025-01-21
|
|
4
|
+
summary: Add configurable fallback provider chain for automatic retry with alternative providers
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Changes
|
|
8
|
+
|
|
9
|
+
### New Features
|
|
10
|
+
|
|
11
|
+
- **Fallback Provider Support**: Configure a chain of fallback providers that automatically retry failed `operate()` calls when the primary provider fails with an unrecoverable error.
|
|
12
|
+
|
|
13
|
+
### Usage
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
// Instance-level configuration
|
|
17
|
+
const llm = new Llm("anthropic", {
|
|
18
|
+
model: "claude-sonnet-4",
|
|
19
|
+
fallback: [
|
|
20
|
+
{ provider: "openai", model: "gpt-4o" },
|
|
21
|
+
{ provider: "gemini", model: "gemini-2.0-flash" },
|
|
22
|
+
],
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Per-call override
|
|
26
|
+
const response = await llm.operate(input, {
|
|
27
|
+
fallback: [{ provider: "openai", model: "gpt-4o" }],
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Disable fallback for specific call
|
|
31
|
+
const response = await llm.operate(input, { fallback: false });
|
|
32
|
+
|
|
33
|
+
// Static method with fallback
|
|
34
|
+
const response = await Llm.operate(input, {
|
|
35
|
+
model: "claude-sonnet-4",
|
|
36
|
+
fallback: [{ provider: "openai", model: "gpt-4o" }],
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Response Metadata
|
|
41
|
+
|
|
42
|
+
The `LlmOperateResponse` now includes:
|
|
43
|
+
- `provider`: Which provider actually handled the request
|
|
44
|
+
- `fallbackUsed`: `true` if a fallback provider was used
|
|
45
|
+
- `fallbackAttempts`: Number of providers tried (1 = primary only)
|
|
46
|
+
|
|
47
|
+
### New Type
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
interface LlmFallbackConfig {
|
|
51
|
+
provider: string;
|
|
52
|
+
model?: string;
|
|
53
|
+
apiKey?: string;
|
|
54
|
+
}
|
|
55
|
+
```
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 0.4.0
|
|
3
|
+
date: 2025-01-20
|
|
4
|
+
summary: Remove deprecated list_prompts and read_prompt tools
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Changes
|
|
8
|
+
|
|
9
|
+
### Breaking Changes
|
|
10
|
+
|
|
11
|
+
- **Removed `list_prompts` tool**: Use `skill("index")` instead
|
|
12
|
+
- **Removed `read_prompt` tool**: Use `skill(alias)` instead
|
|
13
|
+
- **Removed `prompts/` directory from package**: All documentation now lives in `skills/`
|
|
14
|
+
|
|
15
|
+
### Migration
|
|
16
|
+
|
|
17
|
+
If you were using `list_prompts`, replace with:
|
|
18
|
+
```
|
|
19
|
+
skill("index")
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
If you were using `read_prompt("Jaypie_Express_Package.md")`, find the equivalent skill alias and use:
|
|
23
|
+
```
|
|
24
|
+
skill("express") // or appropriate alias
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Use `skill("index")` to see all available skills with descriptions.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.2.15
|
|
3
|
+
date: 2025-01-20
|
|
4
|
+
summary: Removed vocabulary mocks, updated to fabric types
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Changes
|
|
8
|
+
|
|
9
|
+
- Removed `vocabulary` mock module (vocabulary package deprecated)
|
|
10
|
+
- Updated `IndexableEntity` type import to `IndexableModel` from `@jaypie/fabric`
|
|
11
|
+
- Removed `mock.vocabulary` exports from mock index
|
|
12
|
+
|
|
13
|
+
## Migration
|
|
14
|
+
|
|
15
|
+
If you were using vocabulary mocks, they are no longer needed as the functionality has moved to `@jaypie/fabric`:
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
// Before
|
|
19
|
+
import { IndexableEntity } from "@jaypie/testkit/mock";
|
|
20
|
+
|
|
21
|
+
// After
|
|
22
|
+
import { IndexableModel } from "@jaypie/fabric";
|
|
23
|
+
```
|
package/skills/agents.md
CHANGED
|
@@ -1,25 +1,35 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: Recommended prompts to help agents use Jaypie; to put in AGENTS.md, CLAUDE.md, etc.
|
|
3
|
+
related: jaypie
|
|
3
4
|
---
|
|
4
5
|
|
|
5
6
|
# Agent Instructions
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
The goal is concise introduction to Jaypie capabilities that invite agent exploration.
|
|
9
|
+
|
|
10
|
+
Add one of the following to AGENTS.md, CLAUDE.md, or similar files.
|
|
11
|
+
|
|
12
|
+
## Complete Version
|
|
13
|
+
|
|
14
|
+
The complete version references as many daily tasks as possible without listing everything.
|
|
15
|
+
Some tasks should not be listed to avoid suboptimal pathing.
|
|
8
16
|
|
|
9
17
|
```markdown
|
|
10
18
|
## Jaypie
|
|
11
19
|
|
|
12
20
|
Query `mcp__jaypie__skill(alias: String)` for development guidance:
|
|
13
21
|
|
|
14
|
-
Contents: index, releasenotes
|
|
15
|
-
Development:
|
|
22
|
+
Contents: index, releasenotes
|
|
23
|
+
Development: documentation, errors, logs, mocks, style, tests
|
|
16
24
|
Infrastructure: aws, cdk, cicd, datadog, dns, dynamodb, secrets, variables
|
|
17
|
-
Patterns: fabric, models, services,
|
|
18
|
-
Meta:
|
|
25
|
+
Patterns: fabric, models, services, vocabulary
|
|
26
|
+
Meta: issues, jaypie, skills, tools
|
|
19
27
|
```
|
|
20
28
|
|
|
21
|
-
|
|
29
|
+
## Short Version
|
|
30
|
+
|
|
31
|
+
The one-line version tells the agent how to find out more about Jaypie skills.
|
|
22
32
|
|
|
23
33
|
```markdown
|
|
24
|
-
`mcp__jaypie__skill(
|
|
34
|
+
`mcp__jaypie__skill(skills)`: Discover Jaypie development skills and tools available in this repository.
|
|
25
35
|
```
|
package/skills/aws.md
CHANGED
|
@@ -1,107 +1,279 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: AWS integration
|
|
3
|
-
related: cdk, dynamodb, secrets, logs
|
|
2
|
+
description: AWS integration and cloud services code patterns
|
|
3
|
+
related: cdk, dynamodb, secrets, logs, tools-aws
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# AWS Integration
|
|
7
7
|
|
|
8
|
-
Jaypie integrates with AWS services through
|
|
8
|
+
Jaypie integrates with AWS services through the `@jaypie/aws` package and CDK constructs.
|
|
9
|
+
Access `@jaypie/aws` through the main `jaypie` package.
|
|
9
10
|
|
|
10
|
-
## MCP
|
|
11
|
+
## MCP Tools
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
For interactive AWS tools (Lambda, S3, SQS, CloudWatch, Step Functions, CloudFormation), see **tools-aws**.
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
aws_lambda_list_functions - List functions with optional prefix filter
|
|
17
|
-
aws_lambda_get_function - Get function configuration and details
|
|
18
|
-
```
|
|
15
|
+
## @jaypie/aws Package
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
```
|
|
22
|
-
aws_stepfunctions_list_executions - List executions for a state machine
|
|
23
|
-
aws_stepfunctions_stop_execution - Stop a running execution
|
|
24
|
-
```
|
|
17
|
+
The `@jaypie/aws` package provides SDK utilities for Secrets Manager, SQS, S3, Textract, and streaming.
|
|
25
18
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
19
|
+
```typescript
|
|
20
|
+
import {
|
|
21
|
+
getEnvSecret,
|
|
22
|
+
getMessages,
|
|
23
|
+
getS3FileBuffer,
|
|
24
|
+
loadEnvSecrets,
|
|
25
|
+
sendBatchMessages,
|
|
26
|
+
sendMessage,
|
|
27
|
+
} from "@jaypie/aws";
|
|
29
28
|
```
|
|
30
29
|
|
|
31
|
-
###
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
### Available Functions
|
|
31
|
+
|
|
32
|
+
| Function | Description |
|
|
33
|
+
|----------|-------------|
|
|
34
|
+
| **Secrets** | |
|
|
35
|
+
| `getEnvSecret(name, { env? })` | Preferred: Fetch secret using env var patterns |
|
|
36
|
+
| `loadEnvSecrets(...names)` | Load multiple secrets into `process.env` |
|
|
37
|
+
| `getSecret(name)` | Internal: Direct fetch by AWS secret name |
|
|
38
|
+
| **SQS Messaging** | |
|
|
39
|
+
| `sendMessage(body, { queueUrl?, ... })` | Send single message to SQS |
|
|
40
|
+
| `sendBatchMessages({ messages, queueUrl?, ... })` | Send multiple messages (batched in groups of 10) |
|
|
41
|
+
| `getMessages(event)` | Parse SQS/SNS event into array of message bodies |
|
|
42
|
+
| `getSingletonMessage(event)` | Get exactly one message or throw `BadGatewayError` |
|
|
43
|
+
| **S3** | |
|
|
44
|
+
| `getS3FileBuffer({ bucket, key })` | Fetch S3 file as Buffer |
|
|
45
|
+
| **Textract** | |
|
|
46
|
+
| `sendTextractJob({ bucket, key, ... })` | Start async Textract job |
|
|
47
|
+
| `getTextractJob(jobId)` | Get results of completed Textract job |
|
|
48
|
+
| **Streaming** | |
|
|
49
|
+
| `JaypieStream` | Class wrapping async iterable with streaming methods |
|
|
50
|
+
| `createJaypieStream(source)` | Factory for JaypieStream |
|
|
51
|
+
| `createLambdaStream(stream, writer)` | Stream to Lambda response writer |
|
|
52
|
+
| `createExpressStream(stream, res)` | Stream to Express response |
|
|
53
|
+
|
|
54
|
+
## Secrets Management
|
|
35
55
|
|
|
36
|
-
###
|
|
56
|
+
### getEnvSecret (Preferred)
|
|
57
|
+
|
|
58
|
+
Use `getEnvSecret` for environment-aware secret resolution. It checks environment variables in order:
|
|
59
|
+
|
|
60
|
+
1. `SECRET_{name}` - Explicit secret reference (fetches from Secrets Manager)
|
|
61
|
+
2. `{name}_SECRET` - Alternative secret reference (fetches from Secrets Manager)
|
|
62
|
+
3. `{name}` - Returns direct value without AWS call
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { getEnvSecret } from "@jaypie/aws";
|
|
66
|
+
|
|
67
|
+
// If SECRET_ANTHROPIC_API_KEY="arn:aws:secretsmanager:..." exists, fetches from AWS
|
|
68
|
+
// Otherwise returns process.env.ANTHROPIC_API_KEY directly
|
|
69
|
+
const apiKey = await getEnvSecret("ANTHROPIC_API_KEY");
|
|
37
70
|
```
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
71
|
+
|
|
72
|
+
This pattern allows the same code to work locally (with direct env values) and in Lambda (with secret references).
|
|
73
|
+
|
|
74
|
+
### loadEnvSecrets
|
|
75
|
+
|
|
76
|
+
Load multiple secrets at once during handler initialization:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { loadEnvSecrets } from "@jaypie/aws";
|
|
80
|
+
|
|
81
|
+
// Load secrets and set in process.env
|
|
82
|
+
await loadEnvSecrets("ANTHROPIC_API_KEY", "OPENAI_API_KEY");
|
|
83
|
+
|
|
84
|
+
// Now available as process.env.ANTHROPIC_API_KEY, etc.
|
|
42
85
|
```
|
|
43
86
|
|
|
44
|
-
###
|
|
87
|
+
### getSecret (Internal Use)
|
|
88
|
+
|
|
89
|
+
Direct fetch by AWS secret name. Requires `AWS_SESSION_TOKEN`. Prefer `getEnvSecret` unless you need to fetch a secret by its exact AWS name:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { getSecret } from "@jaypie/aws";
|
|
93
|
+
|
|
94
|
+
// Fetch by exact AWS secret name
|
|
95
|
+
const secret = await getSecret("my-project/production/api-key");
|
|
45
96
|
```
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
97
|
+
|
|
98
|
+
## SQS Messaging
|
|
99
|
+
|
|
100
|
+
### sendMessage
|
|
101
|
+
|
|
102
|
+
Send a single message to SQS. Uses `CDK_ENV_QUEUE_URL` by default:
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import { sendMessage } from "@jaypie/aws";
|
|
106
|
+
|
|
107
|
+
// Simple usage with default queue
|
|
108
|
+
await sendMessage({ action: "process", documentId: "doc-123" });
|
|
109
|
+
|
|
110
|
+
// With explicit queue URL
|
|
111
|
+
await sendMessage({ action: "process" }, { queueUrl: "https://sqs..." });
|
|
112
|
+
|
|
113
|
+
// With options
|
|
114
|
+
await sendMessage(
|
|
115
|
+
{ action: "process" },
|
|
116
|
+
{
|
|
117
|
+
delaySeconds: 30,
|
|
118
|
+
messageAttributes: { Priority: { DataType: "String", StringValue: "high" } },
|
|
119
|
+
queueUrl: process.env.CDK_ENV_QUEUE_URL,
|
|
120
|
+
}
|
|
121
|
+
);
|
|
50
122
|
```
|
|
51
123
|
|
|
52
|
-
###
|
|
124
|
+
### sendBatchMessages
|
|
125
|
+
|
|
126
|
+
Send multiple messages, automatically batched in groups of 10:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import { sendBatchMessages } from "@jaypie/aws";
|
|
130
|
+
|
|
131
|
+
const messages = items.map((item) => ({ action: "process", id: item.id }));
|
|
132
|
+
await sendBatchMessages({ messages });
|
|
53
133
|
```
|
|
54
|
-
|
|
134
|
+
|
|
135
|
+
### getMessages and getSingletonMessage
|
|
136
|
+
|
|
137
|
+
Parse incoming SQS/SNS events:
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
import { getMessages, getSingletonMessage } from "@jaypie/aws";
|
|
141
|
+
|
|
142
|
+
// Get all messages from event
|
|
143
|
+
const messages = getMessages(event); // Returns array
|
|
144
|
+
|
|
145
|
+
// Get exactly one message or throw BadGatewayError
|
|
146
|
+
const message = getSingletonMessage(event);
|
|
55
147
|
```
|
|
56
148
|
|
|
57
|
-
##
|
|
149
|
+
## S3 Operations
|
|
58
150
|
|
|
59
|
-
|
|
60
|
-
1. Environment variables (`AWS_ACCESS_KEY_ID`, etc.)
|
|
61
|
-
2. `~/.aws/credentials` and `~/.aws/config`
|
|
62
|
-
3. SSO sessions via `aws sso login`
|
|
151
|
+
### getS3FileBuffer
|
|
63
152
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
153
|
+
Fetch a file from S3 as a Buffer:
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { getS3FileBuffer } from "@jaypie/aws";
|
|
67
157
|
|
|
68
|
-
|
|
69
|
-
|
|
158
|
+
const buffer = await getS3FileBuffer({
|
|
159
|
+
bucket: process.env.CDK_ENV_BUCKET,
|
|
160
|
+
key: "documents/report.pdf",
|
|
161
|
+
});
|
|
70
162
|
```
|
|
71
163
|
|
|
72
|
-
##
|
|
164
|
+
## Textract
|
|
73
165
|
|
|
74
|
-
|
|
166
|
+
### Document Processing
|
|
75
167
|
|
|
76
168
|
```typescript
|
|
77
|
-
import {
|
|
169
|
+
import { sendTextractJob, getTextractJob } from "@jaypie/aws";
|
|
78
170
|
|
|
79
|
-
//
|
|
80
|
-
const
|
|
171
|
+
// Start async job
|
|
172
|
+
const { JobId } = await sendTextractJob({
|
|
173
|
+
bucket: process.env.CDK_ENV_BUCKET,
|
|
174
|
+
key: "documents/scan.pdf",
|
|
175
|
+
});
|
|
81
176
|
|
|
82
|
-
//
|
|
83
|
-
|
|
177
|
+
// Later, retrieve results
|
|
178
|
+
const results = await getTextractJob(JobId);
|
|
84
179
|
```
|
|
85
180
|
|
|
86
|
-
## Environment
|
|
87
|
-
|
|
88
|
-
Use CDK environment variables in Lambda:
|
|
181
|
+
## Environment Variables
|
|
89
182
|
|
|
90
183
|
| Variable | Description |
|
|
91
184
|
|----------|-------------|
|
|
92
|
-
| `
|
|
93
|
-
| `
|
|
185
|
+
| `AWS_SESSION_TOKEN` | Required for secrets access in Lambda |
|
|
186
|
+
| `CDK_ENV_BUCKET` | Default S3 bucket name |
|
|
187
|
+
| `CDK_ENV_QUEUE_URL` | Default SQS queue URL |
|
|
94
188
|
| `CDK_ENV_SNS_TOPIC_ARN` | SNS topic ARN |
|
|
189
|
+
| `CDK_ENV_SNS_ROLE_ARN` | SNS role ARN |
|
|
190
|
+
| `PROJECT_KEY` | Used for FIFO queue message group ID |
|
|
95
191
|
|
|
96
|
-
##
|
|
192
|
+
## Credential Management
|
|
97
193
|
|
|
98
|
-
|
|
194
|
+
### Local Development
|
|
195
|
+
|
|
196
|
+
Configure credentials via environment or files:
|
|
99
197
|
|
|
100
198
|
```bash
|
|
101
199
|
# Set default profile
|
|
102
200
|
export AWS_PROFILE=development
|
|
103
201
|
|
|
104
|
-
# Or
|
|
105
|
-
|
|
202
|
+
# Or use named profiles
|
|
203
|
+
export AWS_PROFILE=production
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Credential chain priority:
|
|
207
|
+
1. Environment variables (`AWS_ACCESS_KEY_ID`, etc.)
|
|
208
|
+
2. `~/.aws/credentials` and `~/.aws/config`
|
|
209
|
+
3. SSO sessions via `aws sso login`
|
|
210
|
+
|
|
211
|
+
### Lambda Runtime
|
|
212
|
+
|
|
213
|
+
Lambda functions automatically receive credentials via IAM role. Use CDK to grant permissions:
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
import { JaypieLambda } from "@jaypie/constructs";
|
|
217
|
+
|
|
218
|
+
const handler = new JaypieLambda(this, "Handler", {
|
|
219
|
+
entry: "src/handler.ts",
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// Grant S3 access
|
|
223
|
+
bucket.grantReadWrite(handler);
|
|
224
|
+
|
|
225
|
+
// Grant SQS access
|
|
226
|
+
queue.grantSendMessages(handler);
|
|
227
|
+
|
|
228
|
+
// Grant Secrets Manager access
|
|
229
|
+
secret.grantRead(handler);
|
|
106
230
|
```
|
|
107
231
|
|
|
232
|
+
## Error Handling
|
|
233
|
+
|
|
234
|
+
Handle AWS errors with Jaypie patterns:
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
import { getEnvSecret } from "@jaypie/aws";
|
|
238
|
+
import { ConfigurationError, log } from "jaypie";
|
|
239
|
+
|
|
240
|
+
async function getApiKey() {
|
|
241
|
+
try {
|
|
242
|
+
return await getEnvSecret("API_KEY");
|
|
243
|
+
} catch (error) {
|
|
244
|
+
log.error("Failed to retrieve API key", { error });
|
|
245
|
+
throw new ConfigurationError("API key not configured");
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Testing
|
|
251
|
+
|
|
252
|
+
Mock AWS functions in tests:
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
import { getEnvSecret, sendMessage } from "@jaypie/testkit/mock";
|
|
256
|
+
import { vi } from "vitest";
|
|
257
|
+
|
|
258
|
+
vi.mock("@jaypie/aws");
|
|
259
|
+
|
|
260
|
+
describe("Handler", () => {
|
|
261
|
+
it("sends message to queue", async () => {
|
|
262
|
+
vi.mocked(sendMessage).mockResolvedValue({ MessageId: "123" });
|
|
263
|
+
|
|
264
|
+
await handler({ documentId: "doc-123" });
|
|
265
|
+
|
|
266
|
+
expect(sendMessage).toHaveBeenCalledWith(
|
|
267
|
+
expect.objectContaining({ documentId: "doc-123" })
|
|
268
|
+
);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
it("fetches secret from environment", async () => {
|
|
272
|
+
vi.mocked(getEnvSecret).mockResolvedValue("test-api-key");
|
|
273
|
+
|
|
274
|
+
const key = await getApiKey();
|
|
275
|
+
|
|
276
|
+
expect(key).toBe("test-api-key");
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
```
|