eoapi-cdk 8.1.1 → 8.2.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/.jsii +594 -26
- package/lib/bastion-host/index.js +1 -1
- package/lib/database/index.d.ts +1 -0
- package/lib/database/index.js +5 -5
- package/lib/index.d.ts +2 -0
- package/lib/index.js +3 -1
- package/lib/ingestor-api/index.js +1 -1
- package/lib/stac-api/index.js +1 -1
- package/lib/stac-browser/index.js +1 -1
- package/lib/stac-item-loader/index.d.ts +322 -0
- package/lib/stac-item-loader/index.js +251 -0
- package/lib/stac-item-loader/runtime/Dockerfile +18 -0
- package/lib/stac-item-loader/runtime/pyproject.toml +17 -0
- package/lib/stac-item-loader/runtime/src/stac_item_loader/handler.py +241 -0
- package/lib/stactools-item-generator/index.d.ts +243 -0
- package/lib/stactools-item-generator/index.js +204 -0
- package/lib/stactools-item-generator/runtime/Dockerfile +20 -0
- package/lib/stactools-item-generator/runtime/pyproject.toml +16 -0
- package/lib/stactools-item-generator/runtime/src/stactools_item_generator/__init__.py +2 -0
- package/lib/stactools-item-generator/runtime/src/stactools_item_generator/handler.py +176 -0
- package/lib/stactools-item-generator/runtime/src/stactools_item_generator/item.py +77 -0
- package/lib/tipg-api/index.js +1 -1
- package/lib/titiler-pgstac-api/index.js +1 -1
- package/package.json +1 -1
- package/pyproject.toml +45 -0
- package/uv.lock +1065 -0
- package/.devcontainer/devcontainer.json +0 -4
- package/.github/pull_request_template.md +0 -4
- package/.github/workflows/build.yaml +0 -73
- package/.github/workflows/build_and_release.yaml +0 -13
- package/.github/workflows/conventional-pr.yaml +0 -26
- package/.github/workflows/deploy.yaml +0 -84
- package/.github/workflows/distribute.yaml +0 -46
- package/.github/workflows/docs.yaml +0 -26
- package/.github/workflows/lint.yaml +0 -26
- package/.github/workflows/tox.yaml +0 -26
- package/.nvmrc +0 -1
- package/.pre-commit-config.yaml +0 -23
- package/CHANGELOG.md +0 -471
- package/diagrams/bastion_diagram.excalidraw +0 -1416
- package/diagrams/bastion_diagram.png +0 -0
- package/diagrams/ingestor_diagram.excalidraw +0 -2274
- package/diagrams/ingestor_diagram.png +0 -0
- package/integration_tests/cdk/README.md +0 -55
- package/integration_tests/cdk/app.py +0 -186
- package/integration_tests/cdk/cdk.json +0 -32
- package/integration_tests/cdk/config.py +0 -52
- package/integration_tests/cdk/package-lock.json +0 -42
- package/integration_tests/cdk/package.json +0 -7
- package/integration_tests/cdk/requirements.txt +0 -7
- package/lib/database/lambda/package-lock.json +0 -1324
- package/lib/ingestor-api/runtime/tests/conftest.py +0 -270
- package/lib/ingestor-api/runtime/tests/test_collection.py +0 -87
- package/lib/ingestor-api/runtime/tests/test_collection_endpoint.py +0 -41
- package/lib/ingestor-api/runtime/tests/test_ingestor.py +0 -60
- package/lib/ingestor-api/runtime/tests/test_registration.py +0 -207
- package/lib/ingestor-api/runtime/tests/test_utils.py +0 -35
- package/lib/ingestor-api/runtime/tests/test_validators.py +0 -164
- package/ruff.toml +0 -23
- package/tox.ini +0 -16
- package/tsconfig.tsbuildinfo +0 -1
- /package/lib/{ingestor-api/runtime/tests → stac-item-loader/runtime/src/stac_item_loader}/__init__.py +0 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.StactoolsItemGenerator = void 0;
|
|
5
|
+
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
6
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
7
|
+
const constructs_1 = require("constructs");
|
|
8
|
+
const aws_ecr_assets_1 = require("aws-cdk-lib/aws-ecr-assets");
|
|
9
|
+
const path = require("path");
|
|
10
|
+
/**
|
|
11
|
+
* AWS CDK Construct for STAC Item Generation Infrastructure
|
|
12
|
+
*
|
|
13
|
+
* The StactoolsItemGenerator creates a serverless, event-driven system for generating
|
|
14
|
+
* STAC (SpatioTemporal Asset Catalog) items from source data. This construct
|
|
15
|
+
* implements the first phase of a two-stage ingestion pipeline that transforms
|
|
16
|
+
* raw geospatial data into standardized STAC metadata.
|
|
17
|
+
*
|
|
18
|
+
* ## Architecture Overview
|
|
19
|
+
*
|
|
20
|
+
* This construct creates the following AWS resources:
|
|
21
|
+
* - **SNS Topic**: Entry point for triggering item generation workflows
|
|
22
|
+
* - **SQS Queue**: Buffers generation requests (120-second visibility timeout)
|
|
23
|
+
* - **Dead Letter Queue**: Captures failed messages after 5 processing attempts
|
|
24
|
+
* - **Lambda Function**: Containerized function that generates STAC items using stactools
|
|
25
|
+
*
|
|
26
|
+
* ## Data Flow
|
|
27
|
+
*
|
|
28
|
+
* 1. External systems publish ItemRequest messages to the SNS topic with metadata about assets
|
|
29
|
+
* 2. The SQS queue buffers these messages and triggers the Lambda function
|
|
30
|
+
* 3. The Lambda function:
|
|
31
|
+
* - Uses `uvx` to install the required stactools package
|
|
32
|
+
* - Executes the `create-item` CLI command with provided arguments
|
|
33
|
+
* - Publishes generated STAC items to the ItemLoad topic
|
|
34
|
+
* 4. Failed processing attempts are sent to the dead letter queue
|
|
35
|
+
*
|
|
36
|
+
* ## Operational Characteristics
|
|
37
|
+
*
|
|
38
|
+
* - **Scalability**: Lambda scales automatically based on queue depth (up to maxConcurrency)
|
|
39
|
+
* - **Flexibility**: Supports any stactools package through dynamic installation
|
|
40
|
+
* - **Reliability**: Dead letter queue captures failed generation attempts
|
|
41
|
+
* - **Isolation**: Each generation task runs in a fresh container environment
|
|
42
|
+
* - **Observability**: CloudWatch logs retained for one week
|
|
43
|
+
*
|
|
44
|
+
* ## Message Schema
|
|
45
|
+
*
|
|
46
|
+
* The function expects messages matching the ItemRequest model:
|
|
47
|
+
*
|
|
48
|
+
* ```json
|
|
49
|
+
* {
|
|
50
|
+
* "package_name": "stactools-glad-global-forest-change",
|
|
51
|
+
* "group_name": "gladglobalforestchange",
|
|
52
|
+
* "create_item_args": [
|
|
53
|
+
* "https://example.com/data.tif"
|
|
54
|
+
* ],
|
|
55
|
+
* "collection_id": "glad-global-forest-change-1.11"
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* ## Usage Example
|
|
60
|
+
*
|
|
61
|
+
* ```typescript
|
|
62
|
+
* // Create item loader first (or get existing topic ARN)
|
|
63
|
+
* const loader = new StacItemLoader(this, 'ItemLoader', {
|
|
64
|
+
* pgstacDb: database
|
|
65
|
+
* });
|
|
66
|
+
*
|
|
67
|
+
* // Create item generator that feeds the loader
|
|
68
|
+
* const generator = new StactoolsItemGenerator(this, 'ItemGenerator', {
|
|
69
|
+
* itemLoadTopicArn: loader.topic.topicArn,
|
|
70
|
+
* lambdaTimeoutSeconds: 120, // Allow time for package installation
|
|
71
|
+
* maxConcurrency: 100, // Control parallel processing
|
|
72
|
+
* batchSize: 10 // Process 10 requests per invocation
|
|
73
|
+
* });
|
|
74
|
+
*
|
|
75
|
+
* // Grant permission to publish to the loader topic
|
|
76
|
+
* loader.topic.grantPublish(generator.lambdaFunction);
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* ## Publishing Generation Requests
|
|
80
|
+
*
|
|
81
|
+
* Send messages to the generator topic to trigger item creation:
|
|
82
|
+
*
|
|
83
|
+
* ```bash
|
|
84
|
+
* aws sns publish --topic-arn $ITEM_GEN_TOPIC --message '{
|
|
85
|
+
* "package_name": "stactools-glad-global-forest-change",
|
|
86
|
+
* "group_name": "gladglobalforestchange",
|
|
87
|
+
* "create_item_args": [
|
|
88
|
+
* "https://storage.googleapis.com/earthenginepartners-hansen/GFC-2023-v1.11/Hansen_GFC-2023-v1.11_gain_40N_080W.tif"
|
|
89
|
+
* ],
|
|
90
|
+
* "collection_id": "glad-global-forest-change-1.11"
|
|
91
|
+
* }'
|
|
92
|
+
* ```
|
|
93
|
+
*
|
|
94
|
+
* ## Batch Processing Example
|
|
95
|
+
*
|
|
96
|
+
* For processing many assets, you can loop through URLs:
|
|
97
|
+
*
|
|
98
|
+
* ```bash
|
|
99
|
+
* while IFS= read -r url; do
|
|
100
|
+
* aws sns publish --topic-arn "$ITEM_GEN_TOPIC" --message "{
|
|
101
|
+
* \"package_name\": \"stactools-glad-glclu2020\",
|
|
102
|
+
* \"group_name\": \"gladglclu2020\",
|
|
103
|
+
* \"create_item_args\": [\"$url\"]
|
|
104
|
+
* }"
|
|
105
|
+
* done < urls.txt
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* ## Monitoring and Troubleshooting
|
|
109
|
+
*
|
|
110
|
+
* - Monitor Lambda logs: `/aws/lambda/{FunctionName}`
|
|
111
|
+
* - Check dead letter queue for failed generation attempts
|
|
112
|
+
* - Use CloudWatch metrics to track processing rates and errors
|
|
113
|
+
* - Failed items can be replayed from the dead letter queue
|
|
114
|
+
*
|
|
115
|
+
* ## Supported Stactools Packages
|
|
116
|
+
*
|
|
117
|
+
* Any package available on PyPI that follows the stactools plugin pattern
|
|
118
|
+
* can be used. Examples include:
|
|
119
|
+
* - `stactools-glad-global-forest-change`
|
|
120
|
+
* - `stactools-glad-glclu2020`
|
|
121
|
+
* - `stactools-landsat`
|
|
122
|
+
* - `stactools-sentinel2`
|
|
123
|
+
*
|
|
124
|
+
* @see {@link https://github.com/stactools-packages} for available stactools packages
|
|
125
|
+
* @see {@link https://stactools.readthedocs.io/} for stactools documentation
|
|
126
|
+
*/
|
|
127
|
+
class StactoolsItemGenerator extends constructs_1.Construct {
|
|
128
|
+
constructor(scope, id, props) {
|
|
129
|
+
super(scope, id);
|
|
130
|
+
const timeoutSeconds = props.lambdaTimeoutSeconds ?? 120;
|
|
131
|
+
const lambdaRuntime = props.lambdaRuntime ?? aws_cdk_lib_1.aws_lambda.Runtime.PYTHON_3_11;
|
|
132
|
+
// Create dead letter queue
|
|
133
|
+
this.deadLetterQueue = new aws_cdk_lib_1.aws_sqs.Queue(this, "DeadLetterQueue", {
|
|
134
|
+
retentionPeriod: aws_cdk_lib_1.Duration.days(14),
|
|
135
|
+
});
|
|
136
|
+
// Create main queue
|
|
137
|
+
this.queue = new aws_cdk_lib_1.aws_sqs.Queue(this, "Queue", {
|
|
138
|
+
visibilityTimeout: aws_cdk_lib_1.Duration.seconds(timeoutSeconds + 10),
|
|
139
|
+
encryption: aws_cdk_lib_1.aws_sqs.QueueEncryption.SQS_MANAGED,
|
|
140
|
+
deadLetterQueue: {
|
|
141
|
+
maxReceiveCount: 5,
|
|
142
|
+
queue: this.deadLetterQueue,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
// Create SNS topic
|
|
146
|
+
this.topic = new aws_cdk_lib_1.aws_sns.Topic(this, "Topic", {
|
|
147
|
+
displayName: `${id}-ItemGenTopic`,
|
|
148
|
+
});
|
|
149
|
+
// Subscribe the queue to the topic
|
|
150
|
+
this.topic.addSubscription(new aws_cdk_lib_1.aws_sns_subscriptions.SqsSubscription(this.queue));
|
|
151
|
+
// Create the lambda function
|
|
152
|
+
this.lambdaFunction = new aws_cdk_lib_1.aws_lambda.DockerImageFunction(this, "Function", {
|
|
153
|
+
code: aws_cdk_lib_1.aws_lambda.DockerImageCode.fromImageAsset(path.join(__dirname, ".."), {
|
|
154
|
+
file: "stactools-item-generator/runtime/Dockerfile",
|
|
155
|
+
platform: aws_ecr_assets_1.Platform.LINUX_AMD64,
|
|
156
|
+
buildArgs: {
|
|
157
|
+
PYTHON_VERSION: lambdaRuntime.toString().replace("python", ""),
|
|
158
|
+
},
|
|
159
|
+
}),
|
|
160
|
+
memorySize: props.memorySize ?? 1024,
|
|
161
|
+
timeout: aws_cdk_lib_1.Duration.seconds(timeoutSeconds),
|
|
162
|
+
logRetention: aws_cdk_lib_1.aws_logs.RetentionDays.ONE_WEEK,
|
|
163
|
+
environment: {
|
|
164
|
+
ITEM_LOAD_TOPIC_ARN: props.itemLoadTopicArn,
|
|
165
|
+
LOG_LEVEL: "INFO",
|
|
166
|
+
...props.environment,
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
// Add SQS event source to the lambda
|
|
170
|
+
this.lambdaFunction.addEventSource(new aws_cdk_lib_1.aws_lambda_event_sources.SqsEventSource(this.queue, {
|
|
171
|
+
batchSize: props.batchSize ?? 10,
|
|
172
|
+
reportBatchItemFailures: true,
|
|
173
|
+
maxConcurrency: props.maxConcurrency ?? 100,
|
|
174
|
+
}));
|
|
175
|
+
// Grant permissions to publish to the item load topic
|
|
176
|
+
// Note: This will be granted externally since we only have the ARN
|
|
177
|
+
// The consuming construct should handle this permission
|
|
178
|
+
// Create outputs
|
|
179
|
+
new aws_cdk_lib_1.CfnOutput(this, "TopicArn", {
|
|
180
|
+
value: this.topic.topicArn,
|
|
181
|
+
description: "ARN of the StactoolsItemGenerator SNS Topic",
|
|
182
|
+
exportName: "stactools-item-generator-topic-arn",
|
|
183
|
+
});
|
|
184
|
+
new aws_cdk_lib_1.CfnOutput(this, "QueueUrl", {
|
|
185
|
+
value: this.queue.queueUrl,
|
|
186
|
+
description: "URL of the StactoolsItemGenerator SQS Queue",
|
|
187
|
+
exportName: "stactools-item-generator-queue-url",
|
|
188
|
+
});
|
|
189
|
+
new aws_cdk_lib_1.CfnOutput(this, "DeadLetterQueueUrl", {
|
|
190
|
+
value: this.deadLetterQueue.queueUrl,
|
|
191
|
+
description: "URL of the StactoolsItemGenerator Dead Letter Queue",
|
|
192
|
+
exportName: "stactools-item-generator-deadletter-queue-url",
|
|
193
|
+
});
|
|
194
|
+
new aws_cdk_lib_1.CfnOutput(this, "FunctionName", {
|
|
195
|
+
value: this.lambdaFunction.functionName,
|
|
196
|
+
description: "Name of the StactoolsItemGenerator Lambda Function",
|
|
197
|
+
exportName: "stactools-item-generator-function-name",
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
exports.StactoolsItemGenerator = StactoolsItemGenerator;
|
|
202
|
+
_a = JSII_RTTI_SYMBOL_1;
|
|
203
|
+
StactoolsItemGenerator[_a] = { fqn: "eoapi-cdk.StactoolsItemGenerator", version: "8.2.0" };
|
|
204
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZDQVNxQjtBQUNyQiwyQ0FBdUM7QUFDdkMsK0RBQXNEO0FBQ3RELDZCQUE2QjtBQWlHN0I7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0hHO0FBQ0gsTUFBYSxzQkFBdUIsU0FBUSxzQkFBUztJQW9DbkQsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUFrQztRQUMxRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLE1BQU0sY0FBYyxHQUFHLEtBQUssQ0FBQyxvQkFBb0IsSUFBSSxHQUFHLENBQUM7UUFDekQsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLGFBQWEsSUFBSSx3QkFBTSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUM7UUFFeEUsMkJBQTJCO1FBQzNCLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxxQkFBRyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsaUJBQWlCLEVBQUU7WUFDNUQsZUFBZSxFQUFFLHNCQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztTQUNuQyxDQUFDLENBQUM7UUFFSCxvQkFBb0I7UUFDcEIsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLHFCQUFHLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUU7WUFDeEMsaUJBQWlCLEVBQUUsc0JBQVEsQ0FBQyxPQUFPLENBQUMsY0FBYyxHQUFHLEVBQUUsQ0FBQztZQUN4RCxVQUFVLEVBQUUscUJBQUcsQ0FBQyxlQUFlLENBQUMsV0FBVztZQUMzQyxlQUFlLEVBQUU7Z0JBQ2YsZUFBZSxFQUFFLENBQUM7Z0JBQ2xCLEtBQUssRUFBRSxJQUFJLENBQUMsZUFBZTthQUM1QjtTQUNGLENBQUMsQ0FBQztRQUVILG1CQUFtQjtRQUNuQixJQUFJLENBQUMsS0FBSyxHQUFHLElBQUkscUJBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLE9BQU8sRUFBRTtZQUN4QyxXQUFXLEVBQUUsR0FBRyxFQUFFLGVBQWU7U0FDbEMsQ0FBQyxDQUFDO1FBRUgsbUNBQW1DO1FBQ25DLElBQUksQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUN4QixJQUFJLG1DQUFnQixDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQ2pELENBQUM7UUFFRiw2QkFBNkI7UUFDN0IsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLHdCQUFNLENBQUMsbUJBQW1CLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRTtZQUNyRSxJQUFJLEVBQUUsd0JBQU0sQ0FBQyxlQUFlLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxFQUFFO2dCQUN0RSxJQUFJLEVBQUUsNkNBQTZDO2dCQUNuRCxRQUFRLEVBQUUseUJBQVEsQ0FBQyxXQUFXO2dCQUM5QixTQUFTLEVBQUU7b0JBQ1QsY0FBYyxFQUFFLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztpQkFDL0Q7YUFDRixDQUFDO1lBQ0YsVUFBVSxFQUFFLEtBQUssQ0FBQyxVQUFVLElBQUksSUFBSTtZQUNwQyxPQUFPLEVBQUUsc0JBQVEsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDO1lBQ3pDLFlBQVksRUFBRSxzQkFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRO1lBQ3pDLFdBQVcsRUFBRTtnQkFDWCxtQkFBbUIsRUFBRSxLQUFLLENBQUMsZ0JBQWdCO2dCQUMzQyxTQUFTLEVBQUUsTUFBTTtnQkFDakIsR0FBRyxLQUFLLENBQUMsV0FBVzthQUNyQjtTQUNGLENBQUMsQ0FBQztRQUVILHFDQUFxQztRQUNyQyxJQUFJLENBQUMsY0FBYyxDQUFDLGNBQWMsQ0FDaEMsSUFBSSxzQ0FBa0IsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRTtZQUNoRCxTQUFTLEVBQUUsS0FBSyxDQUFDLFNBQVMsSUFBSSxFQUFFO1lBQ2hDLHVCQUF1QixFQUFFLElBQUk7WUFDN0IsY0FBYyxFQUFFLEtBQUssQ0FBQyxjQUFjLElBQUksR0FBRztTQUM1QyxDQUFDLENBQ0gsQ0FBQztRQUVGLHNEQUFzRDtRQUN0RCxtRUFBbUU7UUFDbkUsd0RBQXdEO1FBRXhELGlCQUFpQjtRQUNqQixJQUFJLHVCQUFTLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRTtZQUM5QixLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRO1lBQzFCLFdBQVcsRUFBRSw2Q0FBNkM7WUFDMUQsVUFBVSxFQUFFLG9DQUFvQztTQUNqRCxDQUFDLENBQUM7UUFFSCxJQUFJLHVCQUFTLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRTtZQUM5QixLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRO1lBQzFCLFdBQVcsRUFBRSw2Q0FBNkM7WUFDMUQsVUFBVSxFQUFFLG9DQUFvQztTQUNqRCxDQUFDLENBQUM7UUFFSCxJQUFJLHVCQUFTLENBQUMsSUFBSSxFQUFFLG9CQUFvQixFQUFFO1lBQ3hDLEtBQUssRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLFFBQVE7WUFDcEMsV0FBVyxFQUFFLHFEQUFxRDtZQUNsRSxVQUFVLEVBQUUsK0NBQStDO1NBQzVELENBQUMsQ0FBQztRQUVILElBQUksdUJBQVMsQ0FBQyxJQUFJLEVBQUUsY0FBYyxFQUFFO1lBQ2xDLEtBQUssRUFBRSxJQUFJLENBQUMsY0FBYyxDQUFDLFlBQVk7WUFDdkMsV0FBVyxFQUFFLG9EQUFvRDtZQUNqRSxVQUFVLEVBQUUsd0NBQXdDO1NBQ3JELENBQUMsQ0FBQztJQUNMLENBQUM7O0FBM0hILHdEQTRIQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIGF3c19sYW1iZGEgYXMgbGFtYmRhLFxuICBhd3Nfc3FzIGFzIHNxcyxcbiAgYXdzX3NucyBhcyBzbnMsXG4gIGF3c19zbnNfc3Vic2NyaXB0aW9ucyBhcyBzbnNTdWJzY3JpcHRpb25zLFxuICBhd3NfbGFtYmRhX2V2ZW50X3NvdXJjZXMgYXMgbGFtYmRhRXZlbnRTb3VyY2VzLFxuICBhd3NfbG9ncyBhcyBsb2dzLFxuICBEdXJhdGlvbixcbiAgQ2ZuT3V0cHV0LFxufSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgeyBQbGF0Zm9ybSB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZWNyLWFzc2V0c1wiO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tIFwicGF0aFwiO1xuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gcHJvcGVydGllcyBmb3IgdGhlIFN0YWN0b29sc0l0ZW1HZW5lcmF0b3IgY29uc3RydWN0LlxuICpcbiAqIFRoZSBTdGFjdG9vbHNJdGVtR2VuZXJhdG9yIGlzIHBhcnQgb2YgYSB0d28tcGhhc2Ugc2VydmVybGVzcyBTVEFDIGluZ2VzdGlvbiBwaXBlbGluZVxuICogdGhhdCBnZW5lcmF0ZXMgU1RBQyBpdGVtcyBmcm9tIHNvdXJjZSBkYXRhLiBUaGlzIGNvbnN0cnVjdCBjcmVhdGVzIHRoZVxuICogaW5mcmFzdHJ1Y3R1cmUgZm9yIHRoZSBmaXJzdCBwaGFzZSBvZiB0aGUgcGlwZWxpbmUgLSBwcm9jZXNzaW5nIG1ldGFkYXRhXG4gKiBhYm91dCBhc3NldHMgYW5kIHRyYW5zZm9ybWluZyB0aGVtIGludG8gc3RhbmRhcmRpemVkIFNUQUMgaXRlbXMuXG4gKlxuICogQGV4YW1wbGVcbiAqIGNvbnN0IGdlbmVyYXRvciA9IG5ldyBTdGFjdG9vbHNJdGVtR2VuZXJhdG9yKHRoaXMsICdJdGVtR2VuZXJhdG9yJywge1xuICogICBpdGVtTG9hZFRvcGljQXJuOiBsb2FkZXIudG9waWMudG9waWNBcm4sXG4gKiAgIGxhbWJkYVRpbWVvdXRTZWNvbmRzOiAxMjAsXG4gKiAgIG1heENvbmN1cnJlbmN5OiAxMDAsXG4gKiAgIGJhdGNoU2l6ZTogMTBcbiAqIH0pO1xuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0YWN0b29sc0l0ZW1HZW5lcmF0b3JQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgbGFtYmRhIHJ1bnRpbWUgdG8gdXNlIGZvciB0aGUgaXRlbSBnZW5lcmF0aW9uIGZ1bmN0aW9uLlxuICAgKlxuICAgKiBUaGUgZnVuY3Rpb24gaXMgY29udGFpbmVyaXplZCB1c2luZyBEb2NrZXIgYW5kIGNhbiBhY2NvbW1vZGF0ZSB2YXJpb3VzXG4gICAqIHN0YWN0b29scyBwYWNrYWdlcy4gVGhlIHJ1bnRpbWUgdmVyc2lvbiBzaG91bGQgYmUgY29tcGF0aWJsZSB3aXRoIHRoZVxuICAgKiBwYWNrYWdlcyB5b3UgcGxhbiB0byB1c2UgZm9yIFNUQUMgaXRlbSBnZW5lcmF0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCBsYW1iZGEuUnVudGltZS5QWVRIT05fM18xMVxuICAgKi9cbiAgcmVhZG9ubHkgbGFtYmRhUnVudGltZT86IGxhbWJkYS5SdW50aW1lO1xuXG4gIC8qKlxuICAgKiBUaGUgdGltZW91dCBmb3IgdGhlIGl0ZW0gZ2VuZXJhdGlvbiBsYW1iZGEgaW4gc2Vjb25kcy5cbiAgICpcbiAgICogVGhpcyBzaG91bGQgYWNjb21tb2RhdGUgdGhlIHRpbWUgbmVlZGVkIHRvOlxuICAgKiAtIEluc3RhbGwgc3RhY3Rvb2xzIHBhY2thZ2VzIHVzaW5nIHV2eFxuICAgKiAtIERvd25sb2FkIGFuZCBwcm9jZXNzIHNvdXJjZSBkYXRhXG4gICAqIC0gR2VuZXJhdGUgU1RBQyBtZXRhZGF0YVxuICAgKiAtIFB1Ymxpc2ggcmVzdWx0cyB0byBTTlNcbiAgICpcbiAgICogVGhlIFNRUyB2aXNpYmlsaXR5IHRpbWVvdXQgd2lsbCBiZSBzZXQgdG8gdGhpcyB2YWx1ZSBwbHVzIDEwIHNlY29uZHMuXG4gICAqXG4gICAqIEBkZWZhdWx0IDEyMFxuICAgKi9cbiAgcmVhZG9ubHkgbGFtYmRhVGltZW91dFNlY29uZHM/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIE1lbW9yeSBzaXplIGZvciB0aGUgbGFtYmRhIGZ1bmN0aW9uIGluIE1CLlxuICAgKlxuICAgKiBIaWdoZXIgbWVtb3J5IGFsbG9jYXRpb24gbWF5IGJlIG5lZWRlZCBmb3IgcHJvY2Vzc2luZyBsYXJnZSBnZW9zcGF0aWFsXG4gICAqIGRhdGFzZXRzIG9yIHdoZW4gc3RhY3Rvb2xzIHBhY2thZ2VzIGhhdmUgaGlnaCBtZW1vcnkgcmVxdWlyZW1lbnRzLlxuICAgKiBNb3JlIG1lbW9yeSBhbHNvIHByb3ZpZGVzIHByb3BvcnRpb25hbGx5IG1vcmUgQ1BVIHBvd2VyLlxuICAgKlxuICAgKiBAZGVmYXVsdCAxMDI0XG4gICAqL1xuICByZWFkb25seSBtZW1vcnlTaXplPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBNYXhpbXVtIG51bWJlciBvZiBjb25jdXJyZW50IGV4ZWN1dGlvbnMuXG4gICAqXG4gICAqIFRoaXMgY29udHJvbHMgaG93IG1hbnkgaXRlbSBnZW5lcmF0aW9uIHRhc2tzIGNhbiBydW4gc2ltdWx0YW5lb3VzbHkuXG4gICAqIEhpZ2hlciBjb25jdXJyZW5jeSBlbmFibGVzIGZhc3RlciBwcm9jZXNzaW5nIG9mIGxhcmdlIGJhdGNoZXMgYnV0XG4gICAqIG1heSBzdHJhaW4gZG93bnN0cmVhbSBzeXN0ZW1zIG9yIGV4dGVybmFsIGRhdGEgc291cmNlcy5cbiAgICpcbiAgICogQGRlZmF1bHQgMTAwXG4gICAqL1xuICByZWFkb25seSBtYXhDb25jdXJyZW5jeT86IG51bWJlcjtcblxuICAvKipcbiAgICogU1FTIGJhdGNoIHNpemUgZm9yIGxhbWJkYSBldmVudCBzb3VyY2UuXG4gICAqXG4gICAqIFRoaXMgZGV0ZXJtaW5lcyBob3cgbWFueSBnZW5lcmF0aW9uIHJlcXVlc3RzIGFyZSBwcm9jZXNzZWQgdG9nZXRoZXJcbiAgICogaW4gYSBzaW5nbGUgbGFtYmRhIGludm9jYXRpb24uIFVubGlrZSB0aGUgbG9hZGVyLCBnZW5lcmF0aW9uIHR5cGljYWxseVxuICAgKiBwcm9jZXNzZXMgaXRlbXMgaW5kaXZpZHVhbGx5LCBzbyBzbWFsbGVyIGJhdGNoIHNpemVzIGFyZSBjb21tb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IDEwXG4gICAqL1xuICByZWFkb25seSBiYXRjaFNpemU/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEFkZGl0aW9uYWwgZW52aXJvbm1lbnQgdmFyaWFibGVzIGZvciB0aGUgbGFtYmRhIGZ1bmN0aW9uLlxuICAgKlxuICAgKiBUaGVzZSB3aWxsIGJlIG1lcmdlZCB3aXRoIGRlZmF1bHQgZW52aXJvbm1lbnQgdmFyaWFibGVzIGluY2x1ZGluZ1xuICAgKiBJVEVNX0xPQURfVE9QSUNfQVJOIGFuZCBMT0dfTEVWRUwuIFVzZSB0aGlzIGZvciBjdXN0b20gY29uZmlndXJhdGlvblxuICAgKiBvciB0byBwYXNzIGNyZWRlbnRpYWxzIGZvciBleHRlcm5hbCBkYXRhIHNvdXJjZXMuXG4gICAqL1xuICByZWFkb25seSBlbnZpcm9ubWVudD86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH07XG5cbiAgLyoqXG4gICAqIEFSTiBvZiB0aGUgU05TIHRvcGljIHRvIHB1Ymxpc2ggZ2VuZXJhdGVkIGl0ZW1zIHRvLlxuICAgKlxuICAgKiBUaGlzIGlzIHR5cGljYWxseSB0aGUgdG9waWMgZnJvbSBhIFN0YWNJdGVtTG9hZGVyIGNvbnN0cnVjdC5cbiAgICogR2VuZXJhdGVkIFNUQUMgaXRlbXMgd2lsbCBiZSBwdWJsaXNoZWQgaGVyZSBmb3IgZG93bnN0cmVhbVxuICAgKiBwcm9jZXNzaW5nIGFuZCBkYXRhYmFzZSBpbnNlcnRpb24uXG4gICAqL1xuICByZWFkb25seSBpdGVtTG9hZFRvcGljQXJuOiBzdHJpbmc7XG59XG5cbi8qKlxuICogQVdTIENESyBDb25zdHJ1Y3QgZm9yIFNUQUMgSXRlbSBHZW5lcmF0aW9uIEluZnJhc3RydWN0dXJlXG4gKlxuICogVGhlIFN0YWN0b29sc0l0ZW1HZW5lcmF0b3IgY3JlYXRlcyBhIHNlcnZlcmxlc3MsIGV2ZW50LWRyaXZlbiBzeXN0ZW0gZm9yIGdlbmVyYXRpbmdcbiAqIFNUQUMgKFNwYXRpb1RlbXBvcmFsIEFzc2V0IENhdGFsb2cpIGl0ZW1zIGZyb20gc291cmNlIGRhdGEuIFRoaXMgY29uc3RydWN0XG4gKiBpbXBsZW1lbnRzIHRoZSBmaXJzdCBwaGFzZSBvZiBhIHR3by1zdGFnZSBpbmdlc3Rpb24gcGlwZWxpbmUgdGhhdCB0cmFuc2Zvcm1zXG4gKiByYXcgZ2Vvc3BhdGlhbCBkYXRhIGludG8gc3RhbmRhcmRpemVkIFNUQUMgbWV0YWRhdGEuXG4gKlxuICogIyMgQXJjaGl0ZWN0dXJlIE92ZXJ2aWV3XG4gKlxuICogVGhpcyBjb25zdHJ1Y3QgY3JlYXRlcyB0aGUgZm9sbG93aW5nIEFXUyByZXNvdXJjZXM6XG4gKiAtICoqU05TIFRvcGljKio6IEVudHJ5IHBvaW50IGZvciB0cmlnZ2VyaW5nIGl0ZW0gZ2VuZXJhdGlvbiB3b3JrZmxvd3NcbiAqIC0gKipTUVMgUXVldWUqKjogQnVmZmVycyBnZW5lcmF0aW9uIHJlcXVlc3RzICgxMjAtc2Vjb25kIHZpc2liaWxpdHkgdGltZW91dClcbiAqIC0gKipEZWFkIExldHRlciBRdWV1ZSoqOiBDYXB0dXJlcyBmYWlsZWQgbWVzc2FnZXMgYWZ0ZXIgNSBwcm9jZXNzaW5nIGF0dGVtcHRzXG4gKiAtICoqTGFtYmRhIEZ1bmN0aW9uKio6IENvbnRhaW5lcml6ZWQgZnVuY3Rpb24gdGhhdCBnZW5lcmF0ZXMgU1RBQyBpdGVtcyB1c2luZyBzdGFjdG9vbHNcbiAqXG4gKiAjIyBEYXRhIEZsb3dcbiAqXG4gKiAxLiBFeHRlcm5hbCBzeXN0ZW1zIHB1Ymxpc2ggSXRlbVJlcXVlc3QgbWVzc2FnZXMgdG8gdGhlIFNOUyB0b3BpYyB3aXRoIG1ldGFkYXRhIGFib3V0IGFzc2V0c1xuICogMi4gVGhlIFNRUyBxdWV1ZSBidWZmZXJzIHRoZXNlIG1lc3NhZ2VzIGFuZCB0cmlnZ2VycyB0aGUgTGFtYmRhIGZ1bmN0aW9uXG4gKiAzLiBUaGUgTGFtYmRhIGZ1bmN0aW9uOlxuICogICAgLSBVc2VzIGB1dnhgIHRvIGluc3RhbGwgdGhlIHJlcXVpcmVkIHN0YWN0b29scyBwYWNrYWdlXG4gKiAgICAtIEV4ZWN1dGVzIHRoZSBgY3JlYXRlLWl0ZW1gIENMSSBjb21tYW5kIHdpdGggcHJvdmlkZWQgYXJndW1lbnRzXG4gKiAgICAtIFB1Ymxpc2hlcyBnZW5lcmF0ZWQgU1RBQyBpdGVtcyB0byB0aGUgSXRlbUxvYWQgdG9waWNcbiAqIDQuIEZhaWxlZCBwcm9jZXNzaW5nIGF0dGVtcHRzIGFyZSBzZW50IHRvIHRoZSBkZWFkIGxldHRlciBxdWV1ZVxuICpcbiAqICMjIE9wZXJhdGlvbmFsIENoYXJhY3RlcmlzdGljc1xuICpcbiAqIC0gKipTY2FsYWJpbGl0eSoqOiBMYW1iZGEgc2NhbGVzIGF1dG9tYXRpY2FsbHkgYmFzZWQgb24gcXVldWUgZGVwdGggKHVwIHRvIG1heENvbmN1cnJlbmN5KVxuICogLSAqKkZsZXhpYmlsaXR5Kio6IFN1cHBvcnRzIGFueSBzdGFjdG9vbHMgcGFja2FnZSB0aHJvdWdoIGR5bmFtaWMgaW5zdGFsbGF0aW9uXG4gKiAtICoqUmVsaWFiaWxpdHkqKjogRGVhZCBsZXR0ZXIgcXVldWUgY2FwdHVyZXMgZmFpbGVkIGdlbmVyYXRpb24gYXR0ZW1wdHNcbiAqIC0gKipJc29sYXRpb24qKjogRWFjaCBnZW5lcmF0aW9uIHRhc2sgcnVucyBpbiBhIGZyZXNoIGNvbnRhaW5lciBlbnZpcm9ubWVudFxuICogLSAqKk9ic2VydmFiaWxpdHkqKjogQ2xvdWRXYXRjaCBsb2dzIHJldGFpbmVkIGZvciBvbmUgd2Vla1xuICpcbiAqICMjIE1lc3NhZ2UgU2NoZW1hXG4gKlxuICogVGhlIGZ1bmN0aW9uIGV4cGVjdHMgbWVzc2FnZXMgbWF0Y2hpbmcgdGhlIEl0ZW1SZXF1ZXN0IG1vZGVsOlxuICpcbiAqIGBgYGpzb25cbiAqIHtcbiAqICAgXCJwYWNrYWdlX25hbWVcIjogXCJzdGFjdG9vbHMtZ2xhZC1nbG9iYWwtZm9yZXN0LWNoYW5nZVwiLFxuICogICBcImdyb3VwX25hbWVcIjogXCJnbGFkZ2xvYmFsZm9yZXN0Y2hhbmdlXCIsXG4gKiAgIFwiY3JlYXRlX2l0ZW1fYXJnc1wiOiBbXG4gKiAgICAgXCJodHRwczovL2V4YW1wbGUuY29tL2RhdGEudGlmXCJcbiAqICAgXSxcbiAqICAgXCJjb2xsZWN0aW9uX2lkXCI6IFwiZ2xhZC1nbG9iYWwtZm9yZXN0LWNoYW5nZS0xLjExXCJcbiAqIH1cbiAqIGBgYFxuICpcbiAqICMjIFVzYWdlIEV4YW1wbGVcbiAqXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBDcmVhdGUgaXRlbSBsb2FkZXIgZmlyc3QgKG9yIGdldCBleGlzdGluZyB0b3BpYyBBUk4pXG4gKiBjb25zdCBsb2FkZXIgPSBuZXcgU3RhY0l0ZW1Mb2FkZXIodGhpcywgJ0l0ZW1Mb2FkZXInLCB7XG4gKiAgIHBnc3RhY0RiOiBkYXRhYmFzZVxuICogfSk7XG4gKlxuICogLy8gQ3JlYXRlIGl0ZW0gZ2VuZXJhdG9yIHRoYXQgZmVlZHMgdGhlIGxvYWRlclxuICogY29uc3QgZ2VuZXJhdG9yID0gbmV3IFN0YWN0b29sc0l0ZW1HZW5lcmF0b3IodGhpcywgJ0l0ZW1HZW5lcmF0b3InLCB7XG4gKiAgIGl0ZW1Mb2FkVG9waWNBcm46IGxvYWRlci50b3BpYy50b3BpY0FybixcbiAqICAgbGFtYmRhVGltZW91dFNlY29uZHM6IDEyMCwgICAgLy8gQWxsb3cgdGltZSBmb3IgcGFja2FnZSBpbnN0YWxsYXRpb25cbiAqICAgbWF4Q29uY3VycmVuY3k6IDEwMCwgICAgICAgICAgLy8gQ29udHJvbCBwYXJhbGxlbCBwcm9jZXNzaW5nXG4gKiAgIGJhdGNoU2l6ZTogMTAgICAgICAgICAgICAgICAgIC8vIFByb2Nlc3MgMTAgcmVxdWVzdHMgcGVyIGludm9jYXRpb25cbiAqIH0pO1xuICpcbiAqIC8vIEdyYW50IHBlcm1pc3Npb24gdG8gcHVibGlzaCB0byB0aGUgbG9hZGVyIHRvcGljXG4gKiBsb2FkZXIudG9waWMuZ3JhbnRQdWJsaXNoKGdlbmVyYXRvci5sYW1iZGFGdW5jdGlvbik7XG4gKiBgYGBcbiAqXG4gKiAjIyBQdWJsaXNoaW5nIEdlbmVyYXRpb24gUmVxdWVzdHNcbiAqXG4gKiBTZW5kIG1lc3NhZ2VzIHRvIHRoZSBnZW5lcmF0b3IgdG9waWMgdG8gdHJpZ2dlciBpdGVtIGNyZWF0aW9uOlxuICpcbiAqIGBgYGJhc2hcbiAqIGF3cyBzbnMgcHVibGlzaCAtLXRvcGljLWFybiAkSVRFTV9HRU5fVE9QSUMgLS1tZXNzYWdlICd7XG4gKiAgIFwicGFja2FnZV9uYW1lXCI6IFwic3RhY3Rvb2xzLWdsYWQtZ2xvYmFsLWZvcmVzdC1jaGFuZ2VcIixcbiAqICAgXCJncm91cF9uYW1lXCI6IFwiZ2xhZGdsb2JhbGZvcmVzdGNoYW5nZVwiLFxuICogICBcImNyZWF0ZV9pdGVtX2FyZ3NcIjogW1xuICogICAgIFwiaHR0cHM6Ly9zdG9yYWdlLmdvb2dsZWFwaXMuY29tL2VhcnRoZW5naW5lcGFydG5lcnMtaGFuc2VuL0dGQy0yMDIzLXYxLjExL0hhbnNlbl9HRkMtMjAyMy12MS4xMV9nYWluXzQwTl8wODBXLnRpZlwiXG4gKiAgIF0sXG4gKiAgIFwiY29sbGVjdGlvbl9pZFwiOiBcImdsYWQtZ2xvYmFsLWZvcmVzdC1jaGFuZ2UtMS4xMVwiXG4gKiB9J1xuICogYGBgXG4gKlxuICogIyMgQmF0Y2ggUHJvY2Vzc2luZyBFeGFtcGxlXG4gKlxuICogRm9yIHByb2Nlc3NpbmcgbWFueSBhc3NldHMsIHlvdSBjYW4gbG9vcCB0aHJvdWdoIFVSTHM6XG4gKlxuICogYGBgYmFzaFxuICogd2hpbGUgSUZTPSByZWFkIC1yIHVybDsgZG9cbiAqICAgYXdzIHNucyBwdWJsaXNoIC0tdG9waWMtYXJuIFwiJElURU1fR0VOX1RPUElDXCIgLS1tZXNzYWdlIFwie1xuICogICAgIFxcXCJwYWNrYWdlX25hbWVcXFwiOiBcXFwic3RhY3Rvb2xzLWdsYWQtZ2xjbHUyMDIwXFxcIixcbiAqICAgICBcXFwiZ3JvdXBfbmFtZVxcXCI6IFxcXCJnbGFkZ2xjbHUyMDIwXFxcIixcbiAqICAgICBcXFwiY3JlYXRlX2l0ZW1fYXJnc1xcXCI6IFtcXFwiJHVybFxcXCJdXG4gKiAgIH1cIlxuICogZG9uZSA8IHVybHMudHh0XG4gKiBgYGBcbiAqXG4gKiAjIyBNb25pdG9yaW5nIGFuZCBUcm91Ymxlc2hvb3RpbmdcbiAqXG4gKiAtIE1vbml0b3IgTGFtYmRhIGxvZ3M6IGAvYXdzL2xhbWJkYS97RnVuY3Rpb25OYW1lfWBcbiAqIC0gQ2hlY2sgZGVhZCBsZXR0ZXIgcXVldWUgZm9yIGZhaWxlZCBnZW5lcmF0aW9uIGF0dGVtcHRzXG4gKiAtIFVzZSBDbG91ZFdhdGNoIG1ldHJpY3MgdG8gdHJhY2sgcHJvY2Vzc2luZyByYXRlcyBhbmQgZXJyb3JzXG4gKiAtIEZhaWxlZCBpdGVtcyBjYW4gYmUgcmVwbGF5ZWQgZnJvbSB0aGUgZGVhZCBsZXR0ZXIgcXVldWVcbiAqXG4gKiAjIyBTdXBwb3J0ZWQgU3RhY3Rvb2xzIFBhY2thZ2VzXG4gKlxuICogQW55IHBhY2thZ2UgYXZhaWxhYmxlIG9uIFB5UEkgdGhhdCBmb2xsb3dzIHRoZSBzdGFjdG9vbHMgcGx1Z2luIHBhdHRlcm5cbiAqIGNhbiBiZSB1c2VkLiBFeGFtcGxlcyBpbmNsdWRlOlxuICogLSBgc3RhY3Rvb2xzLWdsYWQtZ2xvYmFsLWZvcmVzdC1jaGFuZ2VgXG4gKiAtIGBzdGFjdG9vbHMtZ2xhZC1nbGNsdTIwMjBgXG4gKiAtIGBzdGFjdG9vbHMtbGFuZHNhdGBcbiAqIC0gYHN0YWN0b29scy1zZW50aW5lbDJgXG4gKlxuICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL3N0YWN0b29scy1wYWNrYWdlc30gZm9yIGF2YWlsYWJsZSBzdGFjdG9vbHMgcGFja2FnZXNcbiAqIEBzZWUge0BsaW5rIGh0dHBzOi8vc3RhY3Rvb2xzLnJlYWR0aGVkb2NzLmlvL30gZm9yIHN0YWN0b29scyBkb2N1bWVudGF0aW9uXG4gKi9cbmV4cG9ydCBjbGFzcyBTdGFjdG9vbHNJdGVtR2VuZXJhdG9yIGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgLyoqXG4gICAqIFRoZSBTUVMgcXVldWUgdGhhdCBidWZmZXJzIGl0ZW0gZ2VuZXJhdGlvbiByZXF1ZXN0cy5cbiAgICpcbiAgICogVGhpcyBxdWV1ZSByZWNlaXZlcyBtZXNzYWdlcyBmcm9tIHRoZSBTTlMgdG9waWMgY29udGFpbmluZyBJdGVtUmVxdWVzdFxuICAgKiBwYXlsb2Fkcy4gSXQncyBjb25maWd1cmVkIHdpdGggYSB2aXNpYmlsaXR5IHRpbWVvdXQgdGhhdCBtYXRjaGVzIHRoZVxuICAgKiBMYW1iZGEgdGltZW91dCBwbHVzIGJ1ZmZlciB0aW1lIHRvIHByZXZlbnQgZHVwbGljYXRlIHByb2Nlc3NpbmcuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgcXVldWU6IHNxcy5RdWV1ZTtcblxuICAvKipcbiAgICogRGVhZCBsZXR0ZXIgcXVldWUgZm9yIGZhaWxlZCBpdGVtIGdlbmVyYXRpb24gYXR0ZW1wdHMuXG4gICAqXG4gICAqIE1lc3NhZ2VzIHRoYXQgZmFpbCBwcm9jZXNzaW5nIGFmdGVyIDUgYXR0ZW1wdHMgYXJlIHNlbnQgaGVyZSBmb3JcbiAgICogaW5zcGVjdGlvbiBhbmQgcG90ZW50aWFsIHJlcGxheS4gVGhpcyBoZWxwcyB3aXRoIGRlYnVnZ2luZyBzdGFjdG9vbHNcbiAgICogcGFja2FnZSBpc3N1ZXMsIG5ldHdvcmsgZmFpbHVyZXMsIG9yIG1hbGZvcm1lZCByZXF1ZXN0cy5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBkZWFkTGV0dGVyUXVldWU6IHNxcy5RdWV1ZTtcblxuICAvKipcbiAgICogVGhlIFNOUyB0b3BpYyB0aGF0IHJlY2VpdmVzIGl0ZW0gZ2VuZXJhdGlvbiByZXF1ZXN0cy5cbiAgICpcbiAgICogRXh0ZXJuYWwgc3lzdGVtcyBwdWJsaXNoIEl0ZW1SZXF1ZXN0IG1lc3NhZ2VzIHRvIHRoaXMgdG9waWMgdG8gdHJpZ2dlclxuICAgKiBTVEFDIGl0ZW0gZ2VuZXJhdGlvbi4gVGhlIHRvcGljIGZhbnMgb3V0IHRvIHRoZSBTUVMgcXVldWUgZm9yIHByb2Nlc3NpbmcuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgdG9waWM6IHNucy5Ub3BpYztcblxuICAvKipcbiAgICogVGhlIGNvbnRhaW5lcml6ZWQgTGFtYmRhIGZ1bmN0aW9uIHRoYXQgZ2VuZXJhdGVzIFNUQUMgaXRlbXMuXG4gICAqXG4gICAqIFRoaXMgRG9ja2VyLWJhc2VkIGZ1bmN0aW9uIGR5bmFtaWNhbGx5IGluc3RhbGxzIHN0YWN0b29scyBwYWNrYWdlc1xuICAgKiB1c2luZyB1dngsIHByb2Nlc3NlcyBzb3VyY2UgZGF0YSwgYW5kIHB1Ymxpc2hlcyBnZW5lcmF0ZWQgU1RBQyBpdGVtc1xuICAgKiB0byB0aGUgY29uZmlndXJlZCBJdGVtTG9hZCBTTlMgdG9waWMuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgbGFtYmRhRnVuY3Rpb246IGxhbWJkYS5Eb2NrZXJJbWFnZUZ1bmN0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBTdGFjdG9vbHNJdGVtR2VuZXJhdG9yUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgY29uc3QgdGltZW91dFNlY29uZHMgPSBwcm9wcy5sYW1iZGFUaW1lb3V0U2Vjb25kcyA/PyAxMjA7XG4gICAgY29uc3QgbGFtYmRhUnVudGltZSA9IHByb3BzLmxhbWJkYVJ1bnRpbWUgPz8gbGFtYmRhLlJ1bnRpbWUuUFlUSE9OXzNfMTE7XG5cbiAgICAvLyBDcmVhdGUgZGVhZCBsZXR0ZXIgcXVldWVcbiAgICB0aGlzLmRlYWRMZXR0ZXJRdWV1ZSA9IG5ldyBzcXMuUXVldWUodGhpcywgXCJEZWFkTGV0dGVyUXVldWVcIiwge1xuICAgICAgcmV0ZW50aW9uUGVyaW9kOiBEdXJhdGlvbi5kYXlzKDE0KSxcbiAgICB9KTtcblxuICAgIC8vIENyZWF0ZSBtYWluIHF1ZXVlXG4gICAgdGhpcy5xdWV1ZSA9IG5ldyBzcXMuUXVldWUodGhpcywgXCJRdWV1ZVwiLCB7XG4gICAgICB2aXNpYmlsaXR5VGltZW91dDogRHVyYXRpb24uc2Vjb25kcyh0aW1lb3V0U2Vjb25kcyArIDEwKSxcbiAgICAgIGVuY3J5cHRpb246IHNxcy5RdWV1ZUVuY3J5cHRpb24uU1FTX01BTkFHRUQsXG4gICAgICBkZWFkTGV0dGVyUXVldWU6IHtcbiAgICAgICAgbWF4UmVjZWl2ZUNvdW50OiA1LFxuICAgICAgICBxdWV1ZTogdGhpcy5kZWFkTGV0dGVyUXVldWUsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8gQ3JlYXRlIFNOUyB0b3BpY1xuICAgIHRoaXMudG9waWMgPSBuZXcgc25zLlRvcGljKHRoaXMsIFwiVG9waWNcIiwge1xuICAgICAgZGlzcGxheU5hbWU6IGAke2lkfS1JdGVtR2VuVG9waWNgLFxuICAgIH0pO1xuXG4gICAgLy8gU3Vic2NyaWJlIHRoZSBxdWV1ZSB0byB0aGUgdG9waWNcbiAgICB0aGlzLnRvcGljLmFkZFN1YnNjcmlwdGlvbihcbiAgICAgIG5ldyBzbnNTdWJzY3JpcHRpb25zLlNxc1N1YnNjcmlwdGlvbih0aGlzLnF1ZXVlKVxuICAgICk7XG5cbiAgICAvLyBDcmVhdGUgdGhlIGxhbWJkYSBmdW5jdGlvblxuICAgIHRoaXMubGFtYmRhRnVuY3Rpb24gPSBuZXcgbGFtYmRhLkRvY2tlckltYWdlRnVuY3Rpb24odGhpcywgXCJGdW5jdGlvblwiLCB7XG4gICAgICBjb2RlOiBsYW1iZGEuRG9ja2VySW1hZ2VDb2RlLmZyb21JbWFnZUFzc2V0KHBhdGguam9pbihfX2Rpcm5hbWUsIFwiLi5cIiksIHtcbiAgICAgICAgZmlsZTogXCJzdGFjdG9vbHMtaXRlbS1nZW5lcmF0b3IvcnVudGltZS9Eb2NrZXJmaWxlXCIsXG4gICAgICAgIHBsYXRmb3JtOiBQbGF0Zm9ybS5MSU5VWF9BTUQ2NCxcbiAgICAgICAgYnVpbGRBcmdzOiB7XG4gICAgICAgICAgUFlUSE9OX1ZFUlNJT046IGxhbWJkYVJ1bnRpbWUudG9TdHJpbmcoKS5yZXBsYWNlKFwicHl0aG9uXCIsIFwiXCIpLFxuICAgICAgICB9LFxuICAgICAgfSksXG4gICAgICBtZW1vcnlTaXplOiBwcm9wcy5tZW1vcnlTaXplID8/IDEwMjQsXG4gICAgICB0aW1lb3V0OiBEdXJhdGlvbi5zZWNvbmRzKHRpbWVvdXRTZWNvbmRzKSxcbiAgICAgIGxvZ1JldGVudGlvbjogbG9ncy5SZXRlbnRpb25EYXlzLk9ORV9XRUVLLFxuICAgICAgZW52aXJvbm1lbnQ6IHtcbiAgICAgICAgSVRFTV9MT0FEX1RPUElDX0FSTjogcHJvcHMuaXRlbUxvYWRUb3BpY0FybixcbiAgICAgICAgTE9HX0xFVkVMOiBcIklORk9cIixcbiAgICAgICAgLi4ucHJvcHMuZW52aXJvbm1lbnQsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8gQWRkIFNRUyBldmVudCBzb3VyY2UgdG8gdGhlIGxhbWJkYVxuICAgIHRoaXMubGFtYmRhRnVuY3Rpb24uYWRkRXZlbnRTb3VyY2UoXG4gICAgICBuZXcgbGFtYmRhRXZlbnRTb3VyY2VzLlNxc0V2ZW50U291cmNlKHRoaXMucXVldWUsIHtcbiAgICAgICAgYmF0Y2hTaXplOiBwcm9wcy5iYXRjaFNpemUgPz8gMTAsXG4gICAgICAgIHJlcG9ydEJhdGNoSXRlbUZhaWx1cmVzOiB0cnVlLFxuICAgICAgICBtYXhDb25jdXJyZW5jeTogcHJvcHMubWF4Q29uY3VycmVuY3kgPz8gMTAwLFxuICAgICAgfSlcbiAgICApO1xuXG4gICAgLy8gR3JhbnQgcGVybWlzc2lvbnMgdG8gcHVibGlzaCB0byB0aGUgaXRlbSBsb2FkIHRvcGljXG4gICAgLy8gTm90ZTogVGhpcyB3aWxsIGJlIGdyYW50ZWQgZXh0ZXJuYWxseSBzaW5jZSB3ZSBvbmx5IGhhdmUgdGhlIEFSTlxuICAgIC8vIFRoZSBjb25zdW1pbmcgY29uc3RydWN0IHNob3VsZCBoYW5kbGUgdGhpcyBwZXJtaXNzaW9uXG5cbiAgICAvLyBDcmVhdGUgb3V0cHV0c1xuICAgIG5ldyBDZm5PdXRwdXQodGhpcywgXCJUb3BpY0FyblwiLCB7XG4gICAgICB2YWx1ZTogdGhpcy50b3BpYy50b3BpY0FybixcbiAgICAgIGRlc2NyaXB0aW9uOiBcIkFSTiBvZiB0aGUgU3RhY3Rvb2xzSXRlbUdlbmVyYXRvciBTTlMgVG9waWNcIixcbiAgICAgIGV4cG9ydE5hbWU6IFwic3RhY3Rvb2xzLWl0ZW0tZ2VuZXJhdG9yLXRvcGljLWFyblwiLFxuICAgIH0pO1xuXG4gICAgbmV3IENmbk91dHB1dCh0aGlzLCBcIlF1ZXVlVXJsXCIsIHtcbiAgICAgIHZhbHVlOiB0aGlzLnF1ZXVlLnF1ZXVlVXJsLFxuICAgICAgZGVzY3JpcHRpb246IFwiVVJMIG9mIHRoZSBTdGFjdG9vbHNJdGVtR2VuZXJhdG9yIFNRUyBRdWV1ZVwiLFxuICAgICAgZXhwb3J0TmFtZTogXCJzdGFjdG9vbHMtaXRlbS1nZW5lcmF0b3ItcXVldWUtdXJsXCIsXG4gICAgfSk7XG5cbiAgICBuZXcgQ2ZuT3V0cHV0KHRoaXMsIFwiRGVhZExldHRlclF1ZXVlVXJsXCIsIHtcbiAgICAgIHZhbHVlOiB0aGlzLmRlYWRMZXR0ZXJRdWV1ZS5xdWV1ZVVybCxcbiAgICAgIGRlc2NyaXB0aW9uOiBcIlVSTCBvZiB0aGUgU3RhY3Rvb2xzSXRlbUdlbmVyYXRvciBEZWFkIExldHRlciBRdWV1ZVwiLFxuICAgICAgZXhwb3J0TmFtZTogXCJzdGFjdG9vbHMtaXRlbS1nZW5lcmF0b3ItZGVhZGxldHRlci1xdWV1ZS11cmxcIixcbiAgICB9KTtcblxuICAgIG5ldyBDZm5PdXRwdXQodGhpcywgXCJGdW5jdGlvbk5hbWVcIiwge1xuICAgICAgdmFsdWU6IHRoaXMubGFtYmRhRnVuY3Rpb24uZnVuY3Rpb25OYW1lLFxuICAgICAgZGVzY3JpcHRpb246IFwiTmFtZSBvZiB0aGUgU3RhY3Rvb2xzSXRlbUdlbmVyYXRvciBMYW1iZGEgRnVuY3Rpb25cIixcbiAgICAgIGV4cG9ydE5hbWU6IFwic3RhY3Rvb2xzLWl0ZW0tZ2VuZXJhdG9yLWZ1bmN0aW9uLW5hbWVcIixcbiAgICB9KTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
ARG PYTHON_VERSION=3.11
|
|
2
|
+
FROM public.ecr.aws/lambda/python:${PYTHON_VERSION}
|
|
3
|
+
COPY --from=ghcr.io/astral-sh/uv:0.7.8 /uv /uvx /bin/
|
|
4
|
+
|
|
5
|
+
ENV UV_CACHE_DIR=/tmp/uv-cache/
|
|
6
|
+
ENV UV_COMPILE_BYTECODE=1
|
|
7
|
+
ENV PYTHONUNBUFFERED=1
|
|
8
|
+
ENV HOME=/tmp
|
|
9
|
+
ENV PATH=/tmp/.local/bin:$PATH
|
|
10
|
+
|
|
11
|
+
WORKDIR ${LAMBDA_TASK_ROOT}
|
|
12
|
+
|
|
13
|
+
COPY stactools-item-generator/runtime/pyproject.toml pyproject.toml
|
|
14
|
+
COPY stactools-item-generator/runtime/src/stactools_item_generator/ ${LAMBDA_TASK_ROOT}/stactools_item_generator/
|
|
15
|
+
|
|
16
|
+
RUN uv export --no-dev --no-editable -o requirements.txt && \
|
|
17
|
+
uv pip install --target ${LAMBDA_TASK_ROOT} -r requirements.txt && \
|
|
18
|
+
uv tool install --with requests stactools;
|
|
19
|
+
|
|
20
|
+
CMD ["stactools_item_generator.handler.handler"]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "stactools-item-generator"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "An application for generating STAC metadata with any stactools package"
|
|
5
|
+
authors = [
|
|
6
|
+
{ name = "hrodmn", email = "henry@developmentseed.org" }
|
|
7
|
+
]
|
|
8
|
+
requires-python = ">=3.11"
|
|
9
|
+
dependencies = [
|
|
10
|
+
"pydantic>=2.11.0",
|
|
11
|
+
"stac-pydantic>=3.2.0",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[build-system]
|
|
15
|
+
requires = ["hatchling"]
|
|
16
|
+
build-backend = "hatchling.build"
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"""AWS Lambda handler for STAC Item Generation."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
5
|
+
import os
|
|
6
|
+
import subprocess
|
|
7
|
+
import traceback
|
|
8
|
+
from typing import TYPE_CHECKING, Annotated, Any, Dict, List, Optional, TypedDict
|
|
9
|
+
|
|
10
|
+
import boto3
|
|
11
|
+
from pydantic import ValidationError
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from aws_lambda_typing.context import Context
|
|
15
|
+
else:
|
|
16
|
+
Context = Annotated[object, "Context object"]
|
|
17
|
+
|
|
18
|
+
from stactools_item_generator.item import ItemRequest, create_stac_item
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger()
|
|
21
|
+
if logger.hasHandlers():
|
|
22
|
+
logger.handlers.clear()
|
|
23
|
+
|
|
24
|
+
log_handler = logging.StreamHandler() # <--- Renamed handler variable
|
|
25
|
+
|
|
26
|
+
log_level_name = os.environ.get("LOG_LEVEL", "INFO").upper()
|
|
27
|
+
log_level = logging._nameToLevel.get(log_level_name, logging.INFO)
|
|
28
|
+
logger.setLevel(log_level)
|
|
29
|
+
|
|
30
|
+
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
|
31
|
+
log_handler.setFormatter(formatter)
|
|
32
|
+
logger.addHandler(log_handler)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_topic_arn() -> str:
|
|
36
|
+
item_load_topic_arn = os.environ.get("ITEM_LOAD_TOPIC_ARN")
|
|
37
|
+
if not item_load_topic_arn:
|
|
38
|
+
logger.error("Environment variable ITEM_LOAD_TOPIC_ARN is not set.")
|
|
39
|
+
raise EnvironmentError("ITEM_LOAD_TOPIC_ARN must be set")
|
|
40
|
+
|
|
41
|
+
return item_load_topic_arn
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def process_record(record: Dict[str, Any], sns_client) -> None:
|
|
45
|
+
"""
|
|
46
|
+
Processes a single SQS record (within a batch).
|
|
47
|
+
Extracts the request, calls create_stac_item, and publishes the result.
|
|
48
|
+
Raises exceptions on failure.
|
|
49
|
+
"""
|
|
50
|
+
message_id = record.get("messageId", "UNKNOWN_ID")
|
|
51
|
+
logger.info(f"Processing record: {message_id}")
|
|
52
|
+
message_str = None
|
|
53
|
+
try:
|
|
54
|
+
sqs_body_str = record["body"]
|
|
55
|
+
logger.debug(f"[{message_id}] SQS message body: {sqs_body_str}")
|
|
56
|
+
sns_notification = json.loads(sqs_body_str)
|
|
57
|
+
|
|
58
|
+
message_str = sns_notification["Message"]
|
|
59
|
+
logger.debug(f"[{message_id}] SNS Message content: {message_str}")
|
|
60
|
+
|
|
61
|
+
message_data = json.loads(message_str)
|
|
62
|
+
item_request = ItemRequest(**message_data)
|
|
63
|
+
logger.info(
|
|
64
|
+
f"[{message_id}] Parsed ItemRequest for package: {item_request.package_name}"
|
|
65
|
+
)
|
|
66
|
+
logger.debug(f"[{message_id}] Full ItemRequest: {item_request.model_dump_json()}")
|
|
67
|
+
|
|
68
|
+
stac_item = create_stac_item(item_request)
|
|
69
|
+
logger.info(f"[{message_id}] Successfully created STAC item: {stac_item.id}")
|
|
70
|
+
logger.debug(
|
|
71
|
+
f"[{message_id}] Generated STAC Item JSON (sample): "
|
|
72
|
+
f"{ {k: v for k, v in stac_item.model_dump().items() if k in ['id', 'collection', 'properties']} }"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
stac_item_json = stac_item.model_dump_json()
|
|
76
|
+
|
|
77
|
+
item_load_topic_arn = get_topic_arn()
|
|
78
|
+
logger.info(
|
|
79
|
+
f"[{message_id}] Publishing STAC item {stac_item.id} to {item_load_topic_arn}"
|
|
80
|
+
)
|
|
81
|
+
response = sns_client.publish(
|
|
82
|
+
TopicArn=item_load_topic_arn,
|
|
83
|
+
Message=stac_item_json,
|
|
84
|
+
)
|
|
85
|
+
logger.info(
|
|
86
|
+
f"[{message_id}] SNS publish response MessageId: {response.get('MessageId')}"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
except json.JSONDecodeError as e:
|
|
90
|
+
logger.error(f"[{message_id}] Failed to decode JSON: {e}")
|
|
91
|
+
logger.error(f"[{message_id}] Problematic data (SQS Body): {record.get('body')}")
|
|
92
|
+
raise
|
|
93
|
+
except ValidationError as e:
|
|
94
|
+
logger.error(f"[{message_id}] Failed to validate ItemRequest: {e}")
|
|
95
|
+
logger.error(f"[{message_id}] Validation errors:\n{e.errors()}")
|
|
96
|
+
problem_data = message_str if message_str is not None else record.get("body")
|
|
97
|
+
logger.error(
|
|
98
|
+
f"[{message_id}] Problematic data (SNS Message or SQS Body): {problem_data}"
|
|
99
|
+
)
|
|
100
|
+
raise
|
|
101
|
+
except (
|
|
102
|
+
subprocess.CalledProcessError
|
|
103
|
+
) as e: # <--- Catching the imported exception type
|
|
104
|
+
logger.error(f"[{message_id}] Subprocess command failed:")
|
|
105
|
+
logger.error(f"[{message_id}] Command: {' '.join(e.cmd)}")
|
|
106
|
+
logger.error(f"[{message_id}] Return code: {e.returncode}")
|
|
107
|
+
logger.error(f"[{message_id}] Stdout: {e.stdout}")
|
|
108
|
+
logger.error(f"[{message_id}] Stderr: {e.stderr}")
|
|
109
|
+
raise
|
|
110
|
+
except Exception as e:
|
|
111
|
+
logger.error(
|
|
112
|
+
f"[{message_id}] An unexpected error occurred processing record: {e}"
|
|
113
|
+
)
|
|
114
|
+
logger.error(traceback.format_exc())
|
|
115
|
+
raise
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class BatchItemFailure(TypedDict):
|
|
119
|
+
itemIdentifier: str
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class PartialBatchFailureResponse(TypedDict):
|
|
123
|
+
batchItemFailures: List[BatchItemFailure]
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def handler(
|
|
127
|
+
event: Dict[str, Any], context: Context
|
|
128
|
+
) -> Optional[PartialBatchFailureResponse]:
|
|
129
|
+
"""
|
|
130
|
+
AWS Lambda handler function triggered by SQS with batching enabled.
|
|
131
|
+
|
|
132
|
+
Processes messages in batches, attempts to generate STAC items, publishes
|
|
133
|
+
successful results to SNS, and reports partial batch failures to SQS.
|
|
134
|
+
"""
|
|
135
|
+
try:
|
|
136
|
+
sns_client = boto3.client("sns", region_name=os.getenv("AWS_DEFAULT_REGION"))
|
|
137
|
+
except Exception as e:
|
|
138
|
+
logging.error(f"Error: {str(e)}")
|
|
139
|
+
raise EnvironmentError("AWS_DEFAULT_REGION must be set") from e
|
|
140
|
+
|
|
141
|
+
records = event.get("Records", [])
|
|
142
|
+
aws_request_id = getattr(context, "aws_request_id", "N/A")
|
|
143
|
+
remaining_time = getattr(context, "get_remaining_time_in_millis", lambda: "N/A")()
|
|
144
|
+
|
|
145
|
+
logger.info(f"Received batch with {len(records)} records.")
|
|
146
|
+
logger.debug(
|
|
147
|
+
f"Lambda Context: RequestId={aws_request_id}, RemainingTime={remaining_time}ms"
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
batch_item_failures: List[BatchItemFailure] = []
|
|
151
|
+
|
|
152
|
+
for record in records:
|
|
153
|
+
message_id = record.get("messageId")
|
|
154
|
+
if not message_id:
|
|
155
|
+
logger.warning("Record missing messageId, cannot report failure for it.")
|
|
156
|
+
continue
|
|
157
|
+
|
|
158
|
+
try:
|
|
159
|
+
process_record(record, sns_client)
|
|
160
|
+
logger.info(f"[{message_id}] Successfully processed.")
|
|
161
|
+
|
|
162
|
+
except Exception:
|
|
163
|
+
logger.error(f"[{message_id}] Marked as failed.")
|
|
164
|
+
batch_item_failures.append({"itemIdentifier": message_id})
|
|
165
|
+
|
|
166
|
+
if batch_item_failures:
|
|
167
|
+
logger.warning(
|
|
168
|
+
f"Finished processing batch. {len(batch_item_failures)} failure(s) reported."
|
|
169
|
+
)
|
|
170
|
+
logger.info(
|
|
171
|
+
f"Returning failed item identifiers: {[f['itemIdentifier'] for f in batch_item_failures]}"
|
|
172
|
+
)
|
|
173
|
+
return {"batchItemFailures": batch_item_failures}
|
|
174
|
+
else:
|
|
175
|
+
logger.info("Finished processing batch. All records successful.")
|
|
176
|
+
return None
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
import subprocess
|
|
4
|
+
from tempfile import NamedTemporaryFile
|
|
5
|
+
from typing import Dict, List, Optional
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
8
|
+
from stac_pydantic.item import Item
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger()
|
|
11
|
+
logger.setLevel(logging.INFO)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ItemRequest(BaseModel):
|
|
15
|
+
package_name: str = Field(..., description="Name of the stactools package")
|
|
16
|
+
group_name: str = Field(..., description="Group name for the STAC item")
|
|
17
|
+
create_item_args: List[str] = Field(
|
|
18
|
+
..., description="Arguments for create-item command"
|
|
19
|
+
)
|
|
20
|
+
create_item_options: Dict[str, str] = Field(
|
|
21
|
+
default_factory=dict, description="Options for create-item command"
|
|
22
|
+
)
|
|
23
|
+
collection_id: Optional[str] = Field(
|
|
24
|
+
None, description="value for the collection field of the item json"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
model_config = ConfigDict(
|
|
28
|
+
json_schema_extra={
|
|
29
|
+
"example": {
|
|
30
|
+
"package_name": "stactools-glad-glclu2020",
|
|
31
|
+
"group_name": "gladglclu2020",
|
|
32
|
+
"create_item_args": [
|
|
33
|
+
"https://storage.googleapis.com/earthenginepartners-hansen/GLCLU2000-2020/v2/2000/50N_090W.tif"
|
|
34
|
+
],
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def create_stac_item(request: ItemRequest) -> Item:
|
|
41
|
+
"""
|
|
42
|
+
Create a STAC item using a stactools package
|
|
43
|
+
"""
|
|
44
|
+
logger.info(f"Received request: {json.dumps(request.model_dump())}")
|
|
45
|
+
|
|
46
|
+
if not request.package_name:
|
|
47
|
+
raise ValueError("Missing required parameter: package_name")
|
|
48
|
+
|
|
49
|
+
command = [
|
|
50
|
+
"uvx",
|
|
51
|
+
"--with",
|
|
52
|
+
f"requests,{request.package_name}",
|
|
53
|
+
"--from",
|
|
54
|
+
"stactools",
|
|
55
|
+
"stac",
|
|
56
|
+
request.group_name,
|
|
57
|
+
"create-item",
|
|
58
|
+
*request.create_item_args,
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
for option, value in request.create_item_options.items():
|
|
62
|
+
command.extend([f"--{option}", value])
|
|
63
|
+
|
|
64
|
+
logger.info(f"Executing command: {' '.join(command)}")
|
|
65
|
+
|
|
66
|
+
with NamedTemporaryFile(suffix=".json") as output:
|
|
67
|
+
command.append(output.name)
|
|
68
|
+
result = subprocess.run(command, capture_output=True, text=True, check=True)
|
|
69
|
+
|
|
70
|
+
logger.info(f"Command output: {result.stdout}")
|
|
71
|
+
with open(output.name) as f:
|
|
72
|
+
item_dict = json.load(f)
|
|
73
|
+
|
|
74
|
+
if request.collection_id:
|
|
75
|
+
item_dict["collection"] = request.collection_id
|
|
76
|
+
|
|
77
|
+
return Item(**item_dict)
|
package/lib/tipg-api/index.js
CHANGED
|
@@ -57,5 +57,5 @@ class TiPgApiLambda extends constructs_1.Construct {
|
|
|
57
57
|
}
|
|
58
58
|
exports.TiPgApiLambda = TiPgApiLambda;
|
|
59
59
|
_a = JSII_RTTI_SYMBOL_1;
|
|
60
|
-
TiPgApiLambda[_a] = { fqn: "eoapi-cdk.TiPgApiLambda", version: "8.
|
|
60
|
+
TiPgApiLambda[_a] = { fqn: "eoapi-cdk.TiPgApiLambda", version: "8.2.0" };
|
|
61
61
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZDQVdxQjtBQUNyQiwyQ0FBdUM7QUFFdkMsNkJBQTZCO0FBRTNCLE1BQWEsYUFBYyxTQUFRLHNCQUFTO0lBSTFDLFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBeUI7UUFDakUsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVqQixJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSx3QkFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFO1lBQzVELFdBQVc7WUFDWCxPQUFPLEVBQUUsd0JBQU0sQ0FBQyxPQUFPLENBQUMsV0FBVztZQUNuQyxPQUFPLEVBQUUsaUJBQWlCO1lBQzFCLFVBQVUsRUFBRSxJQUFJO1lBQ2hCLFlBQVksRUFBRSxzQkFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRO1lBQ3pDLE9BQU8sRUFBRSxzQkFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDN0IsSUFBSSxFQUFFLHdCQUFNLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsRUFBRTtnQkFDNUQsSUFBSSxFQUFFLDZCQUE2QjtnQkFDbkMsU0FBUyxFQUFFLEVBQUUsY0FBYyxFQUFFLE1BQU0sRUFBRTthQUN0QyxDQUFDO1lBQ0YsR0FBRyxFQUFFLEtBQUssQ0FBQyxHQUFHO1lBQ2QsVUFBVSxFQUFFLEtBQUssQ0FBQyxlQUFlO1lBQ2pDLGlCQUFpQixFQUFFLElBQUk7WUFDdkIsV0FBVyxFQUFFO2dCQUNYLGlCQUFpQixFQUFFLEtBQUssQ0FBQyxRQUFRLENBQUMsU0FBUztnQkFDM0MsZ0JBQWdCLEVBQUUsR0FBRztnQkFDckIsZ0JBQWdCLEVBQUUsR0FBRztnQkFDckIsR0FBRyxLQUFLLENBQUMsTUFBTTthQUNoQjtZQUNELGlFQUFpRTtZQUNqRSxHQUFHLEtBQUssQ0FBQyxxQkFBcUI7U0FDL0IsQ0FBQyxDQUFDO1FBRUgsS0FBSyxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFFbEQsSUFBSSxLQUFLLENBQUMsR0FBRyxFQUFDLENBQUM7WUFDYixJQUFJLENBQUMsa0JBQWtCLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFLHFCQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSw2QkFBNkIsQ0FBQyxDQUFDO1FBQzNHLENBQUM7UUFFRCxNQUFNLE9BQU8sR0FBRyxJQUFJLDhCQUFZLENBQUMsT0FBTyxDQUN0QyxJQUFJLEVBQ0osR0FBRyxtQkFBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxTQUFTLFdBQVcsRUFDdEM7WUFDRSxvQkFBb0IsRUFBRSxLQUFLLENBQUMsaUJBQWlCO2dCQUMzQyxDQUFDLENBQUM7b0JBQ0UsVUFBVSxFQUFFLEtBQUssQ0FBQyxpQkFBaUI7aUJBQ3BDO2dCQUNILENBQUMsQ0FBQyxTQUFTO1lBQ2Isa0JBQWtCLEVBQ2hCLElBQUksMkNBQXlCLENBQUMscUJBQXFCLENBQ2pELGFBQWEsRUFDYixJQUFJLENBQUMsa0JBQWtCLEVBQ3ZCLEtBQUssQ0FBQyxpQkFBaUI7Z0JBQ3JCLENBQUMsQ0FBQztvQkFDRSxnQkFBZ0IsRUFDZCxJQUFJLDhCQUFZLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxlQUFlLENBQ2pELE1BQU0sRUFDTiw4QkFBWSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQzlCLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQzdCLENBQ0Y7aUJBQ0o7Z0JBQ0gsQ0FBQyxDQUFDLFNBQVMsQ0FDZDtTQUNKLENBQ0YsQ0FBQztRQUVGLElBQUksQ0FBQyxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUksQ0FBQztRQUV4QixJQUFJLHVCQUFTLENBQUMsSUFBSSxFQUFFLGlCQUFpQixFQUFFO1lBQ3JDLFVBQVUsRUFBRSxHQUFHLG1CQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsVUFBVTtZQUNqRCxLQUFLLEVBQUUsSUFBSSxDQUFDLEdBQUc7U0FDaEIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7QUF2RUgsc0NBd0VDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgU3RhY2ssXG4gIGF3c19hcGlnYXRld2F5djIgYXMgYXBpZ2F0ZXdheXYyLFxuICBhd3NfYXBpZ2F0ZXdheXYyX2ludGVncmF0aW9ucyBhcyBhcGlnYXRld2F5djJfaW50ZWdyYXRpb25zLFxuICBhd3NfZWMyIGFzIGVjMixcbiAgYXdzX2xhbWJkYSBhcyBsYW1iZGEsXG4gIGF3c19sb2dzIGFzIGxvZ3MsXG4gIGF3c19yZHMgYXMgcmRzLFxuICBhd3Nfc2VjcmV0c21hbmFnZXIgYXMgc2VjcmV0c21hbmFnZXIsXG4gIENmbk91dHB1dCxcbiAgRHVyYXRpb24sXG59IGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSBcImNvbnN0cnVjdHNcIjtcbmltcG9ydCB7IEN1c3RvbUxhbWJkYUZ1bmN0aW9uUHJvcHMgfSBmcm9tIFwiLi4vdXRpbHNcIjtcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5cbiAgZXhwb3J0IGNsYXNzIFRpUGdBcGlMYW1iZGEgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICAgIHJlYWRvbmx5IHVybDogc3RyaW5nO1xuICAgIHB1YmxpYyB0aVBnTGFtYmRhRnVuY3Rpb246IGxhbWJkYS5GdW5jdGlvbjtcblxuICAgIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBUaVBnQXBpTGFtYmRhUHJvcHMpIHtcbiAgICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICAgIHRoaXMudGlQZ0xhbWJkYUZ1bmN0aW9uID0gbmV3IGxhbWJkYS5GdW5jdGlvbih0aGlzLCBcImxhbWJkYVwiLCB7XG4gICAgICAgIC8vIGRlZmF1bHRzXG4gICAgICAgIHJ1bnRpbWU6IGxhbWJkYS5SdW50aW1lLlBZVEhPTl8zXzExLFxuICAgICAgICBoYW5kbGVyOiBcImhhbmRsZXIuaGFuZGxlclwiLFxuICAgICAgICBtZW1vcnlTaXplOiAxMDI0LFxuICAgICAgICBsb2dSZXRlbnRpb246IGxvZ3MuUmV0ZW50aW9uRGF5cy5PTkVfV0VFSyxcbiAgICAgICAgdGltZW91dDogRHVyYXRpb24uc2Vjb25kcygzMCksXG4gICAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Eb2NrZXJCdWlsZChwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4nKSwge1xuICAgICAgICAgIGZpbGU6IFwidGlwZy1hcGkvcnVudGltZS9Eb2NrZXJmaWxlXCIsXG4gICAgICAgICAgYnVpbGRBcmdzOiB7IFBZVEhPTl9WRVJTSU9OOiAnMy4xMScgfSxcbiAgICAgICAgfSksXG4gICAgICAgIHZwYzogcHJvcHMudnBjLFxuICAgICAgICB2cGNTdWJuZXRzOiBwcm9wcy5zdWJuZXRTZWxlY3Rpb24sXG4gICAgICAgIGFsbG93UHVibGljU3VibmV0OiB0cnVlLFxuICAgICAgICBlbnZpcm9ubWVudDoge1xuICAgICAgICAgIFBHU1RBQ19TRUNSRVRfQVJOOiBwcm9wcy5kYlNlY3JldC5zZWNyZXRBcm4sXG4gICAgICAgICAgREJfTUlOX0NPTk5fU0laRTogXCIxXCIsXG4gICAgICAgICAgREJfTUFYX0NPTk5fU0laRTogXCIxXCIsXG4gICAgICAgICAgLi4ucHJvcHMuYXBpRW52LFxuICAgICAgICB9LFxuICAgICAgICAvLyBvdmVyd3JpdGVzIGRlZmF1bHRzIHdpdGggdXNlci1wcm92aWRlZCBjb25maWd1cmFibGUgcHJvcGVydGllc1xuICAgICAgICAuLi5wcm9wcy5sYW1iZGFGdW5jdGlvbk9wdGlvbnNcbiAgICAgIH0pO1xuXG4gICAgICBwcm9wcy5kYlNlY3JldC5ncmFudFJlYWQodGhpcy50aVBnTGFtYmRhRnVuY3Rpb24pO1xuXG4gICAgICBpZiAocHJvcHMudnBjKXtcbiAgICAgICAgdGhpcy50aVBnTGFtYmRhRnVuY3Rpb24uY29ubmVjdGlvbnMuYWxsb3dUbyhwcm9wcy5kYiwgZWMyLlBvcnQudGNwKDU0MzIpLCBcImFsbG93IGNvbm5lY3Rpb25zIGZyb20gdGlwZ1wiKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdGlwZ0FwaSA9IG5ldyBhcGlnYXRld2F5djIuSHR0cEFwaShcbiAgICAgICAgdGhpcyxcbiAgICAgICAgYCR7U3RhY2sub2YodGhpcykuc3RhY2tOYW1lfS10aXBnLWFwaWAsXG4gICAgICAgIHtcbiAgICAgICAgICBkZWZhdWx0RG9tYWluTWFwcGluZzogcHJvcHMudGlwZ0FwaURvbWFpbk5hbWVcbiAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgIGRvbWFpbk5hbWU6IHByb3BzLnRpcGdBcGlEb21haW5OYW1lLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgICBkZWZhdWx0SW50ZWdyYXRpb246XG4gICAgICAgICAgICBuZXcgYXBpZ2F0ZXdheXYyX2ludGVncmF0aW9ucy5IdHRwTGFtYmRhSW50ZWdyYXRpb24oXG4gICAgICAgICAgICAgIFwiaW50ZWdyYXRpb25cIixcbiAgICAgICAgICAgICAgdGhpcy50aVBnTGFtYmRhRnVuY3Rpb24sXG4gICAgICAgICAgICAgIHByb3BzLnRpcGdBcGlEb21haW5OYW1lXG4gICAgICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmFtZXRlck1hcHBpbmc6XG4gICAgICAgICAgICAgICAgICAgICAgbmV3IGFwaWdhdGV3YXl2Mi5QYXJhbWV0ZXJNYXBwaW5nKCkub3ZlcndyaXRlSGVhZGVyKFxuICAgICAgICAgICAgICAgICAgICAgICAgXCJob3N0XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBhcGlnYXRld2F5djIuTWFwcGluZ1ZhbHVlLmN1c3RvbShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMudGlwZ0FwaURvbWFpbk5hbWUubmFtZVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgOiB1bmRlZmluZWRcbiAgICAgICAgICAgICksXG4gICAgICAgIH1cbiAgICAgICk7XG5cbiAgICAgIHRoaXMudXJsID0gdGlwZ0FwaS51cmwhO1xuXG4gICAgICBuZXcgQ2ZuT3V0cHV0KHRoaXMsIFwidGlwZy1hcGktb3V0cHV0XCIsIHtcbiAgICAgICAgZXhwb3J0TmFtZTogYCR7U3RhY2sub2YodGhpcykuc3RhY2tOYW1lfS10aXAtdXJsYCxcbiAgICAgICAgdmFsdWU6IHRoaXMudXJsLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgZXhwb3J0IGludGVyZmFjZSBUaVBnQXBpTGFtYmRhUHJvcHMge1xuICAgIC8qKlxuICAgICAqIFZQQyBpbnRvIHdoaWNoIHRoZSBsYW1iZGEgc2hvdWxkIGJlIGRlcGxveWVkLlxuICAgICAqL1xuICAgIHJlYWRvbmx5IHZwYz86IGVjMi5JVnBjO1xuXG4gICAgLyoqXG4gICAgICogUkRTIEluc3RhbmNlIHdpdGggaW5zdGFsbGVkIHBnU1RBQyBvciBwZ2JvdW5jZXIgc2VydmVyLlxuICAgICAqL1xuICAgIHJlYWRvbmx5IGRiOiByZHMuSURhdGFiYXNlSW5zdGFuY2UgfCBlYzIuSUluc3RhbmNlO1xuXG4gICAgLyoqXG4gICAgICogU3VibmV0IGludG8gd2hpY2ggdGhlIGxhbWJkYSBzaG91bGQgYmUgZGVwbG95ZWQuXG4gICAgICovXG4gICAgcmVhZG9ubHkgc3VibmV0U2VsZWN0aW9uPzogZWMyLlN1Ym5ldFNlbGVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIFNlY3JldCBjb250YWluaW5nIGNvbm5lY3Rpb24gaW5mb3JtYXRpb24gZm9yIHBnU1RBQyBkYXRhYmFzZS5cbiAgICAgKi9cbiAgICByZWFkb25seSBkYlNlY3JldDogc2VjcmV0c21hbmFnZXIuSVNlY3JldDtcblxuICAgIC8qKlxuICAgICAqIEN1c3RvbWl6ZWQgZW52aXJvbm1lbnQgdmFyaWFibGVzIHRvIHNlbmQgdG8gdGl0aWxlci1wZ3N0YWMgcnVudGltZS5cbiAgICAgKi9cbiAgICByZWFkb25seSBhcGlFbnY/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuXG4gICAgLyoqXG4gICAgICogQ3VzdG9tIERvbWFpbiBOYW1lIGZvciB0aXBnIEFQSS4gSWYgZGVmaW5lZCwgd2lsbCBjcmVhdGUgdGhlXG4gICAgICogZG9tYWluIG5hbWUgYW5kIGludGVncmF0ZSBpdCB3aXRoIHRoZSB0aXBnIEFQSS5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0IC0gdW5kZWZpbmVkXG4gICAgICovXG4gICAgcmVhZG9ubHkgdGlwZ0FwaURvbWFpbk5hbWU/OiBhcGlnYXRld2F5djIuSURvbWFpbk5hbWU7XG5cbiAgICAvKipcbiAgICAgKiBDYW4gYmUgdXNlZCB0byBvdmVycmlkZSB0aGUgZGVmYXVsdCBsYW1iZGEgZnVuY3Rpb24gcHJvcGVydGllcy5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0IC0gZGVmaW5lZCBpbiB0aGUgY29uc3RydWN0LlxuICAgICAqL1xuICAgIHJlYWRvbmx5IGxhbWJkYUZ1bmN0aW9uT3B0aW9ucz86IEN1c3RvbUxhbWJkYUZ1bmN0aW9uUHJvcHM7XG4gIH1cbiJdfQ==
|
|
@@ -77,5 +77,5 @@ class TitilerPgstacApiLambda extends constructs_1.Construct {
|
|
|
77
77
|
}
|
|
78
78
|
exports.TitilerPgstacApiLambda = TitilerPgstacApiLambda;
|
|
79
79
|
_a = JSII_RTTI_SYMBOL_1;
|
|
80
|
-
TitilerPgstacApiLambda[_a] = { fqn: "eoapi-cdk.TitilerPgstacApiLambda", version: "8.
|
|
80
|
+
TitilerPgstacApiLambda[_a] = { fqn: "eoapi-cdk.TitilerPgstacApiLambda", version: "8.2.0" };
|
|
81
81
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZDQVlxQjtBQUNyQiwyQ0FBdUM7QUFFdkMsNkJBQTZCO0FBRTNCLDRFQUE0RTtBQUM1RSxJQUFJLHVCQUF1QixHQUEyQjtJQUNwRCxrQ0FBa0MsRUFBRSxpQkFBaUI7SUFDckQsZUFBZSxFQUFFLEtBQUs7SUFDdEIsOEJBQThCLEVBQUUsV0FBVztJQUMzQyw2QkFBNkIsRUFBRSxPQUFPO0lBQ3RDLG9DQUFvQyxFQUFFLEtBQUs7SUFDM0MscUJBQXFCLEVBQUUsS0FBSztJQUM1QixtQkFBbUIsRUFBRSxHQUFHO0lBQ3hCLGdCQUFnQixFQUFFLFFBQVE7SUFDMUIsV0FBVyxFQUFFLE1BQU07SUFDbkIsZ0JBQWdCLEVBQUUsU0FBUztJQUMzQixrQkFBa0IsRUFBRSxHQUFHO0lBQ3ZCLGtCQUFrQixFQUFFLEdBQUc7Q0FDeEIsQ0FBQTtBQUVELE1BQWEsc0JBQXVCLFNBQVEsc0JBQVM7SUFJbkQsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUFrQztRQUMxRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLElBQUksQ0FBQywyQkFBMkIsR0FBRyxJQUFJLHdCQUFNLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUU7WUFDckUsV0FBVztZQUNYLE9BQU8sRUFBRSx3QkFBTSxDQUFDLE9BQU8sQ0FBQyxXQUFXO1lBQ25DLE9BQU8sRUFBRSxpQkFBaUI7WUFDMUIsVUFBVSxFQUFFLElBQUk7WUFDaEIsWUFBWSxFQUFFLHNCQUFRLENBQUMsYUFBYSxDQUFDLFFBQVE7WUFDN0MsT0FBTyxFQUFFLHNCQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUM3QixJQUFJLEVBQUUsd0JBQU0sQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxFQUFFO2dCQUM1RCxJQUFJLEVBQUUsdUNBQXVDO2dCQUM3QyxTQUFTLEVBQUUsRUFBRSxjQUFjLEVBQUUsTUFBTSxFQUFFO2FBQ3RDLENBQUM7WUFDRixHQUFHLEVBQUUsS0FBSyxDQUFDLEdBQUc7WUFDZCxVQUFVLEVBQUUsS0FBSyxDQUFDLGVBQWU7WUFDakMsaUJBQWlCLEVBQUUsSUFBSTtZQUN2Qix3RUFBd0U7WUFDeEUsV0FBVyxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyx1QkFBdUIsRUFBRSxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsbUJBQW1CLEVBQUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsdUJBQXVCO1lBQ3BKLGlFQUFpRTtZQUNqRSxHQUFHLEtBQUssQ0FBQyxxQkFBcUI7U0FDL0IsQ0FBQyxDQUFDO1FBRUgsZ0RBQWdEO1FBQ2hELElBQUksS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2xCLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFO2dCQUM3QixJQUFJLENBQUMsMkJBQTJCLENBQUMsZUFBZSxDQUFDLElBQUkscUJBQUcsQ0FBQyxlQUFlLENBQUM7b0JBQ3ZFLE9BQU8sRUFBRSxDQUFDLGNBQWMsQ0FBQztvQkFDekIsU0FBUyxFQUFFLENBQUMsZ0JBQWdCLE1BQU0sSUFBSSxDQUFDO2lCQUN4QyxDQUFDLENBQUMsQ0FBQztZQUNOLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELEtBQUssQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1FBRTNELElBQUksS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ2QsSUFBSSxDQUFDLDJCQUEyQixDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxxQkFBRyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsZ0NBQWdDLENBQUMsQ0FBQztRQUN2SCxDQUFDO1FBRUQsTUFBTSxPQUFPLEdBQUcsSUFBSSw4QkFBWSxDQUFDLE9BQU8sQ0FDdEMsSUFBSSxFQUNKLEdBQUcsbUJBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxxQkFBcUIsRUFDaEQ7WUFDRSxvQkFBb0IsRUFBRSxLQUFLLENBQUMsMEJBQTBCO2dCQUNwRCxDQUFDLENBQUM7b0JBQ0UsVUFBVSxFQUFFLEtBQUssQ0FBQywwQkFBMEI7aUJBQzdDO2dCQUNILENBQUMsQ0FBQyxTQUFTO1lBQ2Isa0JBQWtCLEVBQ2hCLElBQUksMkNBQXlCLENBQUMscUJBQXFCLENBQ2pELGFBQWEsRUFDYixJQUFJLENBQUMsMkJBQTJCLEVBQ2hDLEtBQUssQ0FBQywwQkFBMEI7Z0JBQzlCLENBQUMsQ0FBQztvQkFDRSxnQkFBZ0IsRUFDZCxJQUFJLDhCQUFZLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxlQUFlLENBQ2pELE1BQU0sRUFDTiw4QkFBWSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQzlCLEtBQUssQ0FBQywwQkFBMEIsQ0FBQyxJQUFJLENBQ3RDLENBQ0Y7aUJBQ0o7Z0JBQ0gsQ0FBQyxDQUFDLFNBQVMsQ0FDZDtTQUNKLENBQ0YsQ0FBQztRQUVGLElBQUksQ0FBQyxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUksQ0FBQztRQUV4QixJQUFJLHVCQUFTLENBQUMsSUFBSSxFQUFFLDJCQUEyQixFQUFFO1lBQy9DLFVBQVUsRUFBRSxHQUFHLG1CQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMscUJBQXFCO1lBQzVELEtBQUssRUFBRSxJQUFJLENBQUMsR0FBRztTQUNoQixDQUFDLENBQUM7SUFDTCxDQUFDOztBQTdFSCx3REE4RUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBTdGFjayxcbiAgYXdzX2FwaWdhdGV3YXl2MiBhcyBhcGlnYXRld2F5djIsXG4gIGF3c19hcGlnYXRld2F5djJfaW50ZWdyYXRpb25zIGFzIGFwaWdhdGV3YXl2Ml9pbnRlZ3JhdGlvbnMsXG4gIGF3c19pYW0gYXMgaWFtLFxuICBhd3NfZWMyIGFzIGVjMixcbiAgYXdzX3JkcyBhcyByZHMsXG4gIGF3c19sYW1iZGEgYXMgbGFtYmRhLFxuICBhd3Nfc2VjcmV0c21hbmFnZXIgYXMgc2VjcmV0c21hbmFnZXIsXG4gIENmbk91dHB1dCxcbiAgRHVyYXRpb24sXG4gIGF3c19sb2dzLFxufSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgeyBDdXN0b21MYW1iZGFGdW5jdGlvblByb3BzIH0gZnJvbSBcIi4uL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuXG4gIC8vIGRlZmF1bHQgc2V0dGluZ3MgdGhhdCBjYW4gYmUgb3ZlcnJpZGRlbiBieSB0aGUgdXNlci1wcm92aWRlZCBlbnZpcm9ubWVudC5cbiAgbGV0IGRlZmF1bHRUaXRpbGVyUGdzdGFjRW52IDp7IFtrZXk6IHN0cmluZ106IGFueSB9ID0ge1xuICAgIFwiQ1BMX1ZTSUxfQ1VSTF9BTExPV0VEX0VYVEVOU0lPTlNcIjogXCIudGlmLC5USUYsLnRpZmZcIixcbiAgICBcIkdEQUxfQ0FDSEVNQVhcIjogXCIyMDBcIixcbiAgICBcIkdEQUxfRElTQUJMRV9SRUFERElSX09OX09QRU5cIjogXCJFTVBUWV9ESVJcIixcbiAgICBcIkdEQUxfSU5HRVNURURfQllURVNfQVRfT1BFTlwiOiBcIjMyNzY4XCIsXG4gICAgXCJHREFMX0hUVFBfTUVSR0VfQ09OU0VDVVRJVkVfUkFOR0VTXCI6IFwiWUVTXCIsXG4gICAgXCJHREFMX0hUVFBfTVVMVElQTEVYXCI6IFwiWUVTXCIsXG4gICAgXCJHREFMX0hUVFBfVkVSU0lPTlwiOiBcIjJcIixcbiAgICBcIlBZVEhPTldBUk5JTkdTXCI6IFwiaWdub3JlXCIsXG4gICAgXCJWU0lfQ0FDSEVcIjogXCJUUlVFXCIsXG4gICAgXCJWU0lfQ0FDSEVfU0laRVwiOiBcIjUwMDAwMDBcIixcbiAgICBcIkRCX01JTl9DT05OX1NJWkVcIjogXCIxXCIsXG4gICAgXCJEQl9NQVhfQ09OTl9TSVpFXCI6IFwiMVwiXG4gIH1cblxuICBleHBvcnQgY2xhc3MgVGl0aWxlclBnc3RhY0FwaUxhbWJkYSBleHRlbmRzIENvbnN0cnVjdCB7XG4gICAgcmVhZG9ubHkgdXJsOiBzdHJpbmc7XG4gICAgcHVibGljIHRpdGlsZXJQZ3N0YWNMYW1iZGFGdW5jdGlvbjogbGFtYmRhLkZ1bmN0aW9uO1xuXG4gICAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IFRpdGlsZXJQZ1N0YWNBcGlMYW1iZGFQcm9wcykge1xuICAgICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgICAgdGhpcy50aXRpbGVyUGdzdGFjTGFtYmRhRnVuY3Rpb24gPSBuZXcgbGFtYmRhLkZ1bmN0aW9uKHRoaXMsIFwibGFtYmRhXCIsIHtcbiAgICAgICAgLy8gZGVmYXVsdHNcbiAgICAgICAgcnVudGltZTogbGFtYmRhLlJ1bnRpbWUuUFlUSE9OXzNfMTEsXG4gICAgICAgIGhhbmRsZXI6IFwiaGFuZGxlci5oYW5kbGVyXCIsXG4gICAgICAgIG1lbW9yeVNpemU6IDMwMDgsXG4gICAgICAgIGxvZ1JldGVudGlvbjogYXdzX2xvZ3MuUmV0ZW50aW9uRGF5cy5PTkVfV0VFSyxcbiAgICAgICAgdGltZW91dDogRHVyYXRpb24uc2Vjb25kcygzMCksXG4gICAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Eb2NrZXJCdWlsZChwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4nKSwge1xuICAgICAgICAgIGZpbGU6IFwidGl0aWxlci1wZ3N0YWMtYXBpL3J1bnRpbWUvRG9ja2VyZmlsZVwiLFxuICAgICAgICAgIGJ1aWxkQXJnczogeyBQWVRIT05fVkVSU0lPTjogJzMuMTEnIH1cbiAgICAgICAgfSksXG4gICAgICAgIHZwYzogcHJvcHMudnBjLFxuICAgICAgICB2cGNTdWJuZXRzOiBwcm9wcy5zdWJuZXRTZWxlY3Rpb24sXG4gICAgICAgIGFsbG93UHVibGljU3VibmV0OiB0cnVlLFxuICAgICAgICAvLyBpZiB1c2VyIHByb3ZpZGVkIGVudmlyb25tZW50IHZhcmlhYmxlcywgbWVyZ2UgdGhlbSB3aXRoIHRoZSBkZWZhdWx0cy5cbiAgICAgICAgZW52aXJvbm1lbnQ6IHByb3BzLmFwaUVudiA/IHsgLi4uZGVmYXVsdFRpdGlsZXJQZ3N0YWNFbnYsIC4uLnByb3BzLmFwaUVudiwgXCJQR1NUQUNfU0VDUkVUX0FSTlwiOiBwcm9wcy5kYlNlY3JldC5zZWNyZXRBcm4gfSA6IGRlZmF1bHRUaXRpbGVyUGdzdGFjRW52LFxuICAgICAgICAvLyBvdmVyd3JpdGVzIGRlZmF1bHRzIHdpdGggdXNlci1wcm92aWRlZCBjb25maWd1cmFibGUgcHJvcGVydGllc1xuICAgICAgICAuLi5wcm9wcy5sYW1iZGFGdW5jdGlvbk9wdGlvbnMsXG4gICAgICB9KTtcblxuICAgICAgLy8gZ3JhbnQgYWNjZXNzIHRvIGJ1Y2tldHMgdXNpbmcgYWRkVG9Sb2xlUG9saWN5XG4gICAgICBpZiAocHJvcHMuYnVja2V0cykge1xuICAgICAgICBwcm9wcy5idWNrZXRzLmZvckVhY2goYnVja2V0ID0+IHtcbiAgICAgICAgICB0aGlzLnRpdGlsZXJQZ3N0YWNMYW1iZGFGdW5jdGlvbi5hZGRUb1JvbGVQb2xpY3kobmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgICAgYWN0aW9uczogW1wiczM6R2V0T2JqZWN0XCJdLFxuICAgICAgICAgICAgcmVzb3VyY2VzOiBbYGFybjphd3M6czM6Ojoke2J1Y2tldH0vKmBdLFxuICAgICAgICAgIH0pKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHByb3BzLmRiU2VjcmV0LmdyYW50UmVhZCh0aGlzLnRpdGlsZXJQZ3N0YWNMYW1iZGFGdW5jdGlvbik7XG5cbiAgICAgIGlmIChwcm9wcy52cGMpIHtcbiAgICAgICAgdGhpcy50aXRpbGVyUGdzdGFjTGFtYmRhRnVuY3Rpb24uY29ubmVjdGlvbnMuYWxsb3dUbyhwcm9wcy5kYiwgZWMyLlBvcnQudGNwKDU0MzIpLCBcImFsbG93IGNvbm5lY3Rpb25zIGZyb20gdGl0aWxlclwiKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3RhY0FwaSA9IG5ldyBhcGlnYXRld2F5djIuSHR0cEFwaShcbiAgICAgICAgdGhpcyxcbiAgICAgICAgYCR7U3RhY2sub2YodGhpcykuc3RhY2tOYW1lfS10aXRpbGVyLXBnc3RhYy1hcGlgLFxuICAgICAgICB7XG4gICAgICAgICAgZGVmYXVsdERvbWFpbk1hcHBpbmc6IHByb3BzLnRpdGlsZXJQZ3N0YWNBcGlEb21haW5OYW1lXG4gICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICBkb21haW5OYW1lOiBwcm9wcy50aXRpbGVyUGdzdGFjQXBpRG9tYWluTmFtZSxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgICAgZGVmYXVsdEludGVncmF0aW9uOlxuICAgICAgICAgICAgbmV3IGFwaWdhdGV3YXl2Ml9pbnRlZ3JhdGlvbnMuSHR0cExhbWJkYUludGVncmF0aW9uKFxuICAgICAgICAgICAgICBcImludGVncmF0aW9uXCIsXG4gICAgICAgICAgICAgIHRoaXMudGl0aWxlclBnc3RhY0xhbWJkYUZ1bmN0aW9uLFxuICAgICAgICAgICAgICBwcm9wcy50aXRpbGVyUGdzdGFjQXBpRG9tYWluTmFtZVxuICAgICAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgICAgICBwYXJhbWV0ZXJNYXBwaW5nOlxuICAgICAgICAgICAgICAgICAgICAgIG5ldyBhcGlnYXRld2F5djIuUGFyYW1ldGVyTWFwcGluZygpLm92ZXJ3cml0ZUhlYWRlcihcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiaG9zdFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXBpZ2F0ZXdheXYyLk1hcHBpbmdWYWx1ZS5jdXN0b20oXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzLnRpdGlsZXJQZ3N0YWNBcGlEb21haW5OYW1lLm5hbWVcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDogdW5kZWZpbmVkXG4gICAgICAgICAgICApLFxuICAgICAgICB9XG4gICAgICApO1xuXG4gICAgICB0aGlzLnVybCA9IHN0YWNBcGkudXJsITtcblxuICAgICAgbmV3IENmbk91dHB1dCh0aGlzLCBcInRpdGlsZXItcGdzdGFjLWFwaS1vdXRwdXRcIiwge1xuICAgICAgICBleHBvcnROYW1lOiBgJHtTdGFjay5vZih0aGlzKS5zdGFja05hbWV9LXRpdGlsZXItcGdzdGFjLXVybGAsXG4gICAgICAgIHZhbHVlOiB0aGlzLnVybCxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGV4cG9ydCBpbnRlcmZhY2UgVGl0aWxlclBnU3RhY0FwaUxhbWJkYVByb3BzIHtcbiAgICAvKipcbiAgICAgKiBWUEMgaW50byB3aGljaCB0aGUgbGFtYmRhIHNob3VsZCBiZSBkZXBsb3llZC5cbiAgICAgKi9cbiAgICByZWFkb25seSB2cGM/OiBlYzIuSVZwYztcblxuICAgIC8qKlxuICAgICAqIFJEUyBJbnN0YW5jZSB3aXRoIGluc3RhbGxlZCBwZ1NUQUMgb3IgcGdib3VuY2VyIHNlcnZlci5cbiAgICAgKi9cbiAgICByZWFkb25seSBkYjogcmRzLklEYXRhYmFzZUluc3RhbmNlIHwgZWMyLklJbnN0YW5jZTtcblxuICAgIC8qKlxuICAgICAqIFN1Ym5ldCBpbnRvIHdoaWNoIHRoZSBsYW1iZGEgc2hvdWxkIGJlIGRlcGxveWVkLlxuICAgICAqL1xuICAgIHJlYWRvbmx5IHN1Ym5ldFNlbGVjdGlvbj86IGVjMi5TdWJuZXRTZWxlY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBTZWNyZXQgY29udGFpbmluZyBjb25uZWN0aW9uIGluZm9ybWF0aW9uIGZvciBwZ1NUQUMgZGF0YWJhc2UuXG4gICAgICovXG4gICAgcmVhZG9ubHkgZGJTZWNyZXQ6IHNlY3JldHNtYW5hZ2VyLklTZWNyZXQ7XG5cbiAgICAvKipcbiAgICAgKiBDdXN0b21pemVkIGVudmlyb25tZW50IHZhcmlhYmxlcyB0byBzZW5kIHRvIHRpdGlsZXItcGdzdGFjIHJ1bnRpbWUuIFRoZXNlIHdpbGwgYmUgbWVyZ2VkIHdpdGggYGRlZmF1bHRUaXRpbGVyUGdzdGFjRW52YC5cbiAgICAgKiBUaGUgZGF0YWJhc2Ugc2VjcmV0IGFybiBpcyBhdXRvbWF0aWNhbGx5IGFkZGVkIHRvIHRoZSBlbnZpcm9ubWVudCB2YXJpYWJsZXMgYXQgZGVwbG95bWVudC5cbiAgICAvKi9cbiAgICByZWFkb25seSBhcGlFbnY/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuXG4gICAgLyoqXG4gICAgICogbGlzdCBvZiBidWNrZXRzIHRoZSBsYW1iZGEgd2lsbCBiZSBncmFudGVkIGFjY2VzcyB0by5cbiAgICAgKi9cbiAgICByZWFkb25seSBidWNrZXRzPzogc3RyaW5nW107XG5cbiAgICAvKipcbiAgICAgKiBDdXN0b20gRG9tYWluIE5hbWUgT3B0aW9ucyBmb3IgVGl0aWxlciBQZ3N0YWMgQVBJLFxuICAgICAqXG4gICAgICogQGRlZmF1bHQgLSB1bmRlZmluZWQuXG4gICAgICovXG4gICAgcmVhZG9ubHkgdGl0aWxlclBnc3RhY0FwaURvbWFpbk5hbWU/OiBhcGlnYXRld2F5djIuSURvbWFpbk5hbWU7XG5cbiAgICAvKipcbiAgICAgKiBDYW4gYmUgdXNlZCB0byBvdmVycmlkZSB0aGUgZGVmYXVsdCBsYW1iZGEgZnVuY3Rpb24gcHJvcGVydGllcy5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0IC0gZGVmaW5lZCBpbiB0aGUgY29uc3RydWN0LlxuICAgICAqL1xuICAgIHJlYWRvbmx5IGxhbWJkYUZ1bmN0aW9uT3B0aW9ucz86IEN1c3RvbUxhbWJkYUZ1bmN0aW9uUHJvcHM7XG4gIH1cbiJdfQ==
|
package/package.json
CHANGED
package/pyproject.toml
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "eoapi-cdk"
|
|
3
|
+
version = "0.0"
|
|
4
|
+
requires-python = ">=3.11"
|
|
5
|
+
dependencies = [
|
|
6
|
+
"stactools-item-generator",
|
|
7
|
+
"stac-item-loader",
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
[tool.uv.sources]
|
|
11
|
+
stactools-item-generator = { workspace = true }
|
|
12
|
+
stac-item-loader = { workspace = true }
|
|
13
|
+
|
|
14
|
+
[tool.uv.workspace]
|
|
15
|
+
members = ["lib/stac-item-loader/runtime", "lib/stactools-item-generator/runtime"]
|
|
16
|
+
|
|
17
|
+
[dependency-groups]
|
|
18
|
+
deploy = [
|
|
19
|
+
"aws-cdk-lib==2.190.0",
|
|
20
|
+
"constructs==10.3.0",
|
|
21
|
+
"pydantic>=2.11.5",
|
|
22
|
+
"pydantic-settings[yaml]>=2.8.1",
|
|
23
|
+
"python-dotenv>=1.1.0",
|
|
24
|
+
"pyyaml>=6.0.2",
|
|
25
|
+
"types-pyyaml>=6.0.12.20250516",
|
|
26
|
+
]
|
|
27
|
+
dev = [
|
|
28
|
+
"aws-lambda-typing>=2.20.0",
|
|
29
|
+
"httpx>=0.28.1",
|
|
30
|
+
"pytest>=8.3.5",
|
|
31
|
+
"pytest-mock>=3.14.0",
|
|
32
|
+
"pytest-postgresql>=7.0.1",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[tool.pytest.ini_options]
|
|
36
|
+
addopts = "-vv --ignore=cdk.out --no-header --tb=native"
|
|
37
|
+
pythonpath = "."
|
|
38
|
+
testpaths = [
|
|
39
|
+
"lib/stactools-item-generator/runtime/tests",
|
|
40
|
+
"lib/stac-item-loader/runtime/tests",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[tool.ruff]
|
|
44
|
+
|
|
45
|
+
[tool.ruff.lint]
|