eoapi-cdk 11.5.0 → 11.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/.jsii +4 -4
  2. package/README.md +2 -0
  3. package/lib/bastion-host/index.js +1 -1
  4. package/lib/database/index.js +1 -1
  5. package/lib/ingestor-api/index.js +1 -1
  6. package/lib/ingestor-api/runtime/pyproject.toml +1 -1
  7. package/lib/ingestor-api/runtime/src/handler.py +27 -4
  8. package/lib/ingestor-api/runtime/uv.lock +437 -403
  9. package/lib/lambda-api-gateway/index.js +1 -1
  10. package/lib/lambda-api-gateway-private/index.js +1 -1
  11. package/lib/stac-api/index.js +2 -2
  12. package/lib/stac-api/runtime/README.md +36 -0
  13. package/lib/stac-api/runtime/pyproject.toml +2 -2
  14. package/lib/stac-api/runtime/src/stac_api/handler.py +82 -86
  15. package/lib/stac-api/runtime/uv.lock +205 -181
  16. package/lib/stac-auth-proxy/index.js +2 -2
  17. package/lib/stac-auth-proxy/runtime/pyproject.toml +2 -2
  18. package/lib/stac-auth-proxy/runtime/src/stac_auth_proxy_api/handler.py +25 -2
  19. package/lib/stac-auth-proxy/runtime/uv.lock +174 -248
  20. package/lib/stac-browser/index.js +1 -1
  21. package/lib/stac-loader/index.js +2 -2
  22. package/lib/stac-loader/runtime/Dockerfile +1 -0
  23. package/lib/stac-loader/runtime/src/stac_loader/handler.py +2 -25
  24. package/lib/stac-loader/runtime/uv.lock +250 -251
  25. package/lib/stactools-item-generator/index.js +1 -1
  26. package/lib/stactools-item-generator/runtime/uv.lock +79 -75
  27. package/lib/tipg-api/index.js +2 -2
  28. package/lib/tipg-api/runtime/pyproject.toml +1 -1
  29. package/lib/tipg-api/runtime/src/tipg_api/handler.py +85 -75
  30. package/lib/tipg-api/runtime/uv.lock +247 -242
  31. package/lib/titiler-pgstac-api/index.js +2 -2
  32. package/lib/titiler-pgstac-api/runtime/pyproject.toml +2 -2
  33. package/lib/titiler-pgstac-api/runtime/src/titiler_pgstac_api/handler.py +79 -50
  34. package/lib/titiler-pgstac-api/runtime/uv.lock +319 -280
  35. package/lib/utils/utils.py +49 -15
  36. package/package.json +4 -4
  37. package/uv.lock +44 -25
@@ -69,7 +69,7 @@ class TitilerPgstacApiLambdaRuntime extends constructs_1.Construct {
69
69
  }
70
70
  exports.TitilerPgstacApiLambdaRuntime = TitilerPgstacApiLambdaRuntime;
71
71
  _a = JSII_RTTI_SYMBOL_1;
72
- TitilerPgstacApiLambdaRuntime[_a] = { fqn: "eoapi-cdk.TitilerPgstacApiLambdaRuntime", version: "11.5.0" };
72
+ TitilerPgstacApiLambdaRuntime[_a] = { fqn: "eoapi-cdk.TitilerPgstacApiLambdaRuntime", version: "11.6.0" };
73
73
  class TitilerPgstacApiLambda extends constructs_1.Construct {
74
74
  constructor(scope, id, props) {
75
75
  super(scope, id);
@@ -109,5 +109,5 @@ class TitilerPgstacApiLambda extends constructs_1.Construct {
109
109
  }
110
110
  exports.TitilerPgstacApiLambda = TitilerPgstacApiLambda;
111
111
  _b = JSII_RTTI_SYMBOL_1;
112
- TitilerPgstacApiLambda[_b] = { fqn: "eoapi-cdk.TitilerPgstacApiLambda", version: "11.5.0" };
112
+ TitilerPgstacApiLambda[_b] = { fqn: "eoapi-cdk.TitilerPgstacApiLambda", version: "11.6.0" };
113
113
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZDQVdxQjtBQUNyQiwyQ0FBdUM7QUFDdkMsNkJBQTZCO0FBQzdCLDhEQUF5RDtBQUN6RCxvQ0FLa0I7QUFFbEIsNEVBQTRFO0FBQzVFLElBQUksdUJBQXVCLEdBQTJCO0lBQ3BELGdDQUFnQyxFQUFFLGlCQUFpQjtJQUNuRCxhQUFhLEVBQUUsS0FBSztJQUNwQiw0QkFBNEIsRUFBRSxXQUFXO0lBQ3pDLDJCQUEyQixFQUFFLE9BQU87SUFDcEMsa0NBQWtDLEVBQUUsS0FBSztJQUN6QyxtQkFBbUIsRUFBRSxLQUFLO0lBQzFCLGlCQUFpQixFQUFFLEdBQUc7SUFDdEIsY0FBYyxFQUFFLFFBQVE7SUFDeEIsU0FBUyxFQUFFLE1BQU07SUFDakIsY0FBYyxFQUFFLFNBQVM7SUFDekIsZ0JBQWdCLEVBQUUsR0FBRztJQUNyQixnQkFBZ0IsRUFBRSxHQUFHO0NBQ3RCLENBQUM7QUFFRixNQUFhLDZCQUE4QixTQUFRLHNCQUFTO0lBRzFELFlBQ0UsS0FBZ0IsRUFDaEIsRUFBVSxFQUNWLEtBQXlDO1FBRXpDLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsTUFBTSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsR0FBRyxrQkFBa0IsRUFBRSxHQUM3QyxLQUFLLENBQUMscUJBQXFCLElBQUksRUFBRSxDQUFDO1FBRXBDLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSx3QkFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFO1lBQ3hELFdBQVc7WUFDWCxPQUFPLEVBQUUsd0JBQU0sQ0FBQyxPQUFPLENBQUMsV0FBVztZQUNuQyxPQUFPLEVBQUUsb0NBQW9DO1lBQzdDLFVBQVUsRUFBRSxJQUFJO1lBQ2hCLFlBQVksRUFBRSxzQkFBUSxDQUFDLGFBQWEsQ0FBQyxRQUFRO1lBQzdDLE9BQU8s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QUM3QyxPQUFPLENBQUMsY0FBYyxFQUN0QixjQUFjLENBQ2YsQ0FBQztRQUNKLENBQUM7YUFBTSxDQUFDO1lBQ04sU0FBUyxHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUM7UUFDckMsQ0FBQztRQUVELE1BQU0sRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJLHFDQUFnQixDQUFDLElBQUksRUFBRSxvQkFBb0IsRUFBRTtZQUMvRCxjQUFjLEVBQUUsU0FBUztZQUN6QixVQUFVLEVBQUUsS0FBSyxDQUFDLFVBQVUsSUFBSSxLQUFLLENBQUMsMEJBQTBCO1NBQ2pFLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDLEdBQUksQ0FBQztRQUVwQixJQUFJLHVCQUFTLENBQUMsSUFBSSxFQUFFLDJCQUEyQixFQUFFO1lBQy9DLFVBQVUsRUFBRSxHQUFHLG1CQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMscUJBQXFCO1lBQzVELEtBQUssRUFBRSxJQUFJLENBQUMsR0FBRztTQUNoQixDQUFDLENBQUM7SUFDTCxDQUFDOztBQTlESCx3REErREMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBhd3NfYXBpZ2F0ZXdheXYyIGFzIGFwaWdhdGV3YXl2MixcbiAgYXdzX2xvZ3MsXG4gIENmbk91dHB1dCxcbiAgRHVyYXRpb24sXG4gIGF3c19lYzIgYXMgZWMyLFxuICBhd3NfaWFtIGFzIGlhbSxcbiAgYXdzX2xhbWJkYSBhcyBsYW1iZGEsXG4gIGF3c19yZHMgYXMgcmRzLFxuICBhd3Nfc2VjcmV0c21hbmFnZXIgYXMgc2VjcmV0c21hbmFnZXIsXG4gIFN0YWNrLFxufSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBMYW1iZGFBcGlHYXRld2F5IH0gZnJvbSBcIi4uL2xhbWJkYS1hcGktZ2F0ZXdheVwiO1xuaW1wb3J0IHtcbiAgQ3VzdG9tTGFtYmRhRnVuY3Rpb25Qcm9wcyxcbiAgcmVzb2x2ZUxhbWJkYUNvZGUsXG4gIGV4dHJhY3REYXRhYmFzZURlcGVuZGVuY2llcyxcbiAgY3JlYXRlTGFtYmRhVmVyc2lvbldpdGhEZXBlbmRlbmNpZXMsXG59IGZyb20gXCIuLi91dGlsc1wiO1xuXG4vLyBkZWZhdWx0IHNldHRpbmdzIHRoYXQgY2FuIGJlIG92ZXJyaWRkZW4gYnkgdGhlIHVzZXItcHJvdmlkZWQgZW52aXJvbm1lbnQuXG5sZXQgZGVmYXVsdFRpdGlsZXJQZ3N0YWNFbnY6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gIENQTF9WU0lMX0NVUkxfQUxMT1dFRF9FWFRFTlNJT05TOiBcIi50aWYsLlRJRiwudGlmZlwiLFxuICBHREFMX0NBQ0hFTUFYOiBcIjIwMFwiLFxuICBHREFMX0RJU0FCTEVfUkVBRERJUl9PTl9PUEVOOiBcIkVNUFRZX0RJUlwiLFxuICBHREFMX0lOR0VTVEVEX0JZVEVTX0FUX09QRU46IFwiMzI3NjhcIixcbiAgR0RBTF9IVFRQX01FUkdFX0NPTlNFQ1VUSVZFX1JBTkdFUzogXCJZRVNcIixcbiAgR0RBTF9IVFRQX01VTFRJUExFWDogXCJZRVNcIixcbiAgR0RBTF9IVFRQX1ZFUlNJT046IFwiMlwiLFxuICBQWVRIT05XQVJOSU5HUzogXCJpZ25vcmVcIixcbiAgVlNJX0NBQ0hFOiBcIlRSVUVcIixcbiAgVlNJX0NBQ0hFX1NJWkU6IFwiNTAwMDAwMFwiLFxuICBEQl9NSU5fQ09OTl9TSVpFOiBcIjFcIixcbiAgREJfTUFYX0NPTk5fU0laRTogXCIxXCIsXG59O1xuXG5leHBvcnQgY2xhc3MgVGl0aWxlclBnc3RhY0FwaUxhbWJkYVJ1bnRpbWUgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBwdWJsaWMgcmVhZG9ubHkgbGFtYmRhRnVuY3Rpb246IGxhbWJkYS5GdW5jdGlvbjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIGlkOiBzdHJpbmcsXG4gICAgcHJvcHM6IFRpdGlsZXJQZ3N0YWNBcGlMYW1iZGFSdW50aW1lUHJvcHMsXG4gICkge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBjb25zdCB7IGNvZGU6IHVzZXJDb2RlLCAuLi5vdGhlckxhbWJkYU9wdGlvbnMgfSA9XG4gICAgICBwcm9wcy5sYW1iZGFGdW5jdGlvbk9wdGlvbnMgfHwge307XG5cbiAgICB0aGlzLmxhbWJkYUZ1bmN0aW9uID0gbmV3IGxhbWJkYS5GdW5jdGlvbih0aGlzLCBcImxhbWJkYVwiLCB7XG4gICAgICAvLyBkZWZhdWx0c1xuICAgICAgcnVudGltZTogbGFtYmRhLlJ1bnRpbWUuUFlUSE9OXzNfMTIsXG4gICAgICBoYW5kbGVyOiBcInRpdGlsZXJfcGdzdGFjX2FwaS5oYW5kbGVyLmhhbmRsZXJcIixcbiAgICAgIG1lbW9yeVNpemU6IDMwMDgsXG4gICAgICBsb2dSZXRlbnRpb246IGF3c19sb2dzLlJldGVudGlvbkRheXMuT05FX1dFRUssXG4gICAgICB0aW1lb3V0OiBEdXJhdGlvbi5zZWNvbmRzKDMwKSxcbiAgICAgIGNvZGU6IHJlc29sdmVMYW1iZGFDb2RlKHVzZXJDb2RlLCBwYXRoLmpvaW4oX19kaXJuYW1lLCBcIi4uXCIpLCB7XG4gICAgICAgIGZpbGU6IFwidGl0aWxlci1wZ3N0YWMtYXBpL3J1bnRpbWUvRG9ja2VyZmlsZVwiLFxuICAgICAgICBidWlsZEFyZ3M6IHsgUFlUSE9OX1ZFUlNJT046IFwiMy4xMlwiIH0sXG4gICAgICB9KSxcbiAgICAgIHZwYzogcHJvcHMudnBjLFxuICAgICAgdnBjU3VibmV0czogcHJvcHMuc3VibmV0U2VsZWN0aW9uLFxuICAgICAgYWxsb3dQdWJsaWNTdWJuZXQ6IHRydWUsXG4gICAgICBlbnZpcm9ubWVudDoge1xuICAgICAgICAuLi5kZWZhdWx0VGl0aWxlclBnc3RhY0VudixcbiAgICAgICAgLi4ucHJvcHMuYXBpRW52LCAvLyBpZiB1c2VyIHByb3ZpZGVkIGVudmlyb25tZW50IHZhcmlhYmxlcywgbWVyZ2UgdGhlbSB3aXRoIHRoZSBkZWZhdWx0cy5cbiAgICAgICAgUEdTVEFDX1NFQ1JFVF9BUk46IHByb3BzLmRiU2VjcmV0LnNlY3JldEFybixcbiAgICAgIH0sXG4gICAgICBzbmFwU3RhcnQ6IHByb3BzLmVuYWJsZVNuYXBTdGFydFxuICAgICAgICA/IGxhbWJkYS5TbmFwU3RhcnRDb25mLk9OX1BVQkxJU0hFRF9WRVJTSU9OU1xuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgIC8vIG92ZXJ3cml0ZXMgZGVmYXVsdHMgd2l0aCB1c2VyLXByb3ZpZGVkIGNvbmZpZ3VyYWJsZSBwcm9wZXJ0aWVzIChleGNsdWRpbmcgY29kZSlcbiAgICAgIC4uLm90aGVyTGFtYmRhT3B0aW9ucyxcbiAgICB9KTtcblxuICAgIC8vIGdyYW50IGFjY2VzcyB0byBidWNrZXRzIHVzaW5nIGFkZFRvUm9sZVBvbGljeVxuICAgIGlmIChwcm9wcy5idWNrZXRzKSB7XG4gICAgICBwcm9wcy5idWNrZXRzLmZvckVhY2goKGJ1Y2tldCkgPT4ge1xuICAgICAgICB0aGlzLmxhbWJkYUZ1bmN0aW9uLmFkZFRvUm9sZVBvbGljeShcbiAgICAgICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgICBhY3Rpb25zOiBbXCJzMzpHZXRPYmplY3RcIl0sXG4gICAgICAgICAgICByZXNvdXJjZXM6IFtgYXJuOmF3czpzMzo6OiR7YnVja2V0fS8qYF0sXG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBwcm9wcy5kYlNlY3JldC5ncmFudFJlYWQodGhpcy5sYW1iZGFGdW5jdGlvbik7XG5cbiAgICBpZiAocHJvcHMudnBjKSB7XG4gICAgICB0aGlzLmxhbWJkYUZ1bmN0aW9uLmNvbm5lY3Rpb25zLmFsbG93VG8oXG4gICAgICAgIHByb3BzLmRiLFxuICAgICAgICBlYzIuUG9ydC50Y3AoNTQzMiksXG4gICAgICAgIFwiYWxsb3cgY29ubmVjdGlvbnMgZnJvbSB0aXRpbGVyXCIsXG4gICAgICApO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRpdGlsZXJQZ3N0YWNBcGlMYW1iZGFSdW50aW1lUHJvcHMge1xuICAvKipcbiAgICogVlBDIGludG8gd2hpY2ggdGhlIGxhbWJkYSBzaG91bGQgYmUgZGVwbG95ZWQuXG4gICAqL1xuICByZWFkb25seSB2cGM/OiBlYzIuSVZwYztcblxuICAvKipcbiAgICogUkRTIEluc3RhbmNlIHdpdGggaW5zdGFsbGVkIHBnU1RBQyBvciBwZ2JvdW5jZXIgc2VydmVyLlxuICAgKi9cbiAgcmVhZG9ubHkgZGI6IHJkcy5JRGF0YWJhc2VJbnN0YW5jZSB8IGVjMi5JSW5zdGFuY2U7XG5cbiAgLyoqXG4gICAqIFN1Ym5ldCBpbnRvIHdoaWNoIHRoZSBsYW1iZGEgc2hvdWxkIGJlIGRlcGxveWVkLlxuICAgKi9cbiAgcmVhZG9ubHkgc3VibmV0U2VsZWN0aW9uPzogZWMyLlN1Ym5ldFNlbGVjdGlvbjtcblxuICAvKipcbiAgICogU2VjcmV0IGNvbnRhaW5pbmcgY29ubmVjdGlvbiBpbmZvcm1hdGlvbiBmb3IgcGdTVEFDIGRhdGFiYXNlLlxuICAgKi9cbiAgcmVhZG9ubHkgZGJTZWNyZXQ6IHNlY3JldHNtYW5hZ2VyLklTZWNyZXQ7XG5cbiAgLyoqXG4gICAqIEN1c3RvbWl6ZWQgZW52aXJvbm1lbnQgdmFyaWFibGVzIHRvIHNlbmQgdG8gdGl0aWxlci1wZ3N0YWMgcnVudGltZS4gVGhlc2Ugd2lsbCBiZSBtZXJnZWQgd2l0aCBgZGVmYXVsdFRpdGlsZXJQZ3N0YWNFbnZgLlxuICAgKiBUaGUgZGF0YWJhc2Ugc2VjcmV0IGFybiBpcyBhdXRvbWF0aWNhbGx5IGFkZGVkIHRvIHRoZSBlbnZpcm9ubWVudCB2YXJpYWJsZXMgYXQgZGVwbG95bWVudC5cbiAgICovXG4gIHJlYWRvbmx5IGFwaUVudj86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG5cbiAgLyoqXG4gICAqIGxpc3Qgb2YgYnVja2V0cyB0aGUgbGFtYmRhIHdpbGwgYmUgZ3JhbnRlZCBhY2Nlc3MgdG8uXG4gICAqL1xuICByZWFkb25seSBidWNrZXRzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIEVuYWJsZSBTbmFwU3RhcnQgdG8gcmVkdWNlIGNvbGQgc3RhcnQgbGF0ZW5jeS5cbiAgICpcbiAgICogU25hcFN0YXJ0IGNyZWF0ZXMgYSBzbmFwc2hvdCBvZiB0aGUgaW5pdGlhbGl6ZWQgTGFtYmRhIGZ1bmN0aW9uLCBhbGxvd2luZyBuZXcgaW5zdGFuY2VzXG4gICAqIHRvIHN0YXJ0IGZyb20gdGhpcyBwcmUtaW5pdGlhbGl6ZWQgc3RhdGUgaW5zdGVhZCBvZiBzdGFydGluZyBmcm9tIHNjcmF0Y2guXG4gICAqXG4gICAqIEJlbmVmaXRzOlxuICAgKiAtIFNpZ25pZmljYW50bHkgcmVkdWNlcyBjb2xkIHN0YXJ0IHRpbWVzICh0eXBpY2FsbHkgMTB4IGZhc3RlcilcbiAgICogLSBJbXByb3ZlcyBBUEkgcmVzcG9uc2UgdGltZSBmb3IgaW5mcmVxdWVudCByZXF1ZXN0c1xuICAgKlxuICAgKiBDb25zaWRlcmF0aW9uczpcbiAgICogLSBBZGRpdGlvbmFsIGNvc3Q6IGNoYXJnZXMgZm9yIHNuYXBzaG90IHN0b3JhZ2UgYW5kIHJlc3RvcmUgb3BlcmF0aW9uc1xuICAgKiAtIFJlcXVpcmVzIExhbWJkYSB2ZXJzaW9uaW5nIChhdXRvbWF0aWNhbGx5IGNvbmZpZ3VyZWQgYnkgdGhpcyBjb25zdHJ1Y3QpXG4gICAqIC0gRGF0YWJhc2UgY29ubmVjdGlvbnMgYXJlIHJlY3JlYXRlZCBvbiByZXN0b3JlIHVzaW5nIHNuYXBzaG90IGxpZmVjeWNsZSBob29rc1xuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9sYW1iZGEvbGF0ZXN0L2RnL3NuYXBzdGFydC5odG1sXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBlbmFibGVTbmFwU3RhcnQ/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBDYW4gYmUgdXNlZCB0byBvdmVycmlkZSB0aGUgZGVmYXVsdCBsYW1iZGEgZnVuY3Rpb24gcHJvcGVydGllcy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBkZWZpbmVkIGluIHRoZSBjb25zdHJ1Y3QuXG4gICAqL1xuICByZWFkb25seSBsYW1iZGFGdW5jdGlvbk9wdGlvbnM/OiBDdXN0b21MYW1iZGFGdW5jdGlvblByb3BzO1xufVxuXG5leHBvcnQgY2xhc3MgVGl0aWxlclBnc3RhY0FwaUxhbWJkYSBleHRlbmRzIENvbnN0cnVjdCB7XG4gIC8qKlxuICAgKiBVUkwgZm9yIHRoZSBUaXRpbGVyIFBnc3RhYyBBUEkuXG4gICAqL1xuICByZWFkb25seSB1cmw6IHN0cmluZztcblxuICAvKipcbiAgICogTGFtYmRhIGZ1bmN0aW9uIGZvciB0aGUgVGl0aWxlciBQZ3N0YWMgQVBJLlxuICAgKi9cbiAgcmVhZG9ubHkgbGFtYmRhRnVuY3Rpb246IGxhbWJkYS5GdW5jdGlvbjtcblxuICAvKipcbiAgICogQGRlcHJlY2F0ZWQgLSB1c2UgbGFtYmRhRnVuY3Rpb24gaW5zdGVhZFxuICAgKi9cbiAgcHVibGljIHRpdGlsZXJQZ3N0YWNMYW1iZGFGdW5jdGlvbjogbGFtYmRhLkZ1bmN0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHNjb3BlOiBDb25zdHJ1Y3QsXG4gICAgaWQ6IHN0cmluZyxcbiAgICBwcm9wczogVGl0aWxlclBnc3RhY0FwaUxhbWJkYVByb3BzLFxuICApIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgY29uc3QgcnVudGltZSA9IG5ldyBUaXRpbGVyUGdzdGFjQXBpTGFtYmRhUnVudGltZSh0aGlzLCBcInJ1bnRpbWVcIiwge1xuICAgICAgdnBjOiBwcm9wcy52cGMsXG4gICAgICBzdWJuZXRTZWxlY3Rpb246IHByb3BzLnN1Ym5ldFNlbGVjdGlvbixcbiAgICAgIGRiOiBwcm9wcy5kYixcbiAgICAgIGRiU2VjcmV0OiBwcm9wcy5kYlNlY3JldCxcbiAgICAgIGFwaUVudjogcHJvcHMuYXBpRW52LFxuICAgICAgYnVja2V0czogcHJvcHMuYnVja2V0cyxcbiAgICAgIGVuYWJsZVNuYXBTdGFydDogcHJvcHMuZW5hYmxlU25hcFN0YXJ0LFxuICAgICAgbGFtYmRhRnVuY3Rpb25PcHRpb25zOiBwcm9wcy5sYW1iZGFGdW5jdGlvbk9wdGlvbnMsXG4gICAgfSk7XG4gICAgdGhpcy50aXRpbGVyUGdzdGFjTGFtYmRhRnVuY3Rpb24gPSB0aGlzLmxhbWJkYUZ1bmN0aW9uID1cbiAgICAgIHJ1bnRpbWUubGFtYmRhRnVuY3Rpb247XG5cbiAgICAvLyBEZXRlcm1pbmUgd2hpY2ggbGFtYmRhIHRvIHVzZSBmb3IgQVBJIEdhdGV3YXlcbiAgICBsZXQgYXBpTGFtYmRhOiBsYW1iZGEuRnVuY3Rpb24gfCBsYW1iZGEuVmVyc2lvbjtcbiAgICBpZiAocHJvcHMuZW5hYmxlU25hcFN0YXJ0KSB7XG4gICAgICAvLyBFeHRyYWN0IGRlcGVuZGVuY2llcyBmcm9tIGRhdGFiYXNlIGlmIGl0J3MgYSBQZ1N0YWNEYXRhYmFzZSB3aXRoIFBnQm91bmNlclxuICAgICAgY29uc3QgZGJEZXBlbmRlbmNpZXMgPSBleHRyYWN0RGF0YWJhc2VEZXBlbmRlbmNpZXMocHJvcHMuZGIpO1xuXG4gICAgICAvLyBDcmVhdGUgdmVyc2lvbiB3aXRoIGRlcGVuZGVuY2llcyB0byBlbnN1cmUgc25hcHNob3QgY3JlYXRpb24gd2FpdHNcbiAgICAgIGFwaUxhbWJkYSA9IGNyZWF0ZUxhbWJkYVZlcnNpb25XaXRoRGVwZW5kZW5jaWVzKFxuICAgICAgICBydW50aW1lLmxhbWJkYUZ1bmN0aW9uLFxuICAgICAgICBkYkRlcGVuZGVuY2llcyxcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFwaUxhbWJkYSA9IHJ1bnRpbWUubGFtYmRhRnVuY3Rpb247XG4gICAgfVxuXG4gICAgY29uc3QgeyBhcGkgfSA9IG5ldyBMYW1iZGFBcGlHYXRld2F5KHRoaXMsIFwidGl0bGllci1wZ3N0YWMtYXBpXCIsIHtcbiAgICAgIGxhbWJkYUZ1bmN0aW9uOiBhcGlMYW1iZGEsXG4gICAgICBkb21haW5OYW1lOiBwcm9wcy5kb21haW5OYW1lID8/IHByb3BzLnRpdGlsZXJQZ3N0YWNBcGlEb21haW5OYW1lLFxuICAgIH0pO1xuXG4gICAgdGhpcy51cmwgPSBhcGkudXJsITtcblxuICAgIG5ldyBDZm5PdXRwdXQodGhpcywgXCJ0aXRpbGVyLXBnc3RhYy1hcGktb3V0cHV0XCIsIHtcbiAgICAgIGV4cG9ydE5hbWU6IGAke1N0YWNrLm9mKHRoaXMpLnN0YWNrTmFtZX0tdGl0aWxlci1wZ3N0YWMtdXJsYCxcbiAgICAgIHZhbHVlOiB0aGlzLnVybCxcbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRpdGlsZXJQZ3N0YWNBcGlMYW1iZGFQcm9wc1xuICBleHRlbmRzIFRpdGlsZXJQZ3N0YWNBcGlMYW1iZGFSdW50aW1lUHJvcHMge1xuICAvKipcbiAgICogRG9tYWluIE5hbWUgZm9yIHRoZSBUaXRpbGVyIFBnc3RhYyBBUEkuIElmIGRlZmluZWQsIHdpbGwgY3JlYXRlIHRoZSBkb21haW4gbmFtZSBhbmQgaW50ZWdyYXRlIGl0IHdpdGggdGhlIFRpdGlsZXIgUGdzdGFjIEFQSS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSB1bmRlZmluZWQuXG4gICAqL1xuICByZWFkb25seSBkb21haW5OYW1lPzogYXBpZ2F0ZXdheXYyLklEb21haW5OYW1lO1xuXG4gIC8qKlxuICAgKiBDdXN0b20gRG9tYWluIE5hbWUgT3B0aW9ucyBmb3IgVGl0aWxlciBQZ3N0YWMgQVBJLFxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBVc2UgJ2RvbWFpbk5hbWUnIGluc3RlYWQuXG4gICAqIEBkZWZhdWx0IC0gdW5kZWZpbmVkLlxuICAgKi9cbiAgcmVhZG9ubHkgdGl0aWxlclBnc3RhY0FwaURvbWFpbk5hbWU/OiBhcGlnYXRld2F5djIuSURvbWFpbk5hbWU7XG59XG4iXX0=
@@ -4,8 +4,8 @@ version = "0.0.0"
4
4
  description = "titiler-pgstac-api runtime"
5
5
  requires-python = ">=3.12"
6
6
  dependencies = [
7
- "mangum==0.19",
8
- "titiler-pgstac[psycopg-binary]>=2.0.0,<2.1.0",
7
+ "mangum>=0.21.0",
8
+ "titiler-pgstac[psycopg-binary]>=2.1.0,<3.0.0",
9
9
  ]
10
10
 
11
11
  [dependency-groups]
@@ -1,18 +1,22 @@
1
- """
2
- Handler for AWS Lambda.
3
- """
1
+ """Handler for AWS Lambda."""
4
2
 
5
- import asyncio
3
+ import logging
6
4
  import os
5
+ from collections.abc import AsyncIterator, Mapping
6
+ from contextlib import asynccontextmanager
7
+ from typing import Any
7
8
 
8
9
  from mangum import Mangum
9
10
  from snapshot_restore_py import register_after_restore, register_before_snapshot
10
- from titiler.pgstac.db import connect_to_db
11
+ from titiler.pgstac.db import close_db_connection, connect_to_db
11
12
  from titiler.pgstac.main import app
12
13
  from titiler.pgstac.settings import PostgresSettings
13
- from utils import get_secret_dict
14
+ from utils import ensure_event_loop, get_secret_dict, run_async
15
+
16
+ logger = logging.getLogger(__name__)
14
17
 
15
18
  _connection_initialized = False
19
+ _original_lifespan = app.router.lifespan_context
16
20
 
17
21
 
18
22
  def _build_postgres_settings() -> PostgresSettings:
@@ -27,69 +31,94 @@ def _build_postgres_settings() -> PostgresSettings:
27
31
  )
28
32
 
29
33
 
30
- @register_before_snapshot
31
- def on_snapshot():
32
- """
33
- Runtime hook called by Lambda before taking a snapshot.
34
- We close database connections that shouldn't be in the snapshot.
35
- """
36
-
37
- # Close any existing database connections before the snapshot is taken
34
+ def _close_db_pool() -> None:
35
+ """Close the current database pool if one exists."""
38
36
  if hasattr(app, "state") and hasattr(app.state, "dbpool") and app.state.dbpool:
39
37
  try:
40
38
  app.state.dbpool.close()
39
+ except Exception:
40
+ logger.exception("SnapStart: error closing database pool")
41
+ finally:
41
42
  app.state.dbpool = None
42
- except Exception as e:
43
- print(f"SnapStart: Error closing database pool: {e}")
44
43
 
45
- return {"statusCode": 200}
46
44
 
45
+ async def _initialize_connection() -> None:
46
+ """Create a fresh database connection pool for the application."""
47
+ global _connection_initialized
47
48
 
48
- @register_after_restore
49
- def on_snap_restore():
50
- """
51
- Runtime hook called by Lambda after restoring from a snapshot.
52
- We recreate database connections that were closed before the snapshot.
53
- """
49
+ _close_db_pool()
50
+ await connect_to_db(app, settings=_build_postgres_settings())
51
+ _connection_initialized = True
52
+
53
+
54
+ async def _shutdown_connection() -> None:
55
+ """Close the current database connection pool if it exists."""
54
56
  global _connection_initialized
55
57
 
56
- try:
57
- # Get the event loop or create a new one
58
- try:
59
- loop = asyncio.get_running_loop()
60
- except RuntimeError:
61
- loop = asyncio.new_event_loop()
62
- asyncio.set_event_loop(loop)
63
-
64
- # Close any existing pool (from snapshot)
65
- if hasattr(app.state, "dbpool") and app.state.dbpool:
66
- try:
67
- app.state.dbpool.close()
68
- except Exception as e:
69
- print(f"SnapStart: Error closing stale pool: {e}")
70
- app.state.dbpool = None
58
+ if hasattr(app, "state") and hasattr(app.state, "dbpool") and app.state.dbpool:
59
+ await close_db_connection(app)
60
+ app.state.dbpool = None
61
+
62
+ _connection_initialized = False
71
63
 
72
- # Create fresh connection pool
73
- loop.run_until_complete(connect_to_db(app, settings=_build_postgres_settings()))
74
64
 
75
- _connection_initialized = True
65
+ @register_before_snapshot
66
+ def on_snapshot() -> dict[str, int]:
67
+ """Close database connections before Lambda SnapStart takes a snapshot."""
68
+ _close_db_pool()
69
+ return {"statusCode": 200}
70
+
76
71
 
77
- except Exception as e:
78
- print(f"SnapStart: Failed to initialize database connection: {e}")
72
+ @register_after_restore
73
+ def on_snap_restore() -> dict[str, int]:
74
+ """Recreate database connections after Lambda SnapStart restores a snapshot."""
75
+ try:
76
+ run_async(_initialize_connection())
77
+ except Exception:
78
+ logger.exception("SnapStart: failed to initialize database connection")
79
79
  raise
80
80
 
81
81
  return {"statusCode": 200}
82
82
 
83
83
 
84
- @app.on_event("startup")
85
- async def startup_event() -> None:
86
- """Connect to database on startup."""
87
- await connect_to_db(app, settings=_build_postgres_settings())
84
+ @asynccontextmanager
85
+ async def lifespan(app_instance) -> AsyncIterator[Mapping[str, Any] | None]:
86
+ """Wrap the upstream lifespan with database setup and teardown.
88
87
 
88
+ We keep the app's lifespan wiring intact for non-Lambda contexts, but the
89
+ Lambda runtime below uses ``Mangum(..., lifespan="off")`` and performs
90
+ connection setup explicitly. In sandbox testing, Mangum lifespan handling
91
+ was not a drop-in replacement for Lambda-container-scoped pool reuse.
92
+ """
93
+ async with _original_lifespan(app_instance) as state:
94
+ await _initialize_connection()
95
+ try:
96
+ yield state
97
+ finally:
98
+ await _shutdown_connection()
99
+
100
+
101
+ app.router.lifespan_context = lifespan
89
102
 
90
- handler = Mangum(app, lifespan="off")
103
+ # The Lambda runtime initializes long-lived async resources on an installed
104
+ # reusable loop, then hands request execution to Mangum. ``ensure_event_loop``
105
+ # is a defensive step for those synchronous initialization paths. It is not here
106
+ # because normal FastAPI route execution cannot run without it.
107
+ _asgi_handler = Mangum(app, lifespan="off")
108
+
109
+
110
+ def handler(event: Any, context: Any) -> dict[str, Any]:
111
+ """Handle AWS Lambda events with a reusable installed event loop.
112
+
113
+ This supports synchronous Lambda-side async setup such as cold-start and
114
+ SnapStart restore initialization before control passes to Mangum.
115
+ """
116
+ ensure_event_loop()
117
+ return _asgi_handler(event, context)
91
118
 
92
119
 
93
120
  if "AWS_EXECUTION_ENV" in os.environ:
94
- loop = asyncio.get_event_loop()
95
- loop.run_until_complete(app.router.startup())
121
+ # Avoid ``asyncio.run(...)`` here. It would create the pool on a temporary
122
+ # loop and then close it, which is a poor fit for container-scoped async
123
+ # resources that should live on the installed reusable loop.
124
+ run_async(_initialize_connection())