diff --git a/batch-requests.md b/batch-requests.md new file mode 100644 index 0000000..a50010f --- /dev/null +++ b/batch-requests.md @@ -0,0 +1,806 @@ +# CAP Java: OData V4 Batch Request Handling + +## Overview + +This document explains OData V4 Batch requests and how SAP Cloud Application Programming Model (CAP) for Java handles them. Batch requests enable clients to bundle multiple operations into a single HTTP request, reducing network overhead and improving performance in distributed systems. + +--- + +## 1. What are OData V4 Batch Requests? + +### 1.1 Definition + +OData V4 Batch requests allow clients to group multiple individual requests (queries, creates, updates, deletes) into a single HTTP POST request. The server processes these requests and returns all responses bundled together in a single HTTP response. + +### 1.2 Key Characteristics + +- **Single HTTP Request**: Multiple operations sent in one HTTP POST to `$batch` endpoint +- **Multipart Format**: Uses multipart/mixed content type with boundary delimiters +- **Change Sets**: Operations can be grouped into atomic transactions (changesets) +- **Independent Requests**: Queries outside changesets are processed independently +- **Reduced Latency**: Fewer HTTP roundtrips improve performance +- **Transaction Control**: Changesets provide all-or-nothing execution semantics + +### 1.3 Structure + +``` +POST /odata/v4/IncidentService/$batch HTTP/1.1 +Content-Type: multipart/mixed; boundary=batch_boundary + +--batch_boundary +Content-Type: multipart/mixed; boundary=changeset_boundary + +--changeset_boundary +Content-Type: application/http +Content-Transfer-Encoding: binary + +POST Incidents HTTP/1.1 +Content-Type: application/json + +{ + "title": "Network outage", + "urgency": "high" +} + +--changeset_boundary +Content-Type: application/http +Content-Transfer-Encoding: binary + +PATCH Incidents(ID=f60f5c43-3c6e-4c79-bb18-23cf314c55e4) HTTP/1.1 +Content-Type: application/json + +{ + "status": "closed" +} + +--changeset_boundary-- + +--batch_boundary +Content-Type: application/http +Content-Transfer-Encoding: binary + +GET Incidents HTTP/1.1 + +--batch_boundary-- +``` + +--- + +## 2. OData V4 Batch Concepts + +### 2.1 Batch Boundary + +- Separates individual requests within the batch +- Defined in the `Content-Type` header +- Format: `multipart/mixed; boundary=` +- Each part starts with `--` +- Batch ends with `----` + +### 2.2 ChangeSet + +A changeset is a group of operations that must be executed atomically: + +- **Atomic Transaction**: All operations succeed or all fail +- **Supported Operations**: CREATE, UPDATE (PUT/PATCH), DELETE +- **Not Allowed**: GET requests cannot be in changesets +- **Own Boundary**: Uses nested multipart with changeset boundary +- **Rollback**: On any failure, all changes in the changeset are rolled back + +### 2.3 Request Types + +**Within ChangeSet (Transactional)**: +- POST (Create) +- PATCH (Update) +- PUT (Replace) +- DELETE (Delete) + +**Outside ChangeSet (Independent)**: +- GET (Query) +- Can also include modification operations that should run independently + +### 2.4 Content References + +Batch requests support `Content-ID` headers to reference created entities within the same batch: + +``` +--changeset_boundary +Content-Type: application/http +Content-Transfer-Encoding: binary +Content-ID: 1 + +POST Incidents HTTP/1.1 +Content-Type: application/json + +{ + "title": "Server down" +} + +--changeset_boundary +Content-Type: application/http +Content-Transfer-Encoding: binary + +POST $1/conversations HTTP/1.1 +Content-Type: application/json + +{ + "message": "Investigating the issue" +} +``` + +Here `$1` references the Incident created in the first request. + +--- + +## 3. CAP Java Batch Request Processing + +### 3.1 Architecture Overview + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ CAP Java Batch Processing │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌──────────────────┐ ┌────────────────┐ ┌───────────────────────┐ │ +│ │ OData Adapter │ │ Batch Executor │ │ Transaction Manager │ │ +│ │ │───▶│ │───▶│ │ │ +│ │ - Parse batch │ │ - Process each │ │ - Begin transaction │ │ +│ │ - Extract parts │ │ request │ │ - Commit/rollback │ │ +│ │ - Build response│ │ - Handle refs │ │ - Savepoint support │ │ +│ └──────────────────┘ └────────────────┘ └───────────────────────┘ │ +│ │ │ │ │ +│ │ ▼ ▼ │ +│ │ ┌────────────────┐ ┌─────────────────────┐ │ +│ │ │ CQN Executor │ │ Database (HANA, │ │ +│ │ │ │─────▶│ H2, PostgreSQL, │ │ +│ │ │ - Build CQN │ │ SQLite) │ │ +│ │ │ - Execute ops │ └─────────────────────┘ │ +│ │ └────────────────┘ │ +│ │ │ +│ └──────────────────▶ Serialize Batch Response │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 3.2 Request Flow + +``` +┌─────────────┐ +│ Client │ +└──────┬──────┘ + │ + │ POST /$batch + │ (multipart/mixed) + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 1. ODataServlet / Request Handler │ +│ - Receives HTTP request │ +│ - Routes to batch endpoint │ +└────────────────────────┬────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 2. Batch Request Parser │ +│ - Parse multipart/mixed content │ +│ - Extract individual request parts │ +│ - Identify changesets vs independent requests │ +│ - Parse Content-ID headers │ +└────────────────────────┬────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 3. Batch Executor │ +│ ┌───────────────────────────────────────────────────┐ │ +│ │ For each ChangeSet: │ │ +│ │ - Begin transaction │ │ +│ │ - Execute all operations in order │ │ +│ │ - Track Content-IDs for references │ │ +│ │ - If any fails: Rollback entire changeset │ │ +│ │ - If all succeed: Commit changeset │ │ +│ └───────────────────────────────────────────────────┘ │ +│ ┌───────────────────────────────────────────────────┐ │ +│ │ For each Independent Request: │ │ +│ │ - Execute immediately │ │ +│ │ - Failure doesn't affect other requests │ │ +│ └───────────────────────────────────────────────────┘ │ +└────────────────────────┬────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 4. Individual Request Processing │ +│ - Parse OData request (GET, POST, PATCH, DELETE) │ +│ - Convert to CQN query/statement │ +│ - Trigger event handlers (@Before/@On/@After) │ +│ - Execute against persistence service │ +│ - Collect response │ +└────────────────────────┬────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 5. Response Builder │ +│ - Collect all individual responses │ +│ - Build multipart/mixed response │ +│ - Include status codes for each operation │ +│ - Map Content-IDs to results │ +└────────────────────────┬────────────────────────────────────┘ + │ + ▼ + ┌────────┐ + │ Client │ + └────────┘ +``` + +### 3.3 Transaction Management + +CAP Java handles transactions for batch requests as follows: + +**ChangeSet Processing**: +```java +// Pseudo-code representation +for (ChangeSet changeSet : batch.getChangeSets()) { + try { + transaction.begin(); + + for (Request request : changeSet.getRequests()) { + Result result = processRequest(request); + results.add(result); + + // Track Content-ID for references + if (request.hasContentId()) { + contentIdMap.put(request.getContentId(), result.getEntity()); + } + } + + transaction.commit(); + } catch (Exception e) { + transaction.rollback(); + // Add error response for entire changeset + results.addChangeSetError(e); + } +} +``` + +**Independent Request Processing**: +```java +// Each request runs in its own transaction +for (Request request : batch.getIndependentRequests()) { + try { + Result result = processRequest(request); + results.add(result); + } catch (Exception e) { + // Error only affects this request + results.addError(request, e); + } +} +``` + +### 3.4 Event Handler Execution + +Event handlers are executed for each operation within the batch: + +```java +@Component +@ServiceName("IncidentService") +public class IncidentServiceHandler implements EventHandler { + + @Before(event = CqnService.EVENT_CREATE, entity = "Incidents") + public void beforeCreateIncident(List incidents) { + // Called for each CREATE in the batch + for (Incidents incident : incidents) { + incident.setCreatedAt(Instant.now()); + } + } + + @On(event = CqnService.EVENT_UPDATE, entity = "Incidents") + public void onUpdateIncident(CdsUpdateEventContext context) { + // Called for each UPDATE in the batch + // Full access to context and transaction + } + + @After(event = CqnService.EVENT_READ, entity = "Incidents") + public void afterReadIncidents(List incidents) { + // Called for each READ in the batch + // Can modify results before sending back + } +} +``` + +--- + +## 4. Batch Response Format + +### 4.1 Successful Response + +``` +HTTP/1.1 200 OK +Content-Type: multipart/mixed; boundary=batch_response_boundary + +--batch_response_boundary +Content-Type: multipart/mixed; boundary=changeset_response_boundary + +--changeset_response_boundary +Content-Type: application/http +Content-Transfer-Encoding: binary + +HTTP/1.1 201 Created +Content-Type: application/json + +{ + "ID": "f60f5c43-3c6e-4c79-bb18-23cf314c55e4", + "title": "Network outage", + "urgency": "high" +} + +--changeset_response_boundary +Content-Type: application/http +Content-Transfer-Encoding: binary + +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "ID": "f60f5c43-3c6e-4c79-bb18-23cf314c55e4", + "status": "closed" +} + +--changeset_response_boundary-- + +--batch_response_boundary +Content-Type: application/http +Content-Transfer-Encoding: binary + +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "value": [ + { + "ID": "f60f5c43-3c6e-4c79-bb18-23cf314c55e4", + "title": "Network outage" + } + ] +} + +--batch_response_boundary-- +``` + +### 4.2 Error Response (ChangeSet Failure) + +When any operation in a changeset fails, the entire changeset is rolled back: + +``` +--batch_response_boundary +Content-Type: multipart/mixed; boundary=changeset_response_boundary + +--changeset_response_boundary +Content-Type: application/http +Content-Transfer-Encoding: binary + +HTTP/1.1 400 Bad Request +Content-Type: application/json + +{ + "error": { + "code": "400", + "message": "Validation failed for field 'urgency'", + "target": "urgency" + } +} + +--changeset_response_boundary-- +``` + +All operations in the changeset are rolled back, and none of the changes are persisted. + +--- + +## 5. Common Use Cases + +### 5.1 Bulk Create + +Create multiple entities in a single atomic transaction: + +``` +POST /$batch + +--batch +Content-Type: multipart/mixed; boundary=changeset + +--changeset +POST Incidents +{ "title": "Issue 1" } + +--changeset +POST Incidents +{ "title": "Issue 2" } + +--changeset +POST Incidents +{ "title": "Issue 3" } + +--changeset-- +--batch-- +``` + +All incidents are created, or none if any validation fails. + +### 5.2 Create with Related Entities + +Create an entity and related entities using Content-ID references: + +``` +--changeset +Content-ID: new-incident + +POST Incidents +{ + "title": "Database performance issue", + "urgency": "high" +} + +--changeset +POST $new-incident/conversations +{ + "message": "Initial investigation started" +} + +--changeset-- +``` + +### 5.3 Mixed Operations + +Combine queries with modifications: + +``` +--batch +GET Incidents?$filter=status eq 'open' + +--batch +Content-Type: multipart/mixed; boundary=changeset + +--changeset +PATCH Incidents(ID=) +{ "status": "closed" } + +--changeset +POST Incidents +{ "title": "New incident" } + +--changeset-- + +--batch +GET Customers + +--batch-- +``` + +The GET requests execute independently, while modifications are atomic. + +--- + +## 6. CAP Java Configuration + +### 6.1 Default Behavior + +CAP Java handles OData V4 batch requests automatically with built-in defaults: + +- Batch requests are **enabled by default** on the `$batch` endpoint +- Transaction management is automatic for changesets +- No special configuration required for basic batch support + +### 6.2 Transaction Management + +CAP Java automatically manages transactions for batch requests: + +**ChangeSet Transactions**: +- Each changeset runs in a single database transaction +- Automatic commit on success, rollback on any failure +- Transaction boundaries are managed by the CAP runtime + +**Independent Requests**: +- Each request outside a changeset may run in its own transaction +- Failure of one request doesn't affect others + +### 6.3 Spring Boot Configuration + +Standard Spring Boot settings apply to batch request processing: + +```yaml +spring: + datasource: + # Connection pool settings affect batch performance + hikari: + maximum-pool-size: 10 + connection-timeout: 30000 +``` + +### 6.4 HTTP Request Limits + +Configure HTTP request size limits (applies to batch requests): + +```yaml +server: + # Maximum HTTP request body size + max-http-request-header-size: 10MB + tomcat: + max-swallow-size: 10MB +``` + +--- + +## 7. Best Practices + +### 7.1 Use ChangeSets for Related Operations + +Group related operations in changesets to ensure data consistency: + +``` +✓ GOOD: Create order and line items in one changeset +✗ BAD: Create order in one changeset, line items in another +``` + +### 7.2 Optimize Request Order + +Order requests to minimize database roundtrips: + +``` +✓ GOOD: Create parent first, then children using Content-ID +✗ BAD: Random order requiring multiple passes +``` + +### 7.3 Limit Batch Size + +Don't create overly large batches: + +``` +✓ GOOD: 10-50 operations per batch +✗ BAD: 1000+ operations (consider pagination or background jobs) +``` + +### 7.4 Handle Partial Failures + +Independent requests outside changesets can fail without affecting others: + +``` +✓ GOOD: Critical operations in changesets, optional operations outside +✗ BAD: All operations in one changeset when partial success is acceptable +``` + +### 7.5 Use Content-IDs Wisely + +Only use Content-IDs when you need to reference created entities: + +``` +✓ GOOD: Content-ID for parent when creating children +✗ BAD: Content-ID on every operation (adds overhead) +``` + +--- + +## 8. Error Handling + +### 8.1 Validation Errors + +If a validation error occurs in a changeset, the entire changeset fails: + +```java +@Before(event = CqnService.EVENT_CREATE, entity = "Incidents") +public void validateIncident(List incidents) { + for (Incidents incident : incidents) { + if (incident.getUrgency() == null) { + throw new ServiceException(ErrorStatuses.BAD_REQUEST, + "Urgency is required"); + } + } +} +``` + +Response: +```json +{ + "error": { + "code": "400", + "message": "Urgency is required" + } +} +``` + +### 8.2 Database Constraint Violations + +Unique constraint violations or foreign key errors roll back the changeset: + +``` +HTTP/1.1 400 Bad Request + +{ + "error": { + "code": "400", + "message": "Entity already exists with this key" + } +} +``` + +### 8.3 Authorization Errors + +If user lacks permission for any operation in a changeset: + +``` +HTTP/1.1 403 Forbidden + +{ + "error": { + "code": "403", + "message": "User not authorized to perform this operation" + } +} +``` + +--- + +## 9. Performance Considerations + +### 9.1 Benefits + +- **Reduced Network Latency**: Single HTTP request vs multiple roundtrips +- **Connection Pooling**: Better utilization of database connections +- **Transaction Overhead**: Fewer transaction begin/commit cycles +- **Client Efficiency**: Simplified client code for bulk operations + +### 9.2 Trade-offs + +- **Memory Usage**: Large batches consume more memory +- **Response Time**: Client waits for all operations to complete +- **Error Recovery**: Partial failures require re-sending entire changeset +- **Debugging**: Harder to troubleshoot than individual requests + +### 9.3 Optimization Tips + +1. **Batch Similar Operations**: Group creates together, updates together +2. **Use Streaming**: For very large batches, process in chunks +3. **Monitor Transaction Time**: Keep changesets small enough to avoid timeouts +4. **Index Properly**: Ensure database indexes support batch operations +5. **Profile Handlers**: Ensure event handlers are efficient + +--- + +## 10. Testing Batch Requests + +### 10.1 Using cURL + +```bash +curl -X POST http://localhost:8080/odata/v4/IncidentService/$batch \ + -H "Content-Type: multipart/mixed; boundary=batch" \ + --data-binary @batch-request.txt +``` + +### 10.2 Using Postman + +1. Create a POST request to `/$batch` +2. Set Content-Type to `multipart/mixed; boundary=batch` +3. Add batch content in raw body +4. Send and inspect multipart response + +### 10.3 Integration Tests + +```java +@SpringBootTest +@AutoConfigureMockMvc +class BatchRequestTest { + + @Autowired + private MockMvc mockMvc; + + @Test + void testBatchCreateIncidents() throws Exception { + String batchContent = """ + --batch + Content-Type: multipart/mixed; boundary=changeset + + --changeset + Content-Type: application/http + Content-Transfer-Encoding: binary + + POST Incidents HTTP/1.1 + Content-Type: application/json + + {"title": "Test Incident 1"} + + --changeset + Content-Type: application/http + Content-Transfer-Encoding: binary + + POST Incidents HTTP/1.1 + Content-Type: application/json + + {"title": "Test Incident 2"} + + --changeset-- + --batch-- + """; + + mockMvc.perform(post("/odata/v4/IncidentService/$batch") + .contentType("multipart/mixed; boundary=batch") + .content(batchContent)) + .andExpect(status().isOk()) + .andExpect(content().contentTypeCompatibleWith("multipart/mixed")); + } +} +``` + +--- + +## 11. Troubleshooting + +### 11.1 Common Issues + +**Issue**: Batch request returns 400 Bad Request +**Solution**: Check boundary delimiters match exactly between Content-Type and body + +**Issue**: ChangeSet operations not atomic +**Solution**: Verify all operations are within changeset boundaries + +**Issue**: Content-ID references not working +**Solution**: Ensure Content-ID is defined before usage, check format `$` + +**Issue**: Performance degradation with large batches +**Solution**: Reduce batch size, check database connection pool settings + +### 11.2 Debugging + +Enable detailed logging in `application.yaml`: + +```yaml +logging: + level: + com.sap.cds: DEBUG + com.sap.cds.odata: TRACE + # See detailed batch processing + com.sap.cds.odata.v4.batch: TRACE +``` + +### 11.3 Monitoring + +Key metrics to monitor: + +- Batch request size distribution +- Average processing time per batch +- Changeset rollback rate +- Individual operation success/failure rates +- Memory consumption during batch processing + +--- + +## 12. Comparison with OData V2 Batch + +### 12.1 Key Differences + +| Aspect | OData V2 | OData V4 | +|--------|----------|----------| +| Content Type | `multipart/mixed` | `multipart/mixed` (same) | +| ChangeSet Format | Similar | Simplified boundaries | +| Content-ID | Limited support | Full support with `$id` | +| Error Handling | Vendor-specific | Standardized | +| Specification | Less detailed | More comprehensive | + +### 12.2 Migration Notes + +When migrating from OData V2 to V4: + +1. Update batch endpoint URLs (`/v2/` → `/v4/`) +2. Review Content-ID reference syntax +3. Update error response parsing +4. Test changeset rollback behavior +5. Verify boundary delimiter handling + +--- + +## Summary + +OData V4 Batch requests provide a powerful mechanism for bundling multiple operations into a single HTTP request. CAP Java handles batch processing automatically, providing: + +- Atomic transactions via changesets +- Content-ID references for related entities +- Automatic transaction management +- Event handler integration +- Standard OData V4 compliance + +By understanding batch request structure and CAP Java's processing model, developers can build efficient applications that minimize network overhead while maintaining data consistency and leveraging CAP's full event-driven architecture. diff --git a/package-lock.json b/package-lock.json index a764963..2a18ffd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,33 +9,30 @@ "version": "1.0.0", "license": "ISC", "devDependencies": { - "@sap/cds-dk": "^8.6.1" + "@sap/cds-dk": "^9" } }, "node_modules/@sap/cds-dk": { - "version": "8.9.3", - "resolved": "https://registry.npmjs.org/@sap/cds-dk/-/cds-dk-8.9.3.tgz", - "integrity": "sha512-hZV6ZvxhG18zqNO6/L4b9+g2Dxq3Jk8+xMzec3S/Z05ErclDd7m9LUPisAXVRZ1D/oy52tUowClqLHhXM4LlFQ==", + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@sap/cds-dk/-/cds-dk-9.7.1.tgz", + "integrity": "sha512-pRaCBjJzLvFoCzeEvqOnJJMyzmd3PHN65YZKuH/5TzMaRSRrB++NQcXnbaDOSlLxZghSpshf7IiUwhAGNnkW7A==", "dev": true, "hasShrinkwrap": true, "license": "SEE LICENSE IN LICENSE", "dependencies": { "@cap-js/asyncapi": "^1.0.0", "@cap-js/openapi": "^1.0.0", - "@sap/cds": "^7 || ^8", - "@sap/cds-foss": "^5.0.0", - "@sap/cds-mtxs": "^1.9.0 || ^2", - "@sap/eslint-plugin-cds": "^3.0.1", + "@sap/cds": ">=8.3", + "@sap/cds-mtxs": ">=2", "@sap/hdi-deploy": "^5", "axios": "^1", - "eslint": "^9", - "express": "^4.17.3", - "hdb": "^0", + "express": "^4.22.1 || ^5", + "hdb": "^2.0.0", "livereload-js": "^4.0.1", "mustache": "^4.0.1", - "node-watch": ">=0.7", "ws": "^8.4.2", - "xml-js": "^1.6.11" + "xml-js": "^1.6.11", + "yaml": "^2" }, "bin": { "cds": "bin/cds.js", @@ -43,11 +40,12 @@ "cds-tsx": "bin/cds-tsx.js" }, "optionalDependencies": { - "@cap-js/sqlite": "^1" + "@cap-js/sqlite": ">=1" } }, "node_modules/@sap/cds-dk/node_modules/@cap-js/asyncapi": { "version": "1.0.3", + "integrity": "sha512-vZSWKAe+3qfvZDXV5SSFiObGWmqyS9MDyEADb5PLVT8kzO39qGaSDPv/GzI/gwvRfCayGAjU4ThiBKrFA7Gclg==", "dev": true, "license": "SEE LICENSE IN LICENSE", "peerDependencies": { @@ -55,21 +53,23 @@ } }, "node_modules/@sap/cds-dk/node_modules/@cap-js/db-service": { - "version": "1.20.0", + "version": "2.8.2", + "integrity": "sha512-5BUWnoRX7LQBEWvEZmq0urEkxWPIIUnV9v2uFYop19W10jtmK6bxKqk+oUGD/7o6C9GNiFcZoLpja7SFohfKOg==", "dev": true, - "license": "SEE LICENSE", + "license": "Apache-2.0", "optional": true, "dependencies": { "generic-pool": "^3.9.0" }, "peerDependencies": { - "@sap/cds": ">=7.9" + "@sap/cds": ">=9.4.5" } }, "node_modules/@sap/cds-dk/node_modules/@cap-js/openapi": { - "version": "1.2.1", + "version": "1.3.1", + "integrity": "sha512-2QqqZlOxfvp/DDmGgTdwbBAAMjaPrrdPCbNC4+z6wjn2jXXk40j0XX7DHNnF4BU8R9LFxaUCHt2x8/9PzE83uA==", "dev": true, - "license": "SEE LICENSE IN LICENSE", + "license": "Apache-2.0", "dependencies": { "pluralize": "^8.0.0" }, @@ -78,292 +78,102 @@ } }, "node_modules/@sap/cds-dk/node_modules/@cap-js/sqlite": { - "version": "1.11.0", + "version": "2.1.3", + "integrity": "sha512-JkIAR8khPEW0jgw440JrtOzsj+TacZmACJsifGnCWpgrC17f2q8r15pzrCnvvCmkLXTqUW1kRg5/B3nLbaO86Q==", "dev": true, - "license": "SEE LICENSE", + "license": "Apache-2.0", "optional": true, "dependencies": { - "@cap-js/db-service": "^1.20.0", - "better-sqlite3": "^11.0.0" - }, - "peerDependencies": { - "@sap/cds": ">=7.6" - } - }, - "node_modules/@sap/cds-dk/node_modules/@eslint-community/eslint-utils": { - "version": "4.6.1", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "@cap-js/db-service": "^2.8.2", + "better-sqlite3": "^12.0.0" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@sap/cds-dk/node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/@eslint/config-array": { - "version": "0.20.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.6", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/@eslint/config-helpers": { - "version": "0.2.1", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/@eslint/core": { - "version": "0.13.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/@eslint/eslintrc": { - "version": "3.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "@sap/cds": ">=9" } }, "node_modules/@sap/cds-dk/node_modules/@eslint/js": { - "version": "9.25.1", + "version": "9.39.2", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/@eslint/object-schema": { - "version": "2.1.6", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/@eslint/plugin-kit": { - "version": "0.2.8", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.13.0", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/@humanfs/core": { - "version": "0.19.1", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/@humanfs/node": { - "version": "0.16.6", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.3.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@sap/cds-dk/node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@sap/cds-dk/node_modules/@humanwhocodes/retry": { - "version": "0.4.2", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "url": "https://eslint.org/donate" } }, "node_modules/@sap/cds-dk/node_modules/@sap/cds": { - "version": "8.9.2", + "version": "9.7.0", + "integrity": "sha512-E2ntY7l98fIIbhRbgjxL/M3+iM0mAOz8ehNu+evCUusQHveTWyx3b4DQomJaD4yOAlzMq1m26iDYQBT8HuSIpg==", "dev": true, "license": "SEE LICENSE IN LICENSE", "dependencies": { - "@sap/cds-compiler": ">=5.1", - "@sap/cds-fiori": "^1", - "@sap/cds-foss": "^5.0.0" + "@sap/cds-compiler": "^6.4", + "@sap/cds-fiori": "^2", + "express": "^4.22.1 || ^5", + "js-yaml": "^4.1.1" }, "bin": { - "cds-deploy": "lib/dbs/cds-deploy.js", - "cds-serve": "bin/serve.js", - "cds-test": "bin/test.js" + "cds-deploy": "bin/deploy.js", + "cds-serve": "bin/serve.js" }, "engines": { - "node": ">=18" + "node": ">=20" }, "peerDependencies": { "@eslint/js": "^9", - "express": "^4", - "tar": "^7" + "tar": "^7.5.6" }, "peerDependenciesMeta": { - "express": { - "optional": true - }, "tar": { "optional": true } } }, "node_modules/@sap/cds-dk/node_modules/@sap/cds-compiler": { - "version": "5.9.2", + "version": "6.7.2", + "integrity": "sha512-5UpDA7boOmwtTBWjhEDbpXKgxjqz+0zObBr12P3g5D7QIMF+hPrPG+J0Bm2AQRPE/lv8VcnzFEaMdibRgmGtUw==", "dev": true, "license": "SEE LICENSE IN LICENSE", - "dependencies": { - "antlr4": "4.9.3" - }, "bin": { "cdsc": "bin/cdsc.js", "cdshi": "bin/cdshi.js", "cdsse": "bin/cdsse.js" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/@sap/cds-dk/node_modules/@sap/cds-fiori": { - "version": "1.4.1", + "version": "2.2.0", + "integrity": "sha512-NnvpmU40Eez5Q3SkyCCLRuBd1XUjk7N+pbXcIPIkKw4rwvqR2/FbjNveRzc8mcrLcQA3/5b/CXYsafDoozUhng==", "dev": true, "license": "SEE LICENSE IN LICENSE", "peerDependencies": { - "@sap/cds": ">=7.6", - "express": ">=4" - } - }, - "node_modules/@sap/cds-dk/node_modules/@sap/cds-foss": { - "version": "5.0.1", - "dev": true, - "license": "See LICENSE in LICENSE", - "dependencies": { - "big.js": "^6.1.1", - "generic-pool": "^3.8.2", - "xmlbuilder": "^15.1.1", - "yaml": "^2.2.2" - }, - "engines": { - "node": ">=14" + "@sap/cds": ">=8" } }, "node_modules/@sap/cds-dk/node_modules/@sap/cds-mtxs": { - "version": "2.7.2", + "version": "3.7.0", + "integrity": "sha512-SojfvUrcPaVmaPpddUqosAC6Eqft+wdZMLs56C5a0XM54l3P+aWKgd4+G2IBbUjtAgeSznzmwb64dT5oOncSOQ==", "dev": true, "license": "SEE LICENSE IN LICENSE", "dependencies": { - "@sap/hdi-deploy": ">=4", - "axios": "^1" + "@sap/hdi-deploy": "^5" }, "bin": { "cds-mtx": "bin/cds-mtx.js", "cds-mtx-migrate": "bin/cds-mtx-migrate.js" - } - }, - "node_modules/@sap/cds-dk/node_modules/@sap/eslint-plugin-cds": { - "version": "3.2.0", - "dev": true, - "license": "See LICENSE file", - "dependencies": { - "@sap/cds": ">=7", - "semver": "^7.7.1" - }, - "engines": { - "node": ">=18" }, "peerDependencies": { - "eslint": ">=8" + "@sap/cds": "^9" } }, "node_modules/@sap/cds-dk/node_modules/@sap/hdi": { - "version": "4.7.0", + "version": "4.8.0", + "integrity": "sha512-tkJmY2ffm6mt4/LFwRBihlQkMxNAXa3ngvRe2N/6+qLIsUNdrH/M03S5mkygXq56K+KoVVZYuradajCusMWwsw==", "dev": true, "license": "See LICENSE file", "dependencies": { @@ -374,7 +184,7 @@ }, "peerDependencies": { "@sap/hana-client": "^2 >= 2.5", - "hdb": "^0" + "hdb": "^2 || ^0" }, "peerDependenciesMeta": { "@sap/hana-client": { @@ -386,12 +196,13 @@ } }, "node_modules/@sap/cds-dk/node_modules/@sap/hdi-deploy": { - "version": "5.4.2", + "version": "5.6.1", + "integrity": "sha512-+qQ7qwG8lko303L5yRj2dud/nDAVuVblV/mmzJT44oPbF0Nry18eD2LUS23hFeuxjRa7rYK5YKQ8ffGgWxVrYQ==", "dev": true, "license": "See LICENSE file", "dependencies": { - "@sap/hdi": "^4.7.0", - "@sap/xsenv": "^5.2.0", + "@sap/hdi": "^4.8.0", + "@sap/xsenv": "^6.0.0", "async": "^3.2.6", "dotenv": "^16.4.5", "handlebars": "^4.7.8", @@ -402,7 +213,7 @@ }, "peerDependencies": { "@sap/hana-client": "^2 >= 2.6", - "hdb": "^0" + "hdb": "^2 || ^0" }, "peerDependenciesMeta": { "@sap/hana-client": { @@ -414,108 +225,41 @@ } }, "node_modules/@sap/cds-dk/node_modules/@sap/xsenv": { - "version": "5.5.0", + "version": "6.1.0", + "integrity": "sha512-vlW4Zad3uiDqHtnYdQ0TsEIH8VIO4HmPGDowfBL5dIcHPmeKDISEQ9ibeHL5FkceqvYcXJEQAVZ5/hsHDqlXZg==", "dev": true, "license": "SEE LICENSE IN LICENSE file", "dependencies": { - "debug": "4.4.0", + "debug": "4.4.3", "node-cache": "^5.1.2", "verror": "1.10.1" }, "engines": { - "node": "^18.0.0 || ^20.0.0 || ^22.0.0" + "node": "^20.0.0 || ^22.0.0 || ^24.0.0" } }, - "node_modules/@sap/cds-dk/node_modules/@types/estree": { - "version": "1.0.7", - "dev": true, - "license": "MIT" - }, - "node_modules/@sap/cds-dk/node_modules/@types/json-schema": { - "version": "7.0.15", - "dev": true, - "license": "MIT" - }, "node_modules/@sap/cds-dk/node_modules/accepts": { - "version": "1.3.8", + "version": "2.0.0", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", "dev": true, "license": "MIT", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" }, "engines": { "node": ">= 0.6" } }, - "node_modules/@sap/cds-dk/node_modules/acorn": { - "version": "8.14.1", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/acorn-jsx": { - "version": "5.3.2", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/ajv": { - "version": "6.12.6", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@sap/cds-dk/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@sap/cds-dk/node_modules/antlr4": { - "version": "4.9.3", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=14" - } - }, "node_modules/@sap/cds-dk/node_modules/argparse": { "version": "2.0.1", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, "license": "Python-2.0" }, - "node_modules/@sap/cds-dk/node_modules/array-flatten": { - "version": "1.1.1", - "dev": true, - "license": "MIT" - }, "node_modules/@sap/cds-dk/node_modules/assert-plus": { "version": "1.0.0", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", "dev": true, "license": "MIT", "engines": { @@ -524,31 +268,30 @@ }, "node_modules/@sap/cds-dk/node_modules/async": { "version": "3.2.6", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "dev": true, "license": "MIT" }, "node_modules/@sap/cds-dk/node_modules/asynckit": { "version": "0.4.0", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true, "license": "MIT" }, "node_modules/@sap/cds-dk/node_modules/axios": { - "version": "1.8.4", + "version": "1.13.4", + "integrity": "sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==", "dev": true, "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", + "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, - "node_modules/@sap/cds-dk/node_modules/balanced-match": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, "node_modules/@sap/cds-dk/node_modules/base64-js": { "version": "1.5.1", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true, "funding": [ { @@ -568,7 +311,8 @@ "optional": true }, "node_modules/@sap/cds-dk/node_modules/better-sqlite3": { - "version": "11.9.1", + "version": "12.6.2", + "integrity": "sha512-8VYKM3MjCa9WcaSAI3hzwhmyHVlH8tiGFwf0RlTsZPWJ1I5MkzjiudCo4KC4DxOaL/53A5B1sI/IbldNFDbsKA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -576,22 +320,14 @@ "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^7.1.1" - } - }, - "node_modules/@sap/cds-dk/node_modules/big.js": { - "version": "6.2.2", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/bigjs" + "engines": { + "node": "20.x || 22.x || 23.x || 24.x || 25.x" } }, "node_modules/@sap/cds-dk/node_modules/bindings": { "version": "1.5.0", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "dev": true, "license": "MIT", "optional": true, @@ -601,6 +337,7 @@ }, "node_modules/@sap/cds-dk/node_modules/bl": { "version": "4.1.0", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, "license": "MIT", "optional": true, @@ -611,52 +348,32 @@ } }, "node_modules/@sap/cds-dk/node_modules/body-parser": { - "version": "1.20.3", + "version": "2.2.2", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", "dev": true, "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/@sap/cds-dk/node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@sap/cds-dk/node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/@sap/cds-dk/node_modules/braces": { "version": "3.0.3", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", "dependencies": { @@ -668,6 +385,7 @@ }, "node_modules/@sap/cds-dk/node_modules/buffer": { "version": "5.7.1", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, "funding": [ { @@ -692,6 +410,7 @@ }, "node_modules/@sap/cds-dk/node_modules/bytes": { "version": "3.1.2", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, "license": "MIT", "engines": { @@ -700,6 +419,7 @@ }, "node_modules/@sap/cds-dk/node_modules/call-bind-apply-helpers": { "version": "1.0.2", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "dev": true, "license": "MIT", "dependencies": { @@ -712,6 +432,7 @@ }, "node_modules/@sap/cds-dk/node_modules/call-bound": { "version": "1.0.4", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, "license": "MIT", "dependencies": { @@ -725,61 +446,25 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@sap/cds-dk/node_modules/callsites": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@sap/cds-dk/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/@sap/cds-dk/node_modules/chownr": { "version": "1.1.4", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true, "license": "ISC", "optional": true }, "node_modules/@sap/cds-dk/node_modules/clone": { "version": "2.1.2", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", "dev": true, "license": "MIT", "engines": { "node": ">=0.8" } }, - "node_modules/@sap/cds-dk/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, "node_modules/@sap/cds-dk/node_modules/combined-stream": { "version": "1.0.8", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, "license": "MIT", "dependencies": { @@ -789,24 +474,22 @@ "node": ">= 0.8" } }, - "node_modules/@sap/cds-dk/node_modules/concat-map": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, "node_modules/@sap/cds-dk/node_modules/content-disposition": { - "version": "0.5.4", + "version": "1.0.1", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", "dev": true, "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/@sap/cds-dk/node_modules/content-type": { "version": "1.0.5", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "dev": true, "license": "MIT", "engines": { @@ -814,7 +497,8 @@ } }, "node_modules/@sap/cds-dk/node_modules/cookie": { - "version": "0.7.1", + "version": "0.7.2", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "dev": true, "license": "MIT", "engines": { @@ -822,30 +506,23 @@ } }, "node_modules/@sap/cds-dk/node_modules/cookie-signature": { - "version": "1.0.6", + "version": "1.2.2", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } }, "node_modules/@sap/cds-dk/node_modules/core-util-is": { "version": "1.0.2", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", "dev": true, "license": "MIT" }, - "node_modules/@sap/cds-dk/node_modules/cross-spawn": { - "version": "7.0.6", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/@sap/cds-dk/node_modules/debug": { - "version": "4.4.0", + "version": "4.4.3", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -862,6 +539,7 @@ }, "node_modules/@sap/cds-dk/node_modules/decompress-response": { "version": "6.0.0", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "dev": true, "license": "MIT", "optional": true, @@ -877,6 +555,7 @@ }, "node_modules/@sap/cds-dk/node_modules/deep-extend": { "version": "0.6.0", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "license": "MIT", "optional": true, @@ -884,13 +563,9 @@ "node": ">=4.0.0" } }, - "node_modules/@sap/cds-dk/node_modules/deep-is": { - "version": "0.1.4", - "dev": true, - "license": "MIT" - }, "node_modules/@sap/cds-dk/node_modules/delayed-stream": { "version": "1.0.0", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, "license": "MIT", "engines": { @@ -899,23 +574,16 @@ }, "node_modules/@sap/cds-dk/node_modules/depd": { "version": "2.0.0", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/@sap/cds-dk/node_modules/destroy": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, "node_modules/@sap/cds-dk/node_modules/detect-libc": { - "version": "2.0.4", + "version": "2.1.2", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, "license": "Apache-2.0", "optional": true, @@ -924,7 +592,8 @@ } }, "node_modules/@sap/cds-dk/node_modules/dotenv": { - "version": "16.5.0", + "version": "16.6.1", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -936,6 +605,7 @@ }, "node_modules/@sap/cds-dk/node_modules/dunder-proto": { "version": "1.0.1", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "dev": true, "license": "MIT", "dependencies": { @@ -949,11 +619,13 @@ }, "node_modules/@sap/cds-dk/node_modules/ee-first": { "version": "1.1.1", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "dev": true, "license": "MIT" }, "node_modules/@sap/cds-dk/node_modules/encodeurl": { "version": "2.0.0", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, "license": "MIT", "engines": { @@ -961,7 +633,8 @@ } }, "node_modules/@sap/cds-dk/node_modules/end-of-stream": { - "version": "1.4.4", + "version": "1.4.5", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "dev": true, "license": "MIT", "optional": true, @@ -971,6 +644,7 @@ }, "node_modules/@sap/cds-dk/node_modules/es-define-property": { "version": "1.0.1", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, "license": "MIT", "engines": { @@ -979,194 +653,49 @@ }, "node_modules/@sap/cds-dk/node_modules/es-errors": { "version": "1.3.0", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/@sap/cds-dk/node_modules/es-object-atoms": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/@sap/cds-dk/node_modules/es-set-tostringtag": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/@sap/cds-dk/node_modules/escape-html": { - "version": "1.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@sap/cds-dk/node_modules/escape-string-regexp": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sap/cds-dk/node_modules/eslint": { - "version": "9.25.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.20.0", - "@eslint/config-helpers": "^0.2.1", - "@eslint/core": "^0.13.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.25.1", - "@eslint/plugin-kit": "^0.2.8", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.3.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/@sap/cds-dk/node_modules/eslint-scope": { - "version": "8.3.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@sap/cds-dk/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@sap/cds-dk/node_modules/espree": { - "version": "10.3.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.14.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@sap/cds-dk/node_modules/esquery": { - "version": "1.6.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, + "license": "MIT", "engines": { - "node": ">=0.10" + "node": ">= 0.4" } }, - "node_modules/@sap/cds-dk/node_modules/esrecurse": { - "version": "4.3.0", + "node_modules/@sap/cds-dk/node_modules/es-object-atoms": { + "version": "1.1.1", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "estraverse": "^5.2.0" + "es-errors": "^1.3.0" }, "engines": { - "node": ">=4.0" + "node": ">= 0.4" } }, - "node_modules/@sap/cds-dk/node_modules/estraverse": { - "version": "5.3.0", + "node_modules/@sap/cds-dk/node_modules/es-set-tostringtag": { + "version": "2.1.0", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, "engines": { - "node": ">=4.0" + "node": ">= 0.4" } }, - "node_modules/@sap/cds-dk/node_modules/esutils": { - "version": "2.0.3", + "node_modules/@sap/cds-dk/node_modules/escape-html": { + "version": "1.0.3", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, "node_modules/@sap/cds-dk/node_modules/etag": { "version": "1.8.1", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true, "license": "MIT", "engines": { @@ -1175,6 +704,7 @@ }, "node_modules/@sap/cds-dk/node_modules/expand-template": { "version": "2.0.3", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", "dev": true, "license": "(MIT OR WTFPL)", "optional": true, @@ -1183,105 +713,67 @@ } }, "node_modules/@sap/cds-dk/node_modules/express": { - "version": "4.21.2", - "dev": true, - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" + "version": "5.2.1", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" } }, - "node_modules/@sap/cds-dk/node_modules/express/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/express/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/@sap/cds-dk/node_modules/extsprintf": { "version": "1.4.1", + "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", "dev": true, "engines": [ "node >=0.6.0" ], "license": "MIT" }, - "node_modules/@sap/cds-dk/node_modules/fast-deep-equal": { - "version": "3.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@sap/cds-dk/node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@sap/cds-dk/node_modules/fast-levenshtein": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/@sap/cds-dk/node_modules/file-entry-cache": { - "version": "8.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, "node_modules/@sap/cds-dk/node_modules/file-uri-to-path": { "version": "1.0.0", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "dev": true, "license": "MIT", "optional": true }, "node_modules/@sap/cds-dk/node_modules/fill-range": { "version": "7.1.1", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "license": "MIT", "dependencies": { @@ -1292,69 +784,29 @@ } }, "node_modules/@sap/cds-dk/node_modules/finalhandler": { - "version": "1.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@sap/cds-dk/node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@sap/cds-dk/node_modules/find-up": { - "version": "5.0.0", + "version": "2.1.1", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">= 18.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sap/cds-dk/node_modules/flat-cache": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/@sap/cds-dk/node_modules/flatted": { - "version": "3.3.3", - "dev": true, - "license": "ISC" - }, "node_modules/@sap/cds-dk/node_modules/follow-redirects": { - "version": "1.15.9", + "version": "1.15.11", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", "dev": true, "funding": [ { @@ -1373,21 +825,45 @@ } }, "node_modules/@sap/cds-dk/node_modules/form-data": { - "version": "4.0.2", + "version": "4.0.5", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { "node": ">= 6" } }, + "node_modules/@sap/cds-dk/node_modules/form-data/node_modules/mime-db": { + "version": "1.52.0", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@sap/cds-dk/node_modules/form-data/node_modules/mime-types": { + "version": "2.1.35", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/@sap/cds-dk/node_modules/forwarded": { "version": "0.2.0", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "dev": true, "license": "MIT", "engines": { @@ -1395,21 +871,24 @@ } }, "node_modules/@sap/cds-dk/node_modules/fresh": { - "version": "0.5.2", + "version": "2.0.0", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/@sap/cds-dk/node_modules/fs-constants": { "version": "1.0.0", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "dev": true, "license": "MIT", "optional": true }, "node_modules/@sap/cds-dk/node_modules/function-bind": { "version": "1.1.2", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, "license": "MIT", "funding": { @@ -1418,14 +897,17 @@ }, "node_modules/@sap/cds-dk/node_modules/generic-pool": { "version": "3.9.0", + "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", "dev": true, "license": "MIT", + "optional": true, "engines": { "node": ">= 4" } }, "node_modules/@sap/cds-dk/node_modules/get-intrinsic": { "version": "1.3.0", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1449,6 +931,7 @@ }, "node_modules/@sap/cds-dk/node_modules/get-proto": { "version": "1.0.1", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "dev": true, "license": "MIT", "dependencies": { @@ -1461,34 +944,14 @@ }, "node_modules/@sap/cds-dk/node_modules/github-from-package": { "version": "0.0.0", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", "dev": true, "license": "MIT", "optional": true }, - "node_modules/@sap/cds-dk/node_modules/glob-parent": { - "version": "6.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/globals": { - "version": "14.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@sap/cds-dk/node_modules/gopd": { "version": "1.2.0", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, "license": "MIT", "engines": { @@ -1500,6 +963,7 @@ }, "node_modules/@sap/cds-dk/node_modules/handlebars": { "version": "4.7.8", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1518,16 +982,9 @@ "uglify-js": "^3.1.4" } }, - "node_modules/@sap/cds-dk/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/@sap/cds-dk/node_modules/has-symbols": { "version": "1.1.0", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, "license": "MIT", "engines": { @@ -1539,6 +996,7 @@ }, "node_modules/@sap/cds-dk/node_modules/has-tostringtag": { "version": "1.0.2", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "license": "MIT", "dependencies": { @@ -1553,6 +1011,7 @@ }, "node_modules/@sap/cds-dk/node_modules/hasown": { "version": "2.0.2", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1563,44 +1022,75 @@ } }, "node_modules/@sap/cds-dk/node_modules/hdb": { - "version": "0.19.12", + "version": "2.27.1", + "integrity": "sha512-xYL/W+fq2TyGHyzm8muolQnw8tdh4+2NQ8mQP2FpLSuhfJ8l0jQNSUZoAXic7NfMEan1Jvf8V1L4blwkgTc6+A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "iconv-lite": "^0.4.18" + "iconv-lite": "0.7.0" + }, + "engines": { + "node": ">= 18" + }, + "optionalDependencies": { + "lz4-wasm-nodejs": "0.9.2" + } + }, + "node_modules/@sap/cds-dk/node_modules/hdb/node_modules/iconv-lite": { + "version": "0.7.0", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": ">= 0.12" + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/@sap/cds-dk/node_modules/http-errors": { - "version": "2.0.0", + "version": "2.0.1", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "dev": true, "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/@sap/cds-dk/node_modules/iconv-lite": { - "version": "0.4.24", + "version": "0.7.2", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/@sap/cds-dk/node_modules/ieee754": { "version": "1.2.1", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "dev": true, "funding": [ { @@ -1619,90 +1109,46 @@ "license": "BSD-3-Clause", "optional": true }, - "node_modules/@sap/cds-dk/node_modules/ignore": { - "version": "5.3.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@sap/cds-dk/node_modules/import-fresh": { - "version": "3.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sap/cds-dk/node_modules/imurmurhash": { - "version": "0.1.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, "node_modules/@sap/cds-dk/node_modules/inherits": { "version": "2.0.4", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true, "license": "ISC" }, "node_modules/@sap/cds-dk/node_modules/ini": { "version": "1.3.8", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true, "license": "ISC", "optional": true }, "node_modules/@sap/cds-dk/node_modules/ipaddr.js": { "version": "1.9.1", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.10" } }, - "node_modules/@sap/cds-dk/node_modules/is-extglob": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/is-glob": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@sap/cds-dk/node_modules/is-number": { "version": "7.0.0", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" } }, - "node_modules/@sap/cds-dk/node_modules/isexe": { - "version": "2.0.0", + "node_modules/@sap/cds-dk/node_modules/is-promise": { + "version": "4.0.0", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "dev": true, - "license": "ISC" + "license": "MIT" }, "node_modules/@sap/cds-dk/node_modules/js-yaml": { - "version": "4.1.0", + "version": "4.1.1", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -1712,67 +1158,22 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@sap/cds-dk/node_modules/json-buffer": { - "version": "3.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@sap/cds-dk/node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@sap/cds-dk/node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@sap/cds-dk/node_modules/keyv": { - "version": "4.5.4", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/@sap/cds-dk/node_modules/levn": { - "version": "0.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/@sap/cds-dk/node_modules/livereload-js": { "version": "4.0.2", + "integrity": "sha512-Fy7VwgQNiOkynYyNBTo3v9hQUhcW5pFAheJN148+DTgpShjsy/22pLHKKwDK5v0kOsZsJBK+6q1PMgLvRmrwFQ==", "dev": true, "license": "MIT" }, - "node_modules/@sap/cds-dk/node_modules/locate-path": { - "version": "6.0.0", + "node_modules/@sap/cds-dk/node_modules/lz4-wasm-nodejs": { + "version": "0.9.2", + "integrity": "sha512-hSwgJPS98q/Oe/89Y1OxzeA/UdnASG8GvldRyKa7aZyoAFCC8VPRtViBSava7wWC66WocjUwBpWau2rEmyFPsw==", "dev": true, "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sap/cds-dk/node_modules/lodash.merge": { - "version": "4.6.2", - "dev": true, - "license": "MIT" + "optional": true }, "node_modules/@sap/cds-dk/node_modules/math-intrinsics": { "version": "1.1.0", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "dev": true, "license": "MIT", "engines": { @@ -1780,31 +1181,29 @@ } }, "node_modules/@sap/cds-dk/node_modules/media-typer": { - "version": "0.3.0", + "version": "1.1.0", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/@sap/cds-dk/node_modules/merge-descriptors": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sap/cds-dk/node_modules/methods": { - "version": "1.1.2", + "version": "2.0.0", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@sap/cds-dk/node_modules/micromatch": { "version": "4.0.8", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { @@ -1815,19 +1214,21 @@ "node": ">=8.6" } }, - "node_modules/@sap/cds-dk/node_modules/mime": { - "version": "1.6.0", + "node_modules/@sap/cds-dk/node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", - "bin": { - "mime": "cli.js" - }, "engines": { - "node": ">=4" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/@sap/cds-dk/node_modules/mime-db": { - "version": "1.52.0", + "version": "1.54.0", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true, "license": "MIT", "engines": { @@ -1835,18 +1236,24 @@ } }, "node_modules/@sap/cds-dk/node_modules/mime-types": { - "version": "2.1.35", + "version": "3.0.2", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "dev": true, "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "mime-db": "^1.54.0" }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/@sap/cds-dk/node_modules/mimic-response": { "version": "3.1.0", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "dev": true, "license": "MIT", "optional": true, @@ -1857,19 +1264,9 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@sap/cds-dk/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@sap/cds-dk/node_modules/minimist": { "version": "1.2.8", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, "license": "MIT", "funding": { @@ -1878,17 +1275,20 @@ }, "node_modules/@sap/cds-dk/node_modules/mkdirp-classic": { "version": "0.5.3", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", "dev": true, "license": "MIT", "optional": true }, "node_modules/@sap/cds-dk/node_modules/ms": { "version": "2.1.3", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, "node_modules/@sap/cds-dk/node_modules/mustache": { "version": "4.2.0", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", "dev": true, "license": "MIT", "bin": { @@ -1897,17 +1297,14 @@ }, "node_modules/@sap/cds-dk/node_modules/napi-build-utils": { "version": "2.0.0", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", "dev": true, "license": "MIT", "optional": true }, - "node_modules/@sap/cds-dk/node_modules/natural-compare": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, "node_modules/@sap/cds-dk/node_modules/negotiator": { - "version": "0.6.3", + "version": "1.0.0", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "dev": true, "license": "MIT", "engines": { @@ -1916,11 +1313,13 @@ }, "node_modules/@sap/cds-dk/node_modules/neo-async": { "version": "2.6.2", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true, "license": "MIT" }, "node_modules/@sap/cds-dk/node_modules/node-abi": { - "version": "3.74.0", + "version": "3.87.0", + "integrity": "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ==", "dev": true, "license": "MIT", "optional": true, @@ -1933,6 +1332,7 @@ }, "node_modules/@sap/cds-dk/node_modules/node-cache": { "version": "5.1.2", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", "dev": true, "license": "MIT", "dependencies": { @@ -1942,16 +1342,9 @@ "node": ">= 8.0.0" } }, - "node_modules/@sap/cds-dk/node_modules/node-watch": { - "version": "0.7.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/@sap/cds-dk/node_modules/object-inspect": { "version": "1.13.4", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, "license": "MIT", "engines": { @@ -1963,6 +1356,7 @@ }, "node_modules/@sap/cds-dk/node_modules/on-finished": { "version": "2.4.1", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, "license": "MIT", "dependencies": { @@ -1974,110 +1368,35 @@ }, "node_modules/@sap/cds-dk/node_modules/once": { "version": "1.4.0", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "license": "ISC", - "optional": true, "dependencies": { "wrappy": "1" } }, - "node_modules/@sap/cds-dk/node_modules/optionator": { - "version": "0.9.4", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/p-limit": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sap/cds-dk/node_modules/p-locate": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sap/cds-dk/node_modules/parent-module": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/@sap/cds-dk/node_modules/parseurl": { "version": "1.3.3", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/@sap/cds-dk/node_modules/path-exists": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@sap/cds-dk/node_modules/path-key": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/@sap/cds-dk/node_modules/path-to-regexp": { - "version": "0.1.12", - "dev": true, - "license": "MIT" - }, - "node_modules/@sap/cds-dk/node_modules/picomatch": { - "version": "2.3.1", + "version": "8.3.0", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8.6" - }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/@sap/cds-dk/node_modules/pluralize": { "version": "8.0.0", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "dev": true, "license": "MIT", "engines": { @@ -2086,6 +1405,7 @@ }, "node_modules/@sap/cds-dk/node_modules/prebuild-install": { "version": "7.1.3", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", "dev": true, "license": "MIT", "optional": true, @@ -2110,16 +1430,9 @@ "node": ">=10" } }, - "node_modules/@sap/cds-dk/node_modules/prelude-ls": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/@sap/cds-dk/node_modules/proxy-addr": { "version": "2.0.7", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "dev": true, "license": "MIT", "dependencies": { @@ -2132,11 +1445,13 @@ }, "node_modules/@sap/cds-dk/node_modules/proxy-from-env": { "version": "1.1.0", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true, "license": "MIT" }, "node_modules/@sap/cds-dk/node_modules/pump": { - "version": "3.0.2", + "version": "3.0.3", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", "dev": true, "license": "MIT", "optional": true, @@ -2145,20 +1460,13 @@ "once": "^1.3.1" } }, - "node_modules/@sap/cds-dk/node_modules/punycode": { - "version": "2.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/@sap/cds-dk/node_modules/qs": { - "version": "6.13.0", + "version": "6.14.1", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -2169,6 +1477,7 @@ }, "node_modules/@sap/cds-dk/node_modules/range-parser": { "version": "1.2.1", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, "license": "MIT", "engines": { @@ -2176,21 +1485,23 @@ } }, "node_modules/@sap/cds-dk/node_modules/raw-body": { - "version": "2.5.2", + "version": "3.0.2", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", "dev": true, "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.10" } }, "node_modules/@sap/cds-dk/node_modules/rc": { "version": "1.2.8", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "optional": true, @@ -2204,17 +1515,9 @@ "rc": "cli.js" } }, - "node_modules/@sap/cds-dk/node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@sap/cds-dk/node_modules/readable-stream": { "version": "3.6.2", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "license": "MIT", "optional": true, @@ -2227,16 +1530,25 @@ "node": ">= 6" } }, - "node_modules/@sap/cds-dk/node_modules/resolve-from": { - "version": "4.0.0", + "node_modules/@sap/cds-dk/node_modules/router": { + "version": "2.2.0", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", "dev": true, "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, "engines": { - "node": ">=4" + "node": ">= 18" } }, "node_modules/@sap/cds-dk/node_modules/safe-buffer": { "version": "5.2.1", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { @@ -2252,22 +1564,30 @@ "url": "https://feross.org/support" } ], - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/@sap/cds-dk/node_modules/safer-buffer": { "version": "2.1.2", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "license": "MIT" }, "node_modules/@sap/cds-dk/node_modules/sax": { - "version": "1.4.1", + "version": "1.4.4", + "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", "dev": true, - "license": "ISC" + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } }, "node_modules/@sap/cds-dk/node_modules/semver": { - "version": "7.7.1", + "version": "7.7.3", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true, "license": "ISC", + "optional": true, "bin": { "semver": "bin/semver.js" }, @@ -2276,89 +1596,59 @@ } }, "node_modules/@sap/cds-dk/node_modules/send": { - "version": "0.19.0", + "version": "1.2.1", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", "dev": true, "license": "MIT", "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" }, "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/send/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@sap/cds-dk/node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@sap/cds-dk/node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/@sap/cds-dk/node_modules/serve-static": { - "version": "1.16.2", + "version": "2.2.1", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", "dev": true, "license": "MIT", "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/@sap/cds-dk/node_modules/setprototypeof": { "version": "1.2.0", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true, "license": "ISC" }, - "node_modules/@sap/cds-dk/node_modules/shebang-command": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sap/cds-dk/node_modules/shebang-regex": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/@sap/cds-dk/node_modules/side-channel": { "version": "1.1.0", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "license": "MIT", "dependencies": { @@ -2377,6 +1667,7 @@ }, "node_modules/@sap/cds-dk/node_modules/side-channel-list": { "version": "1.0.0", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "dev": true, "license": "MIT", "dependencies": { @@ -2392,6 +1683,7 @@ }, "node_modules/@sap/cds-dk/node_modules/side-channel-map": { "version": "1.0.1", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, "license": "MIT", "dependencies": { @@ -2409,6 +1701,7 @@ }, "node_modules/@sap/cds-dk/node_modules/side-channel-weakmap": { "version": "1.0.2", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, "license": "MIT", "dependencies": { @@ -2427,6 +1720,7 @@ }, "node_modules/@sap/cds-dk/node_modules/simple-concat": { "version": "1.0.1", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", "dev": true, "funding": [ { @@ -2447,6 +1741,7 @@ }, "node_modules/@sap/cds-dk/node_modules/simple-get": { "version": "4.0.1", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", "dev": true, "funding": [ { @@ -2472,6 +1767,7 @@ }, "node_modules/@sap/cds-dk/node_modules/source-map": { "version": "0.6.1", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -2479,7 +1775,8 @@ } }, "node_modules/@sap/cds-dk/node_modules/statuses": { - "version": "2.0.1", + "version": "2.0.2", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "dev": true, "license": "MIT", "engines": { @@ -2488,6 +1785,7 @@ }, "node_modules/@sap/cds-dk/node_modules/string_decoder": { "version": "1.3.0", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "license": "MIT", "optional": true, @@ -2496,29 +1794,18 @@ } }, "node_modules/@sap/cds-dk/node_modules/strip-json-comments": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sap/cds-dk/node_modules/supports-color": { - "version": "7.2.0", + "version": "2.0.1", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true, "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, + "optional": true, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, "node_modules/@sap/cds-dk/node_modules/tar-fs": { - "version": "2.1.2", + "version": "2.1.4", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", "dev": true, "license": "MIT", "optional": true, @@ -2531,6 +1818,7 @@ }, "node_modules/@sap/cds-dk/node_modules/tar-stream": { "version": "2.2.0", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dev": true, "license": "MIT", "optional": true, @@ -2547,6 +1835,7 @@ }, "node_modules/@sap/cds-dk/node_modules/to-regex-range": { "version": "5.0.1", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2558,6 +1847,7 @@ }, "node_modules/@sap/cds-dk/node_modules/toidentifier": { "version": "1.0.1", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, "license": "MIT", "engines": { @@ -2566,6 +1856,7 @@ }, "node_modules/@sap/cds-dk/node_modules/tunnel-agent": { "version": "0.6.0", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dev": true, "license": "Apache-2.0", "optional": true, @@ -2576,24 +1867,15 @@ "node": "*" } }, - "node_modules/@sap/cds-dk/node_modules/type-check": { - "version": "0.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/@sap/cds-dk/node_modules/type-is": { - "version": "1.6.18", + "version": "2.0.1", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", "dev": true, "license": "MIT", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" }, "engines": { "node": ">= 0.6" @@ -2601,6 +1883,7 @@ }, "node_modules/@sap/cds-dk/node_modules/uglify-js": { "version": "3.19.3", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, "license": "BSD-2-Clause", "optional": true, @@ -2613,36 +1896,23 @@ }, "node_modules/@sap/cds-dk/node_modules/unpipe": { "version": "1.0.0", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/@sap/cds-dk/node_modules/uri-js": { - "version": "4.4.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, "node_modules/@sap/cds-dk/node_modules/util-deprecate": { "version": "1.0.2", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true, "license": "MIT", "optional": true }, - "node_modules/@sap/cds-dk/node_modules/utils-merge": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/@sap/cds-dk/node_modules/vary": { "version": "1.1.2", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, "license": "MIT", "engines": { @@ -2651,6 +1921,7 @@ }, "node_modules/@sap/cds-dk/node_modules/verror": { "version": "1.10.1", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", "dev": true, "license": "MIT", "dependencies": { @@ -2662,41 +1933,21 @@ "node": ">=0.6.0" } }, - "node_modules/@sap/cds-dk/node_modules/which": { - "version": "2.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@sap/cds-dk/node_modules/word-wrap": { - "version": "1.2.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@sap/cds-dk/node_modules/wordwrap": { "version": "1.0.0", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", "dev": true, "license": "MIT" }, "node_modules/@sap/cds-dk/node_modules/wrappy": { "version": "1.0.2", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true, - "license": "ISC", - "optional": true + "license": "ISC" }, "node_modules/@sap/cds-dk/node_modules/ws": { - "version": "8.18.1", + "version": "8.19.0", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", "dev": true, "license": "MIT", "engines": { @@ -2717,6 +1968,7 @@ }, "node_modules/@sap/cds-dk/node_modules/xml-js": { "version": "1.6.11", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", "dev": true, "license": "MIT", "dependencies": { @@ -2726,34 +1978,19 @@ "xml-js": "bin/cli.js" } }, - "node_modules/@sap/cds-dk/node_modules/xmlbuilder": { - "version": "15.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0" - } - }, "node_modules/@sap/cds-dk/node_modules/yaml": { - "version": "2.7.1", + "version": "2.8.2", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", "dev": true, "license": "ISC", "bin": { "yaml": "bin.mjs" }, "engines": { - "node": ">= 14" - } - }, - "node_modules/@sap/cds-dk/node_modules/yocto-queue": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" + "node": ">= 14.6" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/eemeli" } } } diff --git a/package.json b/package.json index 535d182..6183b12 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,6 @@ "app/incidents" ], "devDependencies": { - "@sap/cds-dk": "^8.6.1" + "@sap/cds-dk": "^9" } } diff --git a/pom.xml b/pom.xml index d5dd5ff..ef0b6b7 100644 --- a/pom.xml +++ b/pom.xml @@ -11,8 +11,8 @@ 1.0.0-SNAPSHOT 21 - 3.9.1 - 3.4.5 + 4.8.0-SNAPSHOT + 3.5.6 1.0.7 https://nodejs.org/dist/ UTF-8 diff --git a/requests.md b/requests.md new file mode 100644 index 0000000..2afbac4 --- /dev/null +++ b/requests.md @@ -0,0 +1,866 @@ +# CAP Java: OData Request/Response Cycle + +## Overview + +This application demonstrates SAP Cloud Application Programming Model (CAP) for Java. CAP provides an opinionated framework that handles OData protocol, database persistence, and business logic orchestration through a well-defined event-driven architecture. + +--- + +## 1. High-Level Architecture + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ CAP Java Runtime │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────────┐ │ +│ │ OData V4 │ │ Service │ │ Persistence Layer │ │ +│ │ Adapter │───▶│ Layer │───▶│ (PersistenceService) │ │ +│ │ │ │ │ │ │ │ +│ │ - Parse │ │ - Processor │ │ - CQN to SQL translation │ │ +│ │ - Serialize │ │ Service │ │ - Transaction management │ │ +│ │ - $metadata │ │ - Admin │ │ - Database execution │ │ +│ │ │ │ Service │ │ │ │ +│ └──────────────┘ └──────────────┘ └──────────────────────────────┘ │ +│ │ │ │ │ +│ │ ▼ │ │ +│ │ ┌──────────────┐ │ │ +│ │ │ Event │ │ │ +│ │ │ Handlers │ │ │ +│ │ │ │ │ │ +│ │ │ @Before │ │ │ +│ │ │ @On │ │ │ +│ │ │ @After │ │ │ +│ │ └──────────────┘ │ │ +│ │ │ │ +└──────────┼──────────────────────────────────────────────┼───────────────────┘ + │ │ + ▼ ▼ + ┌─────────────┐ ┌─────────────────┐ + │ HTTP │ │ Database │ + │ Client │ │ (H2/HANA) │ + └─────────────┘ └─────────────────┘ +``` + +## 2. The CDS Model Layer + +CAP uses **CDS (Core Data Services)** to define both the domain model and service exposure: + +### Domain Model + +**File:** [`db/schema.cds`](db/schema.cds) + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Domain Model │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────┐ ┌─────────────┐ │ +│ │ Incidents │────────▶│ Customers │ │ +│ │ │ N:1 │ │ │ +│ │ - title │ │ - name │ │ +│ │ - urgency ─┼────┐ │ - email │ │ +│ │ - status ──┼──┐ │ │ - phone │ │ +│ │ │ │ │ │ │ │ +│ └──────┬──────┘ │ │ └──────┬──────┘ │ +│ │ │ │ │ │ +│ │ 1:N │ │ │ 1:N │ +│ ▼ │ │ ▼ │ +│ ┌─────────────┐ │ │ ┌─────────────┐ │ +│ │Conversation │ │ │ │ Addresses │ │ +│ │ - author │ │ │ │ - city │ │ +│ │ - message │ │ │ │ - postCode │ │ +│ └─────────────┘ │ │ └─────────────┘ │ +│ │ │ │ +│ ┌─────────┘ └─────────┐ │ +│ ▼ ▼ │ +│ ┌─────────────┐ ┌─────────────┐ │ +│ │ Status │ │ Urgency │ (CodeList entities) │ +│ │ N,A,I,H, │ │ H, M, L │ │ +│ │ R,C │ │ │ │ +│ └─────────────┘ └─────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +**Code Reference:** [`db/schema.cds:7-18`](db/schema.cds) - Incidents entity definition + +```cds +entity Incidents : cuid, managed { + customer : Association to Customers; + title : String @title : 'Title'; + urgency : Association to Urgency default 'M'; + status : Association to Status default 'N'; + conversation : Composition of many { ... }; +} +``` + +### Service Projections + +**File:** [`srv/services.cds`](srv/services.cds) + +``` +┌────────────────────────────────────┐ ┌────────────────────────────────────┐ +│ ProcessorService │ │ AdminService │ +│ @requires: 'support' │ │ @requires: 'admin' │ +├────────────────────────────────────┤ ├────────────────────────────────────┤ +│ │ │ │ +│ Incidents │ │ Incidents │ +│ ├── @odata.draft.enabled │ │ └── full CRUD │ +│ └── full CRUD │ │ │ +│ │ │ Customers │ +│ Customers │ │ └── full CRUD │ +│ └── @readonly │ │ │ +│ │ │ │ +└────────────────────────────────────┘ └────────────────────────────────────┘ + │ │ + │ OData Endpoint │ OData Endpoint + ▼ ▼ + /odata/v4/ProcessorService /odata/v4/AdminService +``` + +**Code Reference:** [`srv/services.cds:6-9`](srv/services.cds) - ProcessorService definition + +```cds +service ProcessorService { + entity Incidents as projection on my.Incidents; + entity Customers @readonly as projection on my.Customers; +} +``` + +**Code Reference:** [`srv/services.cds:19-21`](srv/services.cds) - Annotations + +```cds +annotate ProcessorService.Incidents with @odata.draft.enabled; +annotate ProcessorService with @(requires: 'support'); +annotate AdminService with @(requires: 'admin'); +``` + +--- + +## 3. Request/Response Flow: CREATE Example + +Let's trace a `POST /odata/v4/ProcessorService/Incidents` request through the actual code: + +``` +┌──────────────────────────────────────────────────────────────────────────────────┐ +│ CREATE Incident Flow │ +└──────────────────────────────────────────────────────────────────────────────────┘ + + Client Database + │ │ + │ POST /odata/v4/ProcessorService/Incidents │ + │ { "title": "Urgent: Server down", "customer_ID": "1001" } │ + │ │ + ▼ │ +``` + +### Step 1: HTTP Entry Point (OData Servlet) + +**Class:** `com.sap.cds.adapter.odata.v4.AbstractCdsODataServlet` +**Artifact:** `cds-adapter-odata-v4` + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 1. OData V4 Adapter Entry Point │ +│ ┌──────────────────────────────────────────────────────────────────────────┐│ +│ │ ││ +│ │ AbstractCdsODataServlet.service(HttpServletRequest, HttpServletResponse)││ +│ │ ││ +│ │ • Establishes request context with runtime.requestContext() ││ +│ │ • Extracts service name from URL: "ProcessorService" ││ +│ │ • Validates service definition exists ││ +│ │ • Initializes Olingo OData infrastructure (EDM, metadata) ││ +│ │ • Registers OlingoProcessor as the request processor ││ +│ │ • Calls odataHandler.process(req, resp) ││ +│ │ ││ +│ └──────────────────────────────────────────────────────────────────────────┘│ +└─────────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +``` + +### Step 2: Olingo Processing Bridge + +**Class:** `com.sap.cds.adapter.odata.v4.processors.OlingoProcessor` +**Implements:** `EntityProcessor`, `ActionEntityProcessor`, `BatchProcessor`, etc. + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 2. Olingo Processor Bridge │ +│ ┌─────────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ OlingoProcessor implements all Olingo processor interfaces │ │ +│ │ │ │ +│ │ • Receives parsed OData request from Olingo │ │ +│ │ • Delegates to CdsProcessor for CAP-specific handling │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +``` + +### Step 3: CQN Conversion & Service Dispatch + +**Class:** `com.sap.cds.adapter.odata.v4.processors.CdsProcessor` +**Key Methods:** +- `processRequest()` - Main entry point +- `post()` - Handles POST/CREATE requests +- `delegateRequest()` - Routes by HTTP method + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 3. CQN Conversion (CdsProcessor) │ +│ ┌─────────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ CdsProcessor.post(CdsODataRequest request) │ │ +│ │ │ │ +│ │ // Get the target service │ │ +│ │ ApplicationService applicationService = globals.getApplicationService();││ +│ │ │ │ +│ │ // Convert OData payload to CQN Insert statement │ │ +│ │ Insert insert = Insert.into(ref).entry(entityData); │ │ +│ │ │ │ +│ │ // Dispatch to service layer (triggers event handlers) │ │ +│ │ result = applicationService.run(insert); // ◄── SERVICE DISPATCH │ │ +│ │ │ │ +│ │ return new CdsODataResponse(SC_CREATED, remapResult(...)); │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────────┘ + │ + │ applicationService.run(insert) + ▼ +``` + +### Step 4: Event Handler Chain + +**Interface:** `com.sap.cds.services.cds.ApplicationService` +**Interface:** `com.sap.cds.services.handler.EventHandler` + +The `applicationService.run()` call triggers the event handler chain: + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 4. Service Layer - Event Dispatch │ +│ ┌─────────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ ApplicationService.run(CqnInsert) │ │ +│ │ │ │ +│ │ • Authorization check: user has 'support' role? (from @requires) │ │ +│ │ • Emit event: CqnService.EVENT_CREATE ("CREATE") │ │ +│ │ • Find registered handlers via @ServiceName annotation │ │ +│ │ • Execute handler chain: @Before → @On → @After │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +``` + +### Step 5: @Before Handler Execution + +**File:** [`srv/src/main/java/customer/incident_management/handler/ProcessorServiceHandler.java`](srv/src/main/java/customer/incident_management/handler/ProcessorServiceHandler.java) + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 5. @Before Handler Phase │ +│ ┌─────────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ ProcessorServiceHandler.java:35-45 │ │ +│ │ ───────────────────────────────────────────────────────────────────── │ │ +│ │ │ │ +│ │ @Before(event = CqnService.EVENT_CREATE) │ │ +│ │ public void ensureHighUrgencyForIncidentsWithUrgentInTitle( │ │ +│ │ List incidents) { │ │ +│ │ for (Incidents incident : incidents) { │ │ +│ │ if (incident.getTitle() │ │ +│ │ .toLowerCase(Locale.ENGLISH) │ │ +│ │ .contains("urgent") && │ │ +│ │ incident.getUrgencyCode() == null || │ │ +│ │ !incident.getUrgencyCode().equals("H")) { │ │ +│ │ │ │ +│ │ incident.setUrgencyCode("H"); // ◄── MUTATE INPUT │ │ +│ │ logger.info("Adjusted Urgency..."); │ │ +│ │ } │ │ +│ │ } │ │ +│ │ } │ │ +│ │ │ │ +│ │ Input: { title: "Urgent: Server down", urgency_code: null } │ │ +│ │ Output: { title: "Urgent: Server down", urgency_code: "H" } │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +``` + +### Step 6: @On Handler (Default Persistence) + +**Interface:** `com.sap.cds.services.persistence.PersistenceService` + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 6. @On Handler Phase (Default: GenericHandler → PersistenceService) │ +│ ┌─────────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ No custom @On handler in this app │ │ +│ │ │ │ +│ │ CAP's built-in GenericHandler delegates to: │ │ +│ │ PersistenceService.run(CqnInsert) │ │ +│ │ │ │ +│ │ The PersistenceService: │ │ +│ │ • Translates CQN to SQL (database-specific) │ │ +│ │ • Manages transaction boundaries │ │ +│ │ • Executes the SQL statement │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +``` + +### Step 7: SQL Generation & Execution + +**Package:** `com.sap.cds.impl.sql.*` (in `cds4j-runtime`) +**Generated Schema:** [`srv/src/main/resources/schema-h2.sql`](srv/src/main/resources/schema-h2.sql) (generated at build time) + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 7. Persistence Layer - SQL Execution │ +│ ┌─────────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ CQN to SQL Translation (com.sap.cds.impl.sql.*) │ │ +│ │ │ │ +│ │ INSERT INTO sap_capire_incidents_Incidents │ │ +│ │ (ID, title, urgency_code, status_code, customer_ID, │ │ +│ │ createdAt, createdBy, modifiedAt, modifiedBy) │ │ +│ │ VALUES │ │ +│ │ (UUID, 'Urgent: Server down', 'H', 'N', '1001', │ │ +│ │ NOW(), 'alice', NOW(), 'alice') │ │ +│ │ │ │ +│ │ Target table defined in: schema-h2.sql (generated from schema.cds) │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ + ┌───────────┐ + │ H2 │ + │ Database │ + └─────┬─────┘ + │ + │ (Result: 1 row inserted) + ▼ +``` + +### Step 8: @After Handler & Response + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 8. @After Handler Phase │ +│ ┌─────────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ No custom @After handler in this app │ │ +│ │ Could be used for: audit logging, notifications, enrichment │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 9. Response Serialization │ +│ ┌─────────────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ CdsProcessor.post() returns: │ │ +│ │ new CdsODataResponse(SC_CREATED, remapResult(result, entity, null)) │ │ +│ │ │ │ +│ │ OlingoProcessor serializes to OData JSON format │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ + Client receives: + HTTP/1.1 201 Created + { + "ID": "...", + "title": "Urgent: Server down", + "urgency_code": "H", + "status_code": "N", + ... + } +``` + +--- + +## 4. Event Handler Phases + +CAP Java uses three handler phases, executed in order: + +``` +┌────────────────────────────────────────────────────────────────────────────────┐ +│ Event Handler Lifecycle │ +├────────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────────┐ │ +│ │ @Before Phase │ │ +│ │ │ │ +│ │ Annotation: com.sap.cds.services.handler.annotations.Before │ │ +│ │ │ │ +│ │ Purpose: Validation, input mutation, authorization checks │ │ +│ │ │ │ +│ │ • Runs BEFORE the main operation │ │ +│ │ • Can modify input data │ │ +│ │ • Can reject request by throwing ServiceException │ │ +│ │ • Multiple @Before handlers execute in registration order │ │ +│ │ │ │ +│ │ This app's handlers: │ │ +│ │ ┌───────────────────────────────────────────────────────────────────┐ │ │ +│ │ │ ProcessorServiceHandler.java:35-45 │ │ │ +│ │ │ @Before(event = CqnService.EVENT_CREATE) │ │ │ +│ │ │ ensureHighUrgencyForIncidentsWithUrgentInTitle(List) │ │ │ +│ │ │ → Mutates urgency_code if title contains "urgent" │ │ │ +│ │ │ │ │ │ +│ │ │ ProcessorServiceHandler.java:50-57 │ │ │ +│ │ │ @Before(event = CqnService.EVENT_UPDATE) │ │ │ +│ │ │ ensureNoUpdateOnClosedIncidents(Incidents) │ │ │ +│ │ │ → Throws ServiceException(CONFLICT) if status = 'C' │ │ │ +│ │ └───────────────────────────────────────────────────────────────────┘ │ │ +│ └─────────────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────────────┐ │ +│ │ @On Phase │ │ +│ │ │ │ +│ │ Annotation: com.sap.cds.services.handler.annotations.On │ │ +│ │ │ │ +│ │ Purpose: Main operation execution │ │ +│ │ │ │ +│ │ • The actual CRUD operation happens here │ │ +│ │ • Default: CAP's GenericHandler delegates to PersistenceService │ │ +│ │ • Custom @On handler REPLACES default behavior │ │ +│ │ • Only ONE @On handler executes (first registered wins) │ │ +│ │ │ │ +│ │ Use cases for custom @On: │ │ +│ │ • Call external APIs instead of/alongside database │ │ +│ │ • Complex multi-step operations │ │ +│ │ • Custom actions/functions │ │ +│ └─────────────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────────────┐ │ +│ │ @After Phase │ │ +│ │ │ │ +│ │ Annotation: com.sap.cds.services.handler.annotations.After │ │ +│ │ │ │ +│ │ Purpose: Post-processing, side effects │ │ +│ │ │ │ +│ │ • Runs AFTER the main operation completes successfully │ │ +│ │ • Can modify response data │ │ +│ │ • Can trigger side effects (notifications, audit logs, etc.) │ │ +│ │ • Multiple @After handlers execute in registration order │ │ +│ │ │ │ +│ │ Common uses: │ │ +│ │ • Enrich response with computed fields │ │ +│ │ • Send notifications │ │ +│ │ • Log audit trails │ │ +│ │ • Trigger downstream workflows │ │ +│ └─────────────────────────────────────────────────────────────────────────┘ │ +│ │ +└────────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 5. UPDATE Flow with Validation Rejection + +The `@Before(EVENT_UPDATE)` handler demonstrates request rejection. + +**File:** [`srv/src/main/java/customer/incident_management/handler/ProcessorServiceHandler.java:50-57`](srv/src/main/java/customer/incident_management/handler/ProcessorServiceHandler.java) + +``` + Client Database + │ │ + │ PATCH /odata/v4/ProcessorService/Incidents(ID='...') │ + │ { "title": "Updated title" } │ + │ │ + ▼ │ +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ @Before(EVENT_UPDATE) - ProcessorServiceHandler.java:50-57 │ +│ ┌─────────────────────────────────────────────────────────────────────────────┐│ +│ │ ││ +│ │ @Before(event = CqnService.EVENT_UPDATE) ││ +│ │ public void ensureNoUpdateOnClosedIncidents(Incidents incident) { ││ +│ │ ││ +│ │ // Line 52: Query current state using PersistenceService ││ +│ │ Incidents in = db.run( ││ +│ │ Select.from(Incidents_.class) ││ +│ │ .where(i -> i.ID().eq(incident.getId())) ││ +│ │ ).single(Incidents.class); ││ +│ │ ││ +│ │ // Line 53-55: Check status and reject if closed ││ +│ │ if (in.getStatusCode().equals("C")) { ││ +│ │ throw new ServiceException( |│ +│ │ ErrorStatuses.CONFLICT, ◄─── HTTP 409 |│ +│ │ "Can't modify a closed incident" |│ +│ │ ); |│ +│ │ } |│ +│ │ } ││ +│ │ ││ +│ └─────────────────────────────────────────────────────────────────────────────┘│ +└─────────────────────────────────────────────────────────────────────────────────┘ + │ + ┌───────────────────────┴───────────────────────┐ + │ │ + ▼ ▼ + Status = 'C' (Closed) Status != 'C' + │ │ + ▼ ▼ + ┌─────────────────────┐ ┌─────────────────────┐ + │ ServiceException │ │ Continue to @On │ + │ thrown │ │ phase (UPDATE │ + │ │ │ proceeds) │ + └──────────┬──────────┘ └─────────────────────┘ + │ + ▼ + Client receives: + HTTP/1.1 409 Conflict + { + "error": { + "code": "409", + "message": "Can't modify a closed incident" + } + } +``` + +**Key Classes Used:** + +| Import | Purpose | +|--------|---------| +| `com.sap.cds.services.ErrorStatuses` | HTTP status code mappings | +| `com.sap.cds.services.ServiceException` | Exception that maps to HTTP error response | +| `com.sap.cds.services.persistence.PersistenceService` | Direct database access | +| `com.sap.cds.ql.Select` | CQN query builder | + +--- + +## 6. CQN (CDS Query Notation) + +CQN is CAP's internal query representation, independent of the database. + +**Package:** `com.sap.cds.ql.*` + +``` +┌────────────────────────────────────────────────────────────────────────────────┐ +│ CQN: Abstraction Layer for Queries │ +├────────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ OData Request CQN Representation │ +│ ───────────── ────────────────── │ +│ │ +│ GET /Incidents?$filter=urgency_code eq 'H' │ +│ ──────────────────────────────────────────── │ +│ │ +│ // com.sap.cds.ql.Select │ +│ Select.from(Incidents_.class) │ +│ .where(i -> i.urgency().code().eq("H")) │ +│ │ +│ CdsProcessor.get() builds this from OData $filter │ +│ │ +│ ═══════════════════════════════════════════════════════════════════════════ │ +│ │ +│ POST /Incidents { "title": "New issue" } │ +│ ──────────────────────────────────────── │ +│ │ +│ // com.sap.cds.ql.Insert │ +│ Insert.into(Incidents_.class) │ +│ .entry(incident) │ +│ │ +│ CdsProcessor.post(): Insert insert = Insert.into(ref).entry(entityData); │ +│ │ +│ ═══════════════════════════════════════════════════════════════════════════ │ +│ │ +│ PATCH /Incidents(ID='xxx') { "status_code": "R" } │ +│ ───────────────────────────────────────────────── │ +│ │ +│ // com.sap.cds.ql.Update │ +│ Update.entity(Incidents_.class) │ +│ .data(incident) │ +│ .where(i -> i.ID().eq("xxx")) │ +│ │ +│ CdsProcessor.patch(): CqnUpdate update = Update.entity(ref).data(entityData);│ +│ │ +│ ═══════════════════════════════════════════════════════════════════════════ │ +│ │ +│ DELETE /Incidents(ID='xxx') │ +│ ─────────────────────────── │ +│ │ +│ // com.sap.cds.ql.Delete │ +│ Delete.from(Incidents_.class) │ +│ .where(i -> i.ID().eq("xxx")) │ +│ │ +│ CdsProcessor.delete(): CqnDelete delete = Delete.from(toPathExpression(...));│ +│ │ +└────────────────────────────────────────────────────────────────────────────────┘ + + │ + │ PersistenceService.run() translates + │ via com.sap.cds.impl.sql.* + ▼ + +┌────────────────────────────────────────────────────────────────────────────────┐ +│ Generated SQL │ +├────────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ SELECT * FROM sap_capire_incidents_Incidents WHERE urgency_code = 'H' │ +│ │ +│ INSERT INTO sap_capire_incidents_Incidents (...) VALUES (...) │ +│ │ +│ UPDATE sap_capire_incidents_Incidents SET status_code = 'R' WHERE ID = ... │ +│ │ +│ DELETE FROM sap_capire_incidents_Incidents WHERE ID = ... │ +│ │ +│ Table names from: srv/src/main/resources/schema-h2.sql (generated) │ +│ │ +└────────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 7. Handler Registration & Spring Integration + +**File:** [`srv/src/main/java/customer/incident_management/handler/ProcessorServiceHandler.java`](srv/src/main/java/customer/incident_management/handler/ProcessorServiceHandler.java) + +```java +// Line 16: Spring component annotation +@Component // Spring-managed bean + +// Line 21: Binds this handler to ProcessorService +@ServiceName(ProcessorService_.CDS_NAME) // "ProcessorService" + +// Line 22: Implements CAP's EventHandler marker interface +public class ProcessorServiceHandler implements EventHandler { + + // Line 26: PersistenceService for direct DB access + private final PersistenceService db; // Injected by Spring + + // Line 28-30: Constructor injection + public ProcessorServiceHandler(PersistenceService db) { + this.db = db; + } + + // Line 35: Register for CREATE events on Incidents + @Before(event = CqnService.EVENT_CREATE) + public void ensureHighUrgencyForIncidentsWithUrgentInTitle( + List incidents) { // CAP deserializes request body + // Handler logic... + } +} +``` + +### Key Annotations & Interfaces + +| Annotation/Interface | Package | Purpose | +|---------------------|---------|---------| +| `@Component` | `org.springframework.stereotype` | Spring bean registration | +| `@ServiceName` | `com.sap.cds.services.handler.annotations` | Binds handler to CDS service | +| `EventHandler` | `com.sap.cds.services.handler` | Marker interface for CAP handlers | +| `@Before` | `com.sap.cds.services.handler.annotations` | Pre-operation handler | +| `@On` | `com.sap.cds.services.handler.annotations` | Main operation handler | +| `@After` | `com.sap.cds.services.handler.annotations` | Post-operation handler | + +### Event Constants + +**Class:** `com.sap.cds.services.cds.CqnService` + +| Constant | Value | Triggered By | +|----------|-------|--------------| +| `EVENT_CREATE` | `"CREATE"` | POST (new entity) | +| `EVENT_READ` | `"READ"` | GET | +| `EVENT_UPDATE` | `"UPDATE"` | PATCH/PUT | +| `EVENT_DELETE` | `"DELETE"` | DELETE | + +### Generated POJOs + +**Location:** `srv/src/gen/java/cds/gen/` +**Generated By:** `cds-maven-plugin` during build + +| Generated Class | Source | +|-----------------|--------| +| `cds.gen.processorservice.Incidents` | `srv/services.cds` projection | +| `cds.gen.processorservice.ProcessorService_` | Service metadata | +| `cds.gen.sap.capire.incidents.Incidents_` | Entity metadata (for CQN queries) | + +--- + +## 8. Draft-Enabled Entities + +**Annotation:** [`srv/services.cds:19`](srv/services.cds) + +```cds +annotate ProcessorService.Incidents with @odata.draft.enabled; +``` + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ Draft Entity Lifecycle │ +├─────────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ 1. CREATE (New Draft) │ +│ POST /ProcessorService/Incidents │ +│ ───────────────────────────────────────────────────────────────────── │ +│ → Creates draft record (IsActiveEntity = false) │ +│ → Stored in: ProcessorService_Incidents_drafts table │ +│ │ +│ 2. EDIT (Modify Draft) │ +│ PATCH /ProcessorService/Incidents(ID='...',IsActiveEntity=false) │ +│ ───────────────────────────────────────────────────────────────────── │ +│ → Updates draft without touching active entity │ +│ → Multiple users can see draft state │ +│ │ +│ 3. ACTIVATE (Promote to Active) │ +│ POST .../Incidents(...,IsActiveEntity=false)/ProcessorService.draftActivate│ +│ ───────────────────────────────────────────────────────────────────── │ +│ → Validates draft │ +│ → Moves to active table (IsActiveEntity = true) │ +│ → Deletes draft record │ +│ │ +│ 4. DISCARD │ +│ DELETE /ProcessorService/Incidents(ID='...',IsActiveEntity=false) │ +│ ───────────────────────────────────────────────────────────────────── │ +│ → Removes draft without affecting active entity │ +│ │ +│ │ +│ ┌─────────────────────┐ ┌─────────────────────┐ │ +│ │ │ │ │ │ +│ │ Draft Tables │ draftActivate │ Active Tables │ │ +│ │ ─────────────── │ ─────────────► │ ───────────── │ │ +│ │ IsActiveEntity │ │ IsActiveEntity │ │ +│ │ = false │ │ = true │ │ +│ │ │ │ │ │ +│ └─────────────────────┘ └─────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 9. Complete Request Flow Summary + +``` +HTTP Request (POST /odata/v4/ProcessorService/Incidents) + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────────┐ +│ AbstractCdsODataServlet.service() │ +│ Package: com.sap.cds.adapter.odata.v4 │ +│ • Establishes request context │ +│ • Extracts service name from URL │ +│ • Initializes Olingo OData infrastructure │ +└─────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────────┐ +│ OlingoProcessor │ +│ Package: com.sap.cds.adapter.odata.v4.processors │ +│ • Implements Olingo processor interfaces │ +│ • Delegates to CdsProcessor │ +└─────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────────┐ +│ CdsProcessor.post() │ +│ Package: com.sap.cds.adapter.odata.v4.processors │ +│ • Converts OData request to CQN: Insert.into(ref).entry(entityData) │ +│ • Calls applicationService.run(insert) │ +└─────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────────┐ +│ ApplicationService.run(CqnInsert) │ +│ Interface: com.sap.cds.services.cds.ApplicationService │ +│ • Authorization check (@requires annotation) │ +│ • Emits EVENT_CREATE event │ +│ • Triggers handler chain │ +└─────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────────┐ +│ @Before Handler │ +│ File: ProcessorServiceHandler.java:35-45 │ +│ Method: ensureHighUrgencyForIncidentsWithUrgentInTitle() │ +│ • Validates/mutates input data │ +│ • Can throw ServiceException to reject request │ +└─────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────────┐ +│ @On Handler (Default: GenericHandler) │ +│ • Delegates to PersistenceService.run(CqnInsert) │ +└─────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PersistenceService.run() │ +│ Interface: com.sap.cds.services.persistence.PersistenceService │ +│ Implementation: com.sap.cds.impl.sql.* (in cds4j-runtime) │ +│ • Translates CQN to SQL │ +│ • Executes within transaction │ +└─────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────────┐ +│ Database (H2) │ +│ Schema: srv/src/main/resources/schema-h2.sql │ +│ Table: sap_capire_incidents_Incidents │ +└─────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────────┐ +│ @After Handler (none in this app) │ +│ • Post-processing, side effects │ +└─────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────────┐ +│ Response Serialization │ +│ CdsProcessor: return new CdsODataResponse(SC_CREATED, remapResult(...)) │ +│ OlingoProcessor: Serializes to OData JSON │ +└─────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +HTTP Response (201 Created + JSON body) +``` + +--- + +## 10. Key Files Reference + +| File | Purpose | +|------|---------| +| [`db/schema.cds`](db/schema.cds) | Domain model (entities, associations) | +| [`srv/services.cds`](srv/services.cds) | Service definitions, projections, annotations | +| [`srv/src/main/java/customer/incident_management/handler/ProcessorServiceHandler.java`](srv/src/main/java/customer/incident_management/handler/ProcessorServiceHandler.java) | Custom event handlers | +| [`srv/src/main/java/customer/incident_management/Application.java`](srv/src/main/java/customer/incident_management/Application.java) | Spring Boot entry point | +| [`srv/src/main/resources/application.yaml`](srv/src/main/resources/application.yaml) | Runtime configuration | +| `srv/src/main/resources/schema-h2.sql` | Generated database schema | +| `srv/src/gen/java/cds/gen/` | Generated POJOs from CDS | + +--- + +## 11. Key Takeaways + +| Concept | Description | +|---------|-------------| +| **CDS-First** | Define models in CDS; CAP generates SQL, POJOs, and OData metadata | +| **Event-Driven** | All operations emit events; handlers intercept at `@Before`/`@On`/`@After` | +| **CQN** | Database-agnostic query notation; same code works on H2, HANA, PostgreSQL | +| **Service Projections** | Multiple services can expose different views of the same entities | +| **Type-Safe POJOs** | Generated from CDS; handlers receive/return typed objects | +| **Spring Integration** | Handlers are Spring beans with full DI support | +| **Draft Support** | Built-in collaborative editing via `@odata.draft.enabled` | +| **Declarative Security** | `@requires` annotation on services enforces role-based access | + +The beauty of CAP Java is that most of the boilerplate (OData parsing, SQL generation, transaction management) is handled automatically, allowing developers to focus on business logic in event handlers.