Spaces:
Running
Running
feat: explain seven TeaQL runtimes (part 2)
Browse filesExplain that the browser executes TypeScript, list all seven supported TeaQL runtimes with language icons and source links, retain an exact tested source snapshot, and publish the rebuilt static app.
This view is limited to 50 files because it contains too many changes. See raw diff
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/customer_order.description.md +71 -0
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/customer_order.id.md +70 -0
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/customer_order.md +104 -0
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/customer_order.order_item_list.md +71 -0
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/customer_order.payment_list.md +71 -0
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/customer_order.platform.md +69 -0
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/customer_order.shipment_list.md +71 -0
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/order_item.md +95 -0
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/order_item.name.md +71 -0
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/payment.customer_order.md +69 -0
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/payment.md +101 -0
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/payment.payment_attempt_list.md +71 -0
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/payment.reference_code.md +71 -0
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/payment_attempt.md +95 -0
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/payment_attempt.payment.md +69 -0
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/platform.md +100 -0
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-update/customer_order.md +93 -0
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-update/order_item.md +91 -0
- source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-update/payment.md +91 -0
- source/teaql-ts/examples/trace-chain/evidence/evaluation.md +30 -0
- source/teaql-ts/examples/trace-chain/evidence/generated-library-manifest.sha256 +22 -0
- source/teaql-ts/examples/trace-chain/evidence/shared-reference-library.sha256 +22 -0
- source/teaql-ts/examples/trace-chain/lib/package.json +13 -0
- source/teaql-ts/examples/trace-chain/lib/src/generated-bootstrap.ts +14 -0
- source/teaql-ts/examples/trace-chain/lib/src/generated-search-models.ts +128 -0
- source/teaql-ts/examples/trace-chain/lib/src/generated/E.ts +893 -0
- source/teaql-ts/examples/trace-chain/lib/src/generated/Q.ts +52 -0
- source/teaql-ts/examples/trace-chain/lib/src/generated/models/CustomerOrder.ts +407 -0
- source/teaql-ts/examples/trace-chain/lib/src/generated/models/OrderItem.ts +219 -0
- source/teaql-ts/examples/trace-chain/lib/src/generated/models/Payment.ts +278 -0
- source/teaql-ts/examples/trace-chain/lib/src/generated/models/PaymentAttempt.ts +219 -0
- source/teaql-ts/examples/trace-chain/lib/src/generated/models/Platform.ts +262 -0
- source/teaql-ts/examples/trace-chain/lib/src/generated/models/Shipment.ts +219 -0
- source/teaql-ts/examples/trace-chain/lib/src/generated/requests/CustomerOrderRequest.ts +907 -0
- source/teaql-ts/examples/trace-chain/lib/src/generated/requests/OrderItemRequest.ts +611 -0
- source/teaql-ts/examples/trace-chain/lib/src/generated/requests/PaymentAttemptRequest.ts +611 -0
- source/teaql-ts/examples/trace-chain/lib/src/generated/requests/PaymentRequest.ts +672 -0
- source/teaql-ts/examples/trace-chain/lib/src/generated/requests/PlatformRequest.ts +607 -0
- source/teaql-ts/examples/trace-chain/lib/src/generated/requests/ShipmentRequest.ts +611 -0
- source/teaql-ts/examples/trace-chain/lib/src/runtime-module.ts +144 -0
- source/teaql-ts/examples/trace-chain/lib/src/teaql-schemas.ts +40 -0
- source/teaql-ts/examples/trace-chain/lib/src/teaql-ts.ts +308 -0
- source/teaql-ts/examples/trace-chain/lib/teaql-i18n.json +126 -0
- source/teaql-ts/examples/trace-chain/lib/tsconfig.json +12 -0
- source/teaql-ts/examples/trace-chain/model.xml +17 -0
- source/teaql-ts/examples/trace-chain/package-lock.json +826 -0
- source/teaql-ts/examples/trace-chain/package.json +7 -0
- source/teaql-ts/examples/trace-chain/paging.ts +124 -0
- source/teaql-ts/examples/trace-chain/plan-item-lineage.ts +160 -0
- source/teaql-ts/examples/trace-chain/relation-aggregate.ts +168 -0
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/customer_order.description.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# TypeScript Query Field Assist — `customer_order.description`
|
| 4 |
+
|
| 5 |
+
KSML entity: `Customer Order`
|
| 6 |
+
KSML field: `description`
|
| 7 |
+
Type: `string`
|
| 8 |
+
|
| 9 |
+
| Capability | Generated API |
|
| 10 |
+
| --- | --- |
|
| 11 |
+
| Select | `selectDescription()` |
|
| 12 |
+
| Equality/set | `withDescriptionIs(value)`, `withDescriptionIsNot(value)`, `withDescriptionIn(...values)`, `withDescriptionNotIn(...values)` |
|
| 13 |
+
| Comparison | `withDescriptionGreaterThan(value)`, `withDescriptionGreaterThanOrEqualTo(value)`, `withDescriptionLessThan(value)`, `withDescriptionLessThanOrEqualTo(value)`, `withDescriptionBetween(lower, upper)` |
|
| 14 |
+
| Null state | `withDescriptionIsKnown()`, `withDescriptionIsUnknown()` |
|
| 15 |
+
| String | `withDescriptionContaining(value)`, `withDescriptionNotContaining(value)`, `withDescriptionStartingWith(value)`, `withDescriptionEndingWith(value)`, `withDescriptionSoundingLike(value)` |
|
| 16 |
+
| Order | `orderByDescriptionAscending()`, `orderByDescriptionDescending()` |
|
| 17 |
+
| Group | `groupByDescription()`, `groupByDescriptionAs(alias)` |
|
| 18 |
+
Execution requires `comment(...)`, `purpose(...)`, and exactly one `context`.
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
---
|
| 22 |
+
|
| 23 |
+
## TeaQL seven-language assist contract
|
| 24 |
+
|
| 25 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 26 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 27 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 28 |
+
|
| 29 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 30 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 31 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 32 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 33 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 34 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 35 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 36 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 37 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 38 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 39 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 40 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 41 |
+
- If the required operation is absent after current entity/action and required field
|
| 42 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 43 |
+
generated library as a fallback.
|
| 44 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 45 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 46 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 47 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 48 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 49 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 50 |
+
|
| 51 |
+
Capability: `query`.
|
| 52 |
+
|
| 53 |
+
- Use generated projection, relation, predicate, sort, and aggregate APIs; never
|
| 54 |
+
concatenate application SQL or silently ignore an unsupported filter.
|
| 55 |
+
- Rows, record count, facets, and aggregates must share the same active filter.
|
| 56 |
+
- Add negative tests for missing purpose/comment and forbidden dynamic fields.
|
| 57 |
+
|
| 58 |
+
### Optional per-parent Top-N optimization
|
| 59 |
+
|
| 60 |
+
- Configure `topNProbeParentThreshold(threshold)` on the nested child request before its intent/execution
|
| 61 |
+
stage. Use the field-specific relation Assist for the exact generated selector.
|
| 62 |
+
- Give the child a per-parent limit and deterministic ordering with an ID tie-breaker;
|
| 63 |
+
bound the parent query separately. A single-parent detail query is not batch Top-N.
|
| 64 |
+
- Server providers default to a window query (`threshold = 0`). A positive threshold
|
| 65 |
+
permits bounded probes only when the already-loaded parent count is at or below it;
|
| 66 |
+
above it, use the window plan. SQLite uses its internal AlwaysProbe policy by default.
|
| 67 |
+
- Measure before opting in. Do not infer a threshold from table size or execute COUNT
|
| 68 |
+
or statistics queries to choose a plan. Keep an index on foreign key + sort + ID.
|
| 69 |
+
- Inspect selected-plan, parent-count, per-parent-limit and probe-count telemetry.
|
| 70 |
+
Runtime-managed probes are not application-owned N+1 loops; neither strategy changes
|
| 71 |
+
authorization, loaded-state semantics or the required comment/purpose.
|
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/customer_order.id.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# TypeScript Query Field Assist — `customer_order.id`
|
| 4 |
+
|
| 5 |
+
KSML entity: `Customer Order`
|
| 6 |
+
KSML field: `id`
|
| 7 |
+
Type: `id`
|
| 8 |
+
|
| 9 |
+
| Capability | Generated API |
|
| 10 |
+
| --- | --- |
|
| 11 |
+
| Select | `selectId()` |
|
| 12 |
+
| Equality/set | `withIdIs(value)`, `withIdIsNot(value)`, `withIdIn(...values)`, `withIdNotIn(...values)` |
|
| 13 |
+
| Comparison | `withIdGreaterThan(value)`, `withIdGreaterThanOrEqualTo(value)`, `withIdLessThan(value)`, `withIdLessThanOrEqualTo(value)`, `withIdBetween(lower, upper)` |
|
| 14 |
+
| Null state | `withIdIsKnown()`, `withIdIsUnknown()` |
|
| 15 |
+
| Order | `orderByIdAscending()`, `orderByIdDescending()` |
|
| 16 |
+
| Group | `groupById()`, `groupByIdAs(alias)` |
|
| 17 |
+
Execution requires `comment(...)`, `purpose(...)`, and exactly one `context`.
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
---
|
| 21 |
+
|
| 22 |
+
## TeaQL seven-language assist contract
|
| 23 |
+
|
| 24 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 25 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 26 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 27 |
+
|
| 28 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 29 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 30 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 31 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 32 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 33 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 34 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 35 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 36 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 37 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 38 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 39 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 40 |
+
- If the required operation is absent after current entity/action and required field
|
| 41 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 42 |
+
generated library as a fallback.
|
| 43 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 44 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 45 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 46 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 47 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 48 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 49 |
+
|
| 50 |
+
Capability: `query`.
|
| 51 |
+
|
| 52 |
+
- Use generated projection, relation, predicate, sort, and aggregate APIs; never
|
| 53 |
+
concatenate application SQL or silently ignore an unsupported filter.
|
| 54 |
+
- Rows, record count, facets, and aggregates must share the same active filter.
|
| 55 |
+
- Add negative tests for missing purpose/comment and forbidden dynamic fields.
|
| 56 |
+
|
| 57 |
+
### Optional per-parent Top-N optimization
|
| 58 |
+
|
| 59 |
+
- Configure `topNProbeParentThreshold(threshold)` on the nested child request before its intent/execution
|
| 60 |
+
stage. Use the field-specific relation Assist for the exact generated selector.
|
| 61 |
+
- Give the child a per-parent limit and deterministic ordering with an ID tie-breaker;
|
| 62 |
+
bound the parent query separately. A single-parent detail query is not batch Top-N.
|
| 63 |
+
- Server providers default to a window query (`threshold = 0`). A positive threshold
|
| 64 |
+
permits bounded probes only when the already-loaded parent count is at or below it;
|
| 65 |
+
above it, use the window plan. SQLite uses its internal AlwaysProbe policy by default.
|
| 66 |
+
- Measure before opting in. Do not infer a threshold from table size or execute COUNT
|
| 67 |
+
or statistics queries to choose a plan. Keep an index on foreign key + sort + ID.
|
| 68 |
+
- Inspect selected-plan, parent-count, per-parent-limit and probe-count telemetry.
|
| 69 |
+
Runtime-managed probes are not application-owned N+1 loops; neither strategy changes
|
| 70 |
+
authorization, loaded-state semantics or the required comment/purpose.
|
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/customer_order.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# TypeScript Assist — Query `Customer Order`
|
| 4 |
+
|
| 5 |
+
Use the exact generated `Q.customerOrdersWithMinimalFields()`
|
| 6 |
+
entry point. Trusted runtime and policy state comes only from `UserContext`.
|
| 7 |
+
|
| 8 |
+
```typescript
|
| 9 |
+
import { Q } from './Q';
|
| 10 |
+
import { CustomerOrder } from './models/CustomerOrder';
|
| 11 |
+
import { SmartList, UserContext } from '../teaql-ts';
|
| 12 |
+
|
| 13 |
+
export async function queryCustomerOrderById(
|
| 14 |
+
context: UserContext,
|
| 15 |
+
entityId: string,
|
| 16 |
+
): Promise<SmartList<CustomerOrder>> {
|
| 17 |
+
return Q.customerOrdersWithMinimalFields()
|
| 18 |
+
.withIdIs(entityId)
|
| 19 |
+
.orderByIdAscending()
|
| 20 |
+
.limit(20)
|
| 21 |
+
.comment('what: load the requested Customer Order row')
|
| 22 |
+
.purpose('why: serve the authorized Customer Order view')
|
| 23 |
+
.executeForList(context);
|
| 24 |
+
}
|
| 25 |
+
```
|
| 26 |
+
|
| 27 |
+
Compile and execute this source unchanged. Use only generated projection,
|
| 28 |
+
predicate, ordering, and relation-selection APIs. Missing or blank intent,
|
| 29 |
+
unknown fields, unbounded reads, and trusted-context inputs must fail. Use generated
|
| 30 |
+
relation loading rather than handwritten child-query loops; never guess a plural.
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
## Field-specific Query Assist
|
| 34 |
+
|
| 35 |
+
Use the canonical KSML field name from this list. Do not substitute a language member name, JSON name, or database column.
|
| 36 |
+
|
| 37 |
+
| KSML field | Type | Field help |
|
| 38 |
+
| --- | --- | --- |
|
| 39 |
+
| `id` | `id` | `typescript-assist-query/customer_order.id` |
|
| 40 |
+
| `platform` | `relation<platform>` | `typescript-assist-query/customer_order.platform` |
|
| 41 |
+
| `order_number` | `string` | `typescript-assist-query/customer_order.order_number` |
|
| 42 |
+
| `description` | `string` | `typescript-assist-query/customer_order.description` |
|
| 43 |
+
| `version` | `version` | `typescript-assist-query/customer_order.version` |
|
| 44 |
+
|
| 45 |
+
Generated reverse relations are derived from referencing KSML fields. Use their exact generated location for relation selection and access:
|
| 46 |
+
|
| 47 |
+
| Generated reverse relation | Child entity | Field help |
|
| 48 |
+
| --- | --- | --- |
|
| 49 |
+
| `order_item_list` | `order_item` | `typescript-assist-query/customer_order.order_item_list` |
|
| 50 |
+
| `payment_list` | `payment` | `typescript-assist-query/customer_order.payment_list` |
|
| 51 |
+
| `shipment_list` | `shipment` | `typescript-assist-query/customer_order.shipment_list` |
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
---
|
| 55 |
+
|
| 56 |
+
## TeaQL seven-language assist contract
|
| 57 |
+
|
| 58 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 59 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 60 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 61 |
+
|
| 62 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 63 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 64 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 65 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 66 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 67 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 68 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 69 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 70 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 71 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 72 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 73 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 74 |
+
- If the required operation is absent after current entity/action and required field
|
| 75 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 76 |
+
generated library as a fallback.
|
| 77 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 78 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 79 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 80 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 81 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 82 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 83 |
+
|
| 84 |
+
Capability: `query`.
|
| 85 |
+
|
| 86 |
+
- Use generated projection, relation, predicate, sort, and aggregate APIs; never
|
| 87 |
+
concatenate application SQL or silently ignore an unsupported filter.
|
| 88 |
+
- Rows, record count, facets, and aggregates must share the same active filter.
|
| 89 |
+
- Add negative tests for missing purpose/comment and forbidden dynamic fields.
|
| 90 |
+
|
| 91 |
+
### Optional per-parent Top-N optimization
|
| 92 |
+
|
| 93 |
+
- Configure `topNProbeParentThreshold(threshold)` on the nested child request before its intent/execution
|
| 94 |
+
stage. Use the field-specific relation Assist for the exact generated selector.
|
| 95 |
+
- Give the child a per-parent limit and deterministic ordering with an ID tie-breaker;
|
| 96 |
+
bound the parent query separately. A single-parent detail query is not batch Top-N.
|
| 97 |
+
- Server providers default to a window query (`threshold = 0`). A positive threshold
|
| 98 |
+
permits bounded probes only when the already-loaded parent count is at or below it;
|
| 99 |
+
above it, use the window plan. SQLite uses its internal AlwaysProbe policy by default.
|
| 100 |
+
- Measure before opting in. Do not infer a threshold from table size or execute COUNT
|
| 101 |
+
or statistics queries to choose a plan. Keep an index on foreign key + sort + ID.
|
| 102 |
+
- Inspect selected-plan, parent-count, per-parent-limit and probe-count telemetry.
|
| 103 |
+
Runtime-managed probes are not application-owned N+1 loops; neither strategy changes
|
| 104 |
+
authorization, loaded-state semantics or the required comment/purpose.
|
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/customer_order.order_item_list.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# Query Reverse-Relation Assist — `customer_order.order_item_list`
|
| 4 |
+
|
| 5 |
+
KSML entity: `customer_order`
|
| 6 |
+
Derived reverse relation: `order_item_list`
|
| 7 |
+
Child entity: `order_item`
|
| 8 |
+
|
| 9 |
+
| Capability | Generated API |
|
| 10 |
+
| --- | --- |
|
| 11 |
+
| Select | `.selectOrderItemListWith(Q.orderItemsWithMinimalFields())` |
|
| 12 |
+
| Related count | `.countOrderItemsAs(alias)` |
|
| 13 |
+
| Filtered related count | `.countOrderItemsWith(alias, childRequest)` |
|
| 14 |
+
| Read related count | `(entity as unknown as Record<string, unknown>)[alias]`; require a present numeric value |
|
| 15 |
+
|
| 16 |
+
Related counts are query projections, not modeled fields or mutation setters. Use a dedicated child request for the aggregate; do not reuse it as a row selection. An alias has no generated E accessor. Use E for modeled fields and loaded relation traversal; then narrow the returned alias from unknown. Missing is not zero. List and stream return entities carrying the alias; executeForRows returns records. Choose aliases that do not collide with model fields, relations or entity methods.
|
| 17 |
+
|
| 18 |
+
Reverse relations are model-derived and never perform an implicit database query. Select the relation explicitly before expression access. Apply query methods before the executable purpose stage, then execute with exactly one trusted context.
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
---
|
| 22 |
+
|
| 23 |
+
## TeaQL seven-language assist contract
|
| 24 |
+
|
| 25 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 26 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 27 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 28 |
+
|
| 29 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 30 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 31 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 32 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 33 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 34 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 35 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 36 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 37 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 38 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 39 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 40 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 41 |
+
- If the required operation is absent after current entity/action and required field
|
| 42 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 43 |
+
generated library as a fallback.
|
| 44 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 45 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 46 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 47 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 48 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 49 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 50 |
+
|
| 51 |
+
Capability: `query`.
|
| 52 |
+
|
| 53 |
+
- Use generated projection, relation, predicate, sort, and aggregate APIs; never
|
| 54 |
+
concatenate application SQL or silently ignore an unsupported filter.
|
| 55 |
+
- Rows, record count, facets, and aggregates must share the same active filter.
|
| 56 |
+
- Add negative tests for missing purpose/comment and forbidden dynamic fields.
|
| 57 |
+
|
| 58 |
+
### Optional per-parent Top-N optimization
|
| 59 |
+
|
| 60 |
+
- Configure `topNProbeParentThreshold(threshold)` on the nested child request before its intent/execution
|
| 61 |
+
stage. Use the field-specific relation Assist for the exact generated selector.
|
| 62 |
+
- Give the child a per-parent limit and deterministic ordering with an ID tie-breaker;
|
| 63 |
+
bound the parent query separately. A single-parent detail query is not batch Top-N.
|
| 64 |
+
- Server providers default to a window query (`threshold = 0`). A positive threshold
|
| 65 |
+
permits bounded probes only when the already-loaded parent count is at or below it;
|
| 66 |
+
above it, use the window plan. SQLite uses its internal AlwaysProbe policy by default.
|
| 67 |
+
- Measure before opting in. Do not infer a threshold from table size or execute COUNT
|
| 68 |
+
or statistics queries to choose a plan. Keep an index on foreign key + sort + ID.
|
| 69 |
+
- Inspect selected-plan, parent-count, per-parent-limit and probe-count telemetry.
|
| 70 |
+
Runtime-managed probes are not application-owned N+1 loops; neither strategy changes
|
| 71 |
+
authorization, loaded-state semantics or the required comment/purpose.
|
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/customer_order.payment_list.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# Query Reverse-Relation Assist — `customer_order.payment_list`
|
| 4 |
+
|
| 5 |
+
KSML entity: `customer_order`
|
| 6 |
+
Derived reverse relation: `payment_list`
|
| 7 |
+
Child entity: `payment`
|
| 8 |
+
|
| 9 |
+
| Capability | Generated API |
|
| 10 |
+
| --- | --- |
|
| 11 |
+
| Select | `.selectPaymentListWith(Q.paymentsWithMinimalFields())` |
|
| 12 |
+
| Related count | `.countPaymentsAs(alias)` |
|
| 13 |
+
| Filtered related count | `.countPaymentsWith(alias, childRequest)` |
|
| 14 |
+
| Read related count | `(entity as unknown as Record<string, unknown>)[alias]`; require a present numeric value |
|
| 15 |
+
|
| 16 |
+
Related counts are query projections, not modeled fields or mutation setters. Use a dedicated child request for the aggregate; do not reuse it as a row selection. An alias has no generated E accessor. Use E for modeled fields and loaded relation traversal; then narrow the returned alias from unknown. Missing is not zero. List and stream return entities carrying the alias; executeForRows returns records. Choose aliases that do not collide with model fields, relations or entity methods.
|
| 17 |
+
|
| 18 |
+
Reverse relations are model-derived and never perform an implicit database query. Select the relation explicitly before expression access. Apply query methods before the executable purpose stage, then execute with exactly one trusted context.
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
---
|
| 22 |
+
|
| 23 |
+
## TeaQL seven-language assist contract
|
| 24 |
+
|
| 25 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 26 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 27 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 28 |
+
|
| 29 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 30 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 31 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 32 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 33 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 34 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 35 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 36 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 37 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 38 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 39 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 40 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 41 |
+
- If the required operation is absent after current entity/action and required field
|
| 42 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 43 |
+
generated library as a fallback.
|
| 44 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 45 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 46 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 47 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 48 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 49 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 50 |
+
|
| 51 |
+
Capability: `query`.
|
| 52 |
+
|
| 53 |
+
- Use generated projection, relation, predicate, sort, and aggregate APIs; never
|
| 54 |
+
concatenate application SQL or silently ignore an unsupported filter.
|
| 55 |
+
- Rows, record count, facets, and aggregates must share the same active filter.
|
| 56 |
+
- Add negative tests for missing purpose/comment and forbidden dynamic fields.
|
| 57 |
+
|
| 58 |
+
### Optional per-parent Top-N optimization
|
| 59 |
+
|
| 60 |
+
- Configure `topNProbeParentThreshold(threshold)` on the nested child request before its intent/execution
|
| 61 |
+
stage. Use the field-specific relation Assist for the exact generated selector.
|
| 62 |
+
- Give the child a per-parent limit and deterministic ordering with an ID tie-breaker;
|
| 63 |
+
bound the parent query separately. A single-parent detail query is not batch Top-N.
|
| 64 |
+
- Server providers default to a window query (`threshold = 0`). A positive threshold
|
| 65 |
+
permits bounded probes only when the already-loaded parent count is at or below it;
|
| 66 |
+
above it, use the window plan. SQLite uses its internal AlwaysProbe policy by default.
|
| 67 |
+
- Measure before opting in. Do not infer a threshold from table size or execute COUNT
|
| 68 |
+
or statistics queries to choose a plan. Keep an index on foreign key + sort + ID.
|
| 69 |
+
- Inspect selected-plan, parent-count, per-parent-limit and probe-count telemetry.
|
| 70 |
+
Runtime-managed probes are not application-owned N+1 loops; neither strategy changes
|
| 71 |
+
authorization, loaded-state semantics or the required comment/purpose.
|
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/customer_order.platform.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# TypeScript Query Field Assist — `customer_order.platform`
|
| 4 |
+
|
| 5 |
+
KSML entity: `Customer Order`
|
| 6 |
+
KSML field: `Platform`
|
| 7 |
+
Type: `Platform`
|
| 8 |
+
|
| 9 |
+
| Capability | Generated API |
|
| 10 |
+
| --- | --- |
|
| 11 |
+
| Select | `selectPlatformWith(request)` |
|
| 12 |
+
| Filter identity | `filterByPlatform(id)`, `filterByPlatformIn(...ids)` |
|
| 13 |
+
| Filter nested request | `withPlatformMatching(request)`, `withoutPlatformMatching(request)` |
|
| 14 |
+
| Group | `groupByPlatform()`, `groupByPlatformAs(alias)` |
|
| 15 |
+
| Facet | `facetByPlatformAs(name, request, includeAllFacets)` |
|
| 16 |
+
Execution requires `comment(...)`, `purpose(...)`, and exactly one `context`.
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
---
|
| 20 |
+
|
| 21 |
+
## TeaQL seven-language assist contract
|
| 22 |
+
|
| 23 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 24 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 25 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 26 |
+
|
| 27 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 28 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 29 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 30 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 31 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 32 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 33 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 34 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 35 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 36 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 37 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 38 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 39 |
+
- If the required operation is absent after current entity/action and required field
|
| 40 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 41 |
+
generated library as a fallback.
|
| 42 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 43 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 44 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 45 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 46 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 47 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 48 |
+
|
| 49 |
+
Capability: `query`.
|
| 50 |
+
|
| 51 |
+
- Use generated projection, relation, predicate, sort, and aggregate APIs; never
|
| 52 |
+
concatenate application SQL or silently ignore an unsupported filter.
|
| 53 |
+
- Rows, record count, facets, and aggregates must share the same active filter.
|
| 54 |
+
- Add negative tests for missing purpose/comment and forbidden dynamic fields.
|
| 55 |
+
|
| 56 |
+
### Optional per-parent Top-N optimization
|
| 57 |
+
|
| 58 |
+
- Configure `topNProbeParentThreshold(threshold)` on the nested child request before its intent/execution
|
| 59 |
+
stage. Use the field-specific relation Assist for the exact generated selector.
|
| 60 |
+
- Give the child a per-parent limit and deterministic ordering with an ID tie-breaker;
|
| 61 |
+
bound the parent query separately. A single-parent detail query is not batch Top-N.
|
| 62 |
+
- Server providers default to a window query (`threshold = 0`). A positive threshold
|
| 63 |
+
permits bounded probes only when the already-loaded parent count is at or below it;
|
| 64 |
+
above it, use the window plan. SQLite uses its internal AlwaysProbe policy by default.
|
| 65 |
+
- Measure before opting in. Do not infer a threshold from table size or execute COUNT
|
| 66 |
+
or statistics queries to choose a plan. Keep an index on foreign key + sort + ID.
|
| 67 |
+
- Inspect selected-plan, parent-count, per-parent-limit and probe-count telemetry.
|
| 68 |
+
Runtime-managed probes are not application-owned N+1 loops; neither strategy changes
|
| 69 |
+
authorization, loaded-state semantics or the required comment/purpose.
|
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/customer_order.shipment_list.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# Query Reverse-Relation Assist — `customer_order.shipment_list`
|
| 4 |
+
|
| 5 |
+
KSML entity: `customer_order`
|
| 6 |
+
Derived reverse relation: `shipment_list`
|
| 7 |
+
Child entity: `shipment`
|
| 8 |
+
|
| 9 |
+
| Capability | Generated API |
|
| 10 |
+
| --- | --- |
|
| 11 |
+
| Select | `.selectShipmentListWith(Q.shipmentsWithMinimalFields())` |
|
| 12 |
+
| Related count | `.countShipmentsAs(alias)` |
|
| 13 |
+
| Filtered related count | `.countShipmentsWith(alias, childRequest)` |
|
| 14 |
+
| Read related count | `(entity as unknown as Record<string, unknown>)[alias]`; require a present numeric value |
|
| 15 |
+
|
| 16 |
+
Related counts are query projections, not modeled fields or mutation setters. Use a dedicated child request for the aggregate; do not reuse it as a row selection. An alias has no generated E accessor. Use E for modeled fields and loaded relation traversal; then narrow the returned alias from unknown. Missing is not zero. List and stream return entities carrying the alias; executeForRows returns records. Choose aliases that do not collide with model fields, relations or entity methods.
|
| 17 |
+
|
| 18 |
+
Reverse relations are model-derived and never perform an implicit database query. Select the relation explicitly before expression access. Apply query methods before the executable purpose stage, then execute with exactly one trusted context.
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
---
|
| 22 |
+
|
| 23 |
+
## TeaQL seven-language assist contract
|
| 24 |
+
|
| 25 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 26 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 27 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 28 |
+
|
| 29 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 30 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 31 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 32 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 33 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 34 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 35 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 36 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 37 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 38 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 39 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 40 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 41 |
+
- If the required operation is absent after current entity/action and required field
|
| 42 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 43 |
+
generated library as a fallback.
|
| 44 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 45 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 46 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 47 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 48 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 49 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 50 |
+
|
| 51 |
+
Capability: `query`.
|
| 52 |
+
|
| 53 |
+
- Use generated projection, relation, predicate, sort, and aggregate APIs; never
|
| 54 |
+
concatenate application SQL or silently ignore an unsupported filter.
|
| 55 |
+
- Rows, record count, facets, and aggregates must share the same active filter.
|
| 56 |
+
- Add negative tests for missing purpose/comment and forbidden dynamic fields.
|
| 57 |
+
|
| 58 |
+
### Optional per-parent Top-N optimization
|
| 59 |
+
|
| 60 |
+
- Configure `topNProbeParentThreshold(threshold)` on the nested child request before its intent/execution
|
| 61 |
+
stage. Use the field-specific relation Assist for the exact generated selector.
|
| 62 |
+
- Give the child a per-parent limit and deterministic ordering with an ID tie-breaker;
|
| 63 |
+
bound the parent query separately. A single-parent detail query is not batch Top-N.
|
| 64 |
+
- Server providers default to a window query (`threshold = 0`). A positive threshold
|
| 65 |
+
permits bounded probes only when the already-loaded parent count is at or below it;
|
| 66 |
+
above it, use the window plan. SQLite uses its internal AlwaysProbe policy by default.
|
| 67 |
+
- Measure before opting in. Do not infer a threshold from table size or execute COUNT
|
| 68 |
+
or statistics queries to choose a plan. Keep an index on foreign key + sort + ID.
|
| 69 |
+
- Inspect selected-plan, parent-count, per-parent-limit and probe-count telemetry.
|
| 70 |
+
Runtime-managed probes are not application-owned N+1 loops; neither strategy changes
|
| 71 |
+
authorization, loaded-state semantics or the required comment/purpose.
|
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/order_item.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# TypeScript Assist — Query `Order Item`
|
| 4 |
+
|
| 5 |
+
Use the exact generated `Q.orderItemsWithMinimalFields()`
|
| 6 |
+
entry point. Trusted runtime and policy state comes only from `UserContext`.
|
| 7 |
+
|
| 8 |
+
```typescript
|
| 9 |
+
import { Q } from './Q';
|
| 10 |
+
import { OrderItem } from './models/OrderItem';
|
| 11 |
+
import { SmartList, UserContext } from '../teaql-ts';
|
| 12 |
+
|
| 13 |
+
export async function queryOrderItemById(
|
| 14 |
+
context: UserContext,
|
| 15 |
+
entityId: string,
|
| 16 |
+
): Promise<SmartList<OrderItem>> {
|
| 17 |
+
return Q.orderItemsWithMinimalFields()
|
| 18 |
+
.withIdIs(entityId)
|
| 19 |
+
.orderByIdAscending()
|
| 20 |
+
.limit(20)
|
| 21 |
+
.comment('what: load the requested Order Item row')
|
| 22 |
+
.purpose('why: serve the authorized Order Item view')
|
| 23 |
+
.executeForList(context);
|
| 24 |
+
}
|
| 25 |
+
```
|
| 26 |
+
|
| 27 |
+
Compile and execute this source unchanged. Use only generated projection,
|
| 28 |
+
predicate, ordering, and relation-selection APIs. Missing or blank intent,
|
| 29 |
+
unknown fields, unbounded reads, and trusted-context inputs must fail. Use generated
|
| 30 |
+
relation loading rather than handwritten child-query loops; never guess a plural.
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
## Field-specific Query Assist
|
| 34 |
+
|
| 35 |
+
Use the canonical KSML field name from this list. Do not substitute a language member name, JSON name, or database column.
|
| 36 |
+
|
| 37 |
+
| KSML field | Type | Field help |
|
| 38 |
+
| --- | --- | --- |
|
| 39 |
+
| `id` | `id` | `typescript-assist-query/order_item.id` |
|
| 40 |
+
| `customer_order` | `relation<customer_order>` | `typescript-assist-query/order_item.customer_order` |
|
| 41 |
+
| `name` | `string` | `typescript-assist-query/order_item.name` |
|
| 42 |
+
| `version` | `version` | `typescript-assist-query/order_item.version` |
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
---
|
| 46 |
+
|
| 47 |
+
## TeaQL seven-language assist contract
|
| 48 |
+
|
| 49 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 50 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 51 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 52 |
+
|
| 53 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 54 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 55 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 56 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 57 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 58 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 59 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 60 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 61 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 62 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 63 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 64 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 65 |
+
- If the required operation is absent after current entity/action and required field
|
| 66 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 67 |
+
generated library as a fallback.
|
| 68 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 69 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 70 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 71 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 72 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 73 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 74 |
+
|
| 75 |
+
Capability: `query`.
|
| 76 |
+
|
| 77 |
+
- Use generated projection, relation, predicate, sort, and aggregate APIs; never
|
| 78 |
+
concatenate application SQL or silently ignore an unsupported filter.
|
| 79 |
+
- Rows, record count, facets, and aggregates must share the same active filter.
|
| 80 |
+
- Add negative tests for missing purpose/comment and forbidden dynamic fields.
|
| 81 |
+
|
| 82 |
+
### Optional per-parent Top-N optimization
|
| 83 |
+
|
| 84 |
+
- Configure `topNProbeParentThreshold(threshold)` on the nested child request before its intent/execution
|
| 85 |
+
stage. Use the field-specific relation Assist for the exact generated selector.
|
| 86 |
+
- Give the child a per-parent limit and deterministic ordering with an ID tie-breaker;
|
| 87 |
+
bound the parent query separately. A single-parent detail query is not batch Top-N.
|
| 88 |
+
- Server providers default to a window query (`threshold = 0`). A positive threshold
|
| 89 |
+
permits bounded probes only when the already-loaded parent count is at or below it;
|
| 90 |
+
above it, use the window plan. SQLite uses its internal AlwaysProbe policy by default.
|
| 91 |
+
- Measure before opting in. Do not infer a threshold from table size or execute COUNT
|
| 92 |
+
or statistics queries to choose a plan. Keep an index on foreign key + sort + ID.
|
| 93 |
+
- Inspect selected-plan, parent-count, per-parent-limit and probe-count telemetry.
|
| 94 |
+
Runtime-managed probes are not application-owned N+1 loops; neither strategy changes
|
| 95 |
+
authorization, loaded-state semantics or the required comment/purpose.
|
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/order_item.name.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# TypeScript Query Field Assist — `order_item.name`
|
| 4 |
+
|
| 5 |
+
KSML entity: `Order Item`
|
| 6 |
+
KSML field: `name`
|
| 7 |
+
Type: `string`
|
| 8 |
+
|
| 9 |
+
| Capability | Generated API |
|
| 10 |
+
| --- | --- |
|
| 11 |
+
| Select | `selectName()` |
|
| 12 |
+
| Equality/set | `withNameIs(value)`, `withNameIsNot(value)`, `withNameIn(...values)`, `withNameNotIn(...values)` |
|
| 13 |
+
| Comparison | `withNameGreaterThan(value)`, `withNameGreaterThanOrEqualTo(value)`, `withNameLessThan(value)`, `withNameLessThanOrEqualTo(value)`, `withNameBetween(lower, upper)` |
|
| 14 |
+
| Null state | `withNameIsKnown()`, `withNameIsUnknown()` |
|
| 15 |
+
| String | `withNameContaining(value)`, `withNameNotContaining(value)`, `withNameStartingWith(value)`, `withNameEndingWith(value)`, `withNameSoundingLike(value)` |
|
| 16 |
+
| Order | `orderByNameAscending()`, `orderByNameDescending()` |
|
| 17 |
+
| Group | `groupByName()`, `groupByNameAs(alias)` |
|
| 18 |
+
Execution requires `comment(...)`, `purpose(...)`, and exactly one `context`.
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
---
|
| 22 |
+
|
| 23 |
+
## TeaQL seven-language assist contract
|
| 24 |
+
|
| 25 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 26 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 27 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 28 |
+
|
| 29 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 30 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 31 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 32 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 33 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 34 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 35 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 36 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 37 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 38 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 39 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 40 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 41 |
+
- If the required operation is absent after current entity/action and required field
|
| 42 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 43 |
+
generated library as a fallback.
|
| 44 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 45 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 46 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 47 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 48 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 49 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 50 |
+
|
| 51 |
+
Capability: `query`.
|
| 52 |
+
|
| 53 |
+
- Use generated projection, relation, predicate, sort, and aggregate APIs; never
|
| 54 |
+
concatenate application SQL or silently ignore an unsupported filter.
|
| 55 |
+
- Rows, record count, facets, and aggregates must share the same active filter.
|
| 56 |
+
- Add negative tests for missing purpose/comment and forbidden dynamic fields.
|
| 57 |
+
|
| 58 |
+
### Optional per-parent Top-N optimization
|
| 59 |
+
|
| 60 |
+
- Configure `topNProbeParentThreshold(threshold)` on the nested child request before its intent/execution
|
| 61 |
+
stage. Use the field-specific relation Assist for the exact generated selector.
|
| 62 |
+
- Give the child a per-parent limit and deterministic ordering with an ID tie-breaker;
|
| 63 |
+
bound the parent query separately. A single-parent detail query is not batch Top-N.
|
| 64 |
+
- Server providers default to a window query (`threshold = 0`). A positive threshold
|
| 65 |
+
permits bounded probes only when the already-loaded parent count is at or below it;
|
| 66 |
+
above it, use the window plan. SQLite uses its internal AlwaysProbe policy by default.
|
| 67 |
+
- Measure before opting in. Do not infer a threshold from table size or execute COUNT
|
| 68 |
+
or statistics queries to choose a plan. Keep an index on foreign key + sort + ID.
|
| 69 |
+
- Inspect selected-plan, parent-count, per-parent-limit and probe-count telemetry.
|
| 70 |
+
Runtime-managed probes are not application-owned N+1 loops; neither strategy changes
|
| 71 |
+
authorization, loaded-state semantics or the required comment/purpose.
|
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/payment.customer_order.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# TypeScript Query Field Assist — `payment.customer_order`
|
| 4 |
+
|
| 5 |
+
KSML entity: `Payment`
|
| 6 |
+
KSML field: `Customer Order`
|
| 7 |
+
Type: `Customer Order`
|
| 8 |
+
|
| 9 |
+
| Capability | Generated API |
|
| 10 |
+
| --- | --- |
|
| 11 |
+
| Select | `selectCustomerOrderWith(request)` |
|
| 12 |
+
| Filter identity | `filterByCustomerOrder(id)`, `filterByCustomerOrderIn(...ids)` |
|
| 13 |
+
| Filter nested request | `withCustomerOrderMatching(request)`, `withoutCustomerOrderMatching(request)` |
|
| 14 |
+
| Group | `groupByCustomerOrder()`, `groupByCustomerOrderAs(alias)` |
|
| 15 |
+
| Facet | `facetByCustomerOrderAs(name, request, includeAllFacets)` |
|
| 16 |
+
Execution requires `comment(...)`, `purpose(...)`, and exactly one `context`.
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
---
|
| 20 |
+
|
| 21 |
+
## TeaQL seven-language assist contract
|
| 22 |
+
|
| 23 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 24 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 25 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 26 |
+
|
| 27 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 28 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 29 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 30 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 31 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 32 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 33 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 34 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 35 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 36 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 37 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 38 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 39 |
+
- If the required operation is absent after current entity/action and required field
|
| 40 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 41 |
+
generated library as a fallback.
|
| 42 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 43 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 44 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 45 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 46 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 47 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 48 |
+
|
| 49 |
+
Capability: `query`.
|
| 50 |
+
|
| 51 |
+
- Use generated projection, relation, predicate, sort, and aggregate APIs; never
|
| 52 |
+
concatenate application SQL or silently ignore an unsupported filter.
|
| 53 |
+
- Rows, record count, facets, and aggregates must share the same active filter.
|
| 54 |
+
- Add negative tests for missing purpose/comment and forbidden dynamic fields.
|
| 55 |
+
|
| 56 |
+
### Optional per-parent Top-N optimization
|
| 57 |
+
|
| 58 |
+
- Configure `topNProbeParentThreshold(threshold)` on the nested child request before its intent/execution
|
| 59 |
+
stage. Use the field-specific relation Assist for the exact generated selector.
|
| 60 |
+
- Give the child a per-parent limit and deterministic ordering with an ID tie-breaker;
|
| 61 |
+
bound the parent query separately. A single-parent detail query is not batch Top-N.
|
| 62 |
+
- Server providers default to a window query (`threshold = 0`). A positive threshold
|
| 63 |
+
permits bounded probes only when the already-loaded parent count is at or below it;
|
| 64 |
+
above it, use the window plan. SQLite uses its internal AlwaysProbe policy by default.
|
| 65 |
+
- Measure before opting in. Do not infer a threshold from table size or execute COUNT
|
| 66 |
+
or statistics queries to choose a plan. Keep an index on foreign key + sort + ID.
|
| 67 |
+
- Inspect selected-plan, parent-count, per-parent-limit and probe-count telemetry.
|
| 68 |
+
Runtime-managed probes are not application-owned N+1 loops; neither strategy changes
|
| 69 |
+
authorization, loaded-state semantics or the required comment/purpose.
|
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/payment.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# TypeScript Assist — Query `Payment`
|
| 4 |
+
|
| 5 |
+
Use the exact generated `Q.paymentsWithMinimalFields()`
|
| 6 |
+
entry point. Trusted runtime and policy state comes only from `UserContext`.
|
| 7 |
+
|
| 8 |
+
```typescript
|
| 9 |
+
import { Q } from './Q';
|
| 10 |
+
import { Payment } from './models/Payment';
|
| 11 |
+
import { SmartList, UserContext } from '../teaql-ts';
|
| 12 |
+
|
| 13 |
+
export async function queryPaymentById(
|
| 14 |
+
context: UserContext,
|
| 15 |
+
entityId: string,
|
| 16 |
+
): Promise<SmartList<Payment>> {
|
| 17 |
+
return Q.paymentsWithMinimalFields()
|
| 18 |
+
.withIdIs(entityId)
|
| 19 |
+
.orderByIdAscending()
|
| 20 |
+
.limit(20)
|
| 21 |
+
.comment('what: load the requested Payment row')
|
| 22 |
+
.purpose('why: serve the authorized Payment view')
|
| 23 |
+
.executeForList(context);
|
| 24 |
+
}
|
| 25 |
+
```
|
| 26 |
+
|
| 27 |
+
Compile and execute this source unchanged. Use only generated projection,
|
| 28 |
+
predicate, ordering, and relation-selection APIs. Missing or blank intent,
|
| 29 |
+
unknown fields, unbounded reads, and trusted-context inputs must fail. Use generated
|
| 30 |
+
relation loading rather than handwritten child-query loops; never guess a plural.
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
## Field-specific Query Assist
|
| 34 |
+
|
| 35 |
+
Use the canonical KSML field name from this list. Do not substitute a language member name, JSON name, or database column.
|
| 36 |
+
|
| 37 |
+
| KSML field | Type | Field help |
|
| 38 |
+
| --- | --- | --- |
|
| 39 |
+
| `id` | `id` | `typescript-assist-query/payment.id` |
|
| 40 |
+
| `customer_order` | `relation<customer_order>` | `typescript-assist-query/payment.customer_order` |
|
| 41 |
+
| `reference_code` | `string` | `typescript-assist-query/payment.reference_code` |
|
| 42 |
+
| `version` | `version` | `typescript-assist-query/payment.version` |
|
| 43 |
+
|
| 44 |
+
Generated reverse relations are derived from referencing KSML fields. Use their exact generated location for relation selection and access:
|
| 45 |
+
|
| 46 |
+
| Generated reverse relation | Child entity | Field help |
|
| 47 |
+
| --- | --- | --- |
|
| 48 |
+
| `payment_attempt_list` | `payment_attempt` | `typescript-assist-query/payment.payment_attempt_list` |
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
---
|
| 52 |
+
|
| 53 |
+
## TeaQL seven-language assist contract
|
| 54 |
+
|
| 55 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 56 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 57 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 58 |
+
|
| 59 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 60 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 61 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 62 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 63 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 64 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 65 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 66 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 67 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 68 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 69 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 70 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 71 |
+
- If the required operation is absent after current entity/action and required field
|
| 72 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 73 |
+
generated library as a fallback.
|
| 74 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 75 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 76 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 77 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 78 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 79 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 80 |
+
|
| 81 |
+
Capability: `query`.
|
| 82 |
+
|
| 83 |
+
- Use generated projection, relation, predicate, sort, and aggregate APIs; never
|
| 84 |
+
concatenate application SQL or silently ignore an unsupported filter.
|
| 85 |
+
- Rows, record count, facets, and aggregates must share the same active filter.
|
| 86 |
+
- Add negative tests for missing purpose/comment and forbidden dynamic fields.
|
| 87 |
+
|
| 88 |
+
### Optional per-parent Top-N optimization
|
| 89 |
+
|
| 90 |
+
- Configure `topNProbeParentThreshold(threshold)` on the nested child request before its intent/execution
|
| 91 |
+
stage. Use the field-specific relation Assist for the exact generated selector.
|
| 92 |
+
- Give the child a per-parent limit and deterministic ordering with an ID tie-breaker;
|
| 93 |
+
bound the parent query separately. A single-parent detail query is not batch Top-N.
|
| 94 |
+
- Server providers default to a window query (`threshold = 0`). A positive threshold
|
| 95 |
+
permits bounded probes only when the already-loaded parent count is at or below it;
|
| 96 |
+
above it, use the window plan. SQLite uses its internal AlwaysProbe policy by default.
|
| 97 |
+
- Measure before opting in. Do not infer a threshold from table size or execute COUNT
|
| 98 |
+
or statistics queries to choose a plan. Keep an index on foreign key + sort + ID.
|
| 99 |
+
- Inspect selected-plan, parent-count, per-parent-limit and probe-count telemetry.
|
| 100 |
+
Runtime-managed probes are not application-owned N+1 loops; neither strategy changes
|
| 101 |
+
authorization, loaded-state semantics or the required comment/purpose.
|
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/payment.payment_attempt_list.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# Query Reverse-Relation Assist — `payment.payment_attempt_list`
|
| 4 |
+
|
| 5 |
+
KSML entity: `payment`
|
| 6 |
+
Derived reverse relation: `payment_attempt_list`
|
| 7 |
+
Child entity: `payment_attempt`
|
| 8 |
+
|
| 9 |
+
| Capability | Generated API |
|
| 10 |
+
| --- | --- |
|
| 11 |
+
| Select | `.selectPaymentAttemptListWith(Q.paymentAttemptsWithMinimalFields())` |
|
| 12 |
+
| Related count | `.countPaymentAttemptsAs(alias)` |
|
| 13 |
+
| Filtered related count | `.countPaymentAttemptsWith(alias, childRequest)` |
|
| 14 |
+
| Read related count | `(entity as unknown as Record<string, unknown>)[alias]`; require a present numeric value |
|
| 15 |
+
|
| 16 |
+
Related counts are query projections, not modeled fields or mutation setters. Use a dedicated child request for the aggregate; do not reuse it as a row selection. An alias has no generated E accessor. Use E for modeled fields and loaded relation traversal; then narrow the returned alias from unknown. Missing is not zero. List and stream return entities carrying the alias; executeForRows returns records. Choose aliases that do not collide with model fields, relations or entity methods.
|
| 17 |
+
|
| 18 |
+
Reverse relations are model-derived and never perform an implicit database query. Select the relation explicitly before expression access. Apply query methods before the executable purpose stage, then execute with exactly one trusted context.
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
---
|
| 22 |
+
|
| 23 |
+
## TeaQL seven-language assist contract
|
| 24 |
+
|
| 25 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 26 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 27 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 28 |
+
|
| 29 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 30 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 31 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 32 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 33 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 34 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 35 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 36 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 37 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 38 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 39 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 40 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 41 |
+
- If the required operation is absent after current entity/action and required field
|
| 42 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 43 |
+
generated library as a fallback.
|
| 44 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 45 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 46 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 47 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 48 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 49 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 50 |
+
|
| 51 |
+
Capability: `query`.
|
| 52 |
+
|
| 53 |
+
- Use generated projection, relation, predicate, sort, and aggregate APIs; never
|
| 54 |
+
concatenate application SQL or silently ignore an unsupported filter.
|
| 55 |
+
- Rows, record count, facets, and aggregates must share the same active filter.
|
| 56 |
+
- Add negative tests for missing purpose/comment and forbidden dynamic fields.
|
| 57 |
+
|
| 58 |
+
### Optional per-parent Top-N optimization
|
| 59 |
+
|
| 60 |
+
- Configure `topNProbeParentThreshold(threshold)` on the nested child request before its intent/execution
|
| 61 |
+
stage. Use the field-specific relation Assist for the exact generated selector.
|
| 62 |
+
- Give the child a per-parent limit and deterministic ordering with an ID tie-breaker;
|
| 63 |
+
bound the parent query separately. A single-parent detail query is not batch Top-N.
|
| 64 |
+
- Server providers default to a window query (`threshold = 0`). A positive threshold
|
| 65 |
+
permits bounded probes only when the already-loaded parent count is at or below it;
|
| 66 |
+
above it, use the window plan. SQLite uses its internal AlwaysProbe policy by default.
|
| 67 |
+
- Measure before opting in. Do not infer a threshold from table size or execute COUNT
|
| 68 |
+
or statistics queries to choose a plan. Keep an index on foreign key + sort + ID.
|
| 69 |
+
- Inspect selected-plan, parent-count, per-parent-limit and probe-count telemetry.
|
| 70 |
+
Runtime-managed probes are not application-owned N+1 loops; neither strategy changes
|
| 71 |
+
authorization, loaded-state semantics or the required comment/purpose.
|
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/payment.reference_code.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# TypeScript Query Field Assist — `payment.reference_code`
|
| 4 |
+
|
| 5 |
+
KSML entity: `Payment`
|
| 6 |
+
KSML field: `reference_code`
|
| 7 |
+
Type: `string`
|
| 8 |
+
|
| 9 |
+
| Capability | Generated API |
|
| 10 |
+
| --- | --- |
|
| 11 |
+
| Select | `selectReferenceCode()` |
|
| 12 |
+
| Equality/set | `withReferenceCodeIs(value)`, `withReferenceCodeIsNot(value)`, `withReferenceCodeIn(...values)`, `withReferenceCodeNotIn(...values)` |
|
| 13 |
+
| Comparison | `withReferenceCodeGreaterThan(value)`, `withReferenceCodeGreaterThanOrEqualTo(value)`, `withReferenceCodeLessThan(value)`, `withReferenceCodeLessThanOrEqualTo(value)`, `withReferenceCodeBetween(lower, upper)` |
|
| 14 |
+
| Null state | `withReferenceCodeIsKnown()`, `withReferenceCodeIsUnknown()` |
|
| 15 |
+
| String | `withReferenceCodeContaining(value)`, `withReferenceCodeNotContaining(value)`, `withReferenceCodeStartingWith(value)`, `withReferenceCodeEndingWith(value)`, `withReferenceCodeSoundingLike(value)` |
|
| 16 |
+
| Order | `orderByReferenceCodeAscending()`, `orderByReferenceCodeDescending()` |
|
| 17 |
+
| Group | `groupByReferenceCode()`, `groupByReferenceCodeAs(alias)` |
|
| 18 |
+
Execution requires `comment(...)`, `purpose(...)`, and exactly one `context`.
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
---
|
| 22 |
+
|
| 23 |
+
## TeaQL seven-language assist contract
|
| 24 |
+
|
| 25 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 26 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 27 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 28 |
+
|
| 29 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 30 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 31 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 32 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 33 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 34 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 35 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 36 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 37 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 38 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 39 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 40 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 41 |
+
- If the required operation is absent after current entity/action and required field
|
| 42 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 43 |
+
generated library as a fallback.
|
| 44 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 45 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 46 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 47 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 48 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 49 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 50 |
+
|
| 51 |
+
Capability: `query`.
|
| 52 |
+
|
| 53 |
+
- Use generated projection, relation, predicate, sort, and aggregate APIs; never
|
| 54 |
+
concatenate application SQL or silently ignore an unsupported filter.
|
| 55 |
+
- Rows, record count, facets, and aggregates must share the same active filter.
|
| 56 |
+
- Add negative tests for missing purpose/comment and forbidden dynamic fields.
|
| 57 |
+
|
| 58 |
+
### Optional per-parent Top-N optimization
|
| 59 |
+
|
| 60 |
+
- Configure `topNProbeParentThreshold(threshold)` on the nested child request before its intent/execution
|
| 61 |
+
stage. Use the field-specific relation Assist for the exact generated selector.
|
| 62 |
+
- Give the child a per-parent limit and deterministic ordering with an ID tie-breaker;
|
| 63 |
+
bound the parent query separately. A single-parent detail query is not batch Top-N.
|
| 64 |
+
- Server providers default to a window query (`threshold = 0`). A positive threshold
|
| 65 |
+
permits bounded probes only when the already-loaded parent count is at or below it;
|
| 66 |
+
above it, use the window plan. SQLite uses its internal AlwaysProbe policy by default.
|
| 67 |
+
- Measure before opting in. Do not infer a threshold from table size or execute COUNT
|
| 68 |
+
or statistics queries to choose a plan. Keep an index on foreign key + sort + ID.
|
| 69 |
+
- Inspect selected-plan, parent-count, per-parent-limit and probe-count telemetry.
|
| 70 |
+
Runtime-managed probes are not application-owned N+1 loops; neither strategy changes
|
| 71 |
+
authorization, loaded-state semantics or the required comment/purpose.
|
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/payment_attempt.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# TypeScript Assist — Query `Payment Attempt`
|
| 4 |
+
|
| 5 |
+
Use the exact generated `Q.paymentAttemptsWithMinimalFields()`
|
| 6 |
+
entry point. Trusted runtime and policy state comes only from `UserContext`.
|
| 7 |
+
|
| 8 |
+
```typescript
|
| 9 |
+
import { Q } from './Q';
|
| 10 |
+
import { PaymentAttempt } from './models/PaymentAttempt';
|
| 11 |
+
import { SmartList, UserContext } from '../teaql-ts';
|
| 12 |
+
|
| 13 |
+
export async function queryPaymentAttemptById(
|
| 14 |
+
context: UserContext,
|
| 15 |
+
entityId: string,
|
| 16 |
+
): Promise<SmartList<PaymentAttempt>> {
|
| 17 |
+
return Q.paymentAttemptsWithMinimalFields()
|
| 18 |
+
.withIdIs(entityId)
|
| 19 |
+
.orderByIdAscending()
|
| 20 |
+
.limit(20)
|
| 21 |
+
.comment('what: load the requested Payment Attempt row')
|
| 22 |
+
.purpose('why: serve the authorized Payment Attempt view')
|
| 23 |
+
.executeForList(context);
|
| 24 |
+
}
|
| 25 |
+
```
|
| 26 |
+
|
| 27 |
+
Compile and execute this source unchanged. Use only generated projection,
|
| 28 |
+
predicate, ordering, and relation-selection APIs. Missing or blank intent,
|
| 29 |
+
unknown fields, unbounded reads, and trusted-context inputs must fail. Use generated
|
| 30 |
+
relation loading rather than handwritten child-query loops; never guess a plural.
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
## Field-specific Query Assist
|
| 34 |
+
|
| 35 |
+
Use the canonical KSML field name from this list. Do not substitute a language member name, JSON name, or database column.
|
| 36 |
+
|
| 37 |
+
| KSML field | Type | Field help |
|
| 38 |
+
| --- | --- | --- |
|
| 39 |
+
| `id` | `id` | `typescript-assist-query/payment_attempt.id` |
|
| 40 |
+
| `payment` | `relation<payment>` | `typescript-assist-query/payment_attempt.payment` |
|
| 41 |
+
| `reference_code` | `string` | `typescript-assist-query/payment_attempt.reference_code` |
|
| 42 |
+
| `version` | `version` | `typescript-assist-query/payment_attempt.version` |
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
---
|
| 46 |
+
|
| 47 |
+
## TeaQL seven-language assist contract
|
| 48 |
+
|
| 49 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 50 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 51 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 52 |
+
|
| 53 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 54 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 55 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 56 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 57 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 58 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 59 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 60 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 61 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 62 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 63 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 64 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 65 |
+
- If the required operation is absent after current entity/action and required field
|
| 66 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 67 |
+
generated library as a fallback.
|
| 68 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 69 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 70 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 71 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 72 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 73 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 74 |
+
|
| 75 |
+
Capability: `query`.
|
| 76 |
+
|
| 77 |
+
- Use generated projection, relation, predicate, sort, and aggregate APIs; never
|
| 78 |
+
concatenate application SQL or silently ignore an unsupported filter.
|
| 79 |
+
- Rows, record count, facets, and aggregates must share the same active filter.
|
| 80 |
+
- Add negative tests for missing purpose/comment and forbidden dynamic fields.
|
| 81 |
+
|
| 82 |
+
### Optional per-parent Top-N optimization
|
| 83 |
+
|
| 84 |
+
- Configure `topNProbeParentThreshold(threshold)` on the nested child request before its intent/execution
|
| 85 |
+
stage. Use the field-specific relation Assist for the exact generated selector.
|
| 86 |
+
- Give the child a per-parent limit and deterministic ordering with an ID tie-breaker;
|
| 87 |
+
bound the parent query separately. A single-parent detail query is not batch Top-N.
|
| 88 |
+
- Server providers default to a window query (`threshold = 0`). A positive threshold
|
| 89 |
+
permits bounded probes only when the already-loaded parent count is at or below it;
|
| 90 |
+
above it, use the window plan. SQLite uses its internal AlwaysProbe policy by default.
|
| 91 |
+
- Measure before opting in. Do not infer a threshold from table size or execute COUNT
|
| 92 |
+
or statistics queries to choose a plan. Keep an index on foreign key + sort + ID.
|
| 93 |
+
- Inspect selected-plan, parent-count, per-parent-limit and probe-count telemetry.
|
| 94 |
+
Runtime-managed probes are not application-owned N+1 loops; neither strategy changes
|
| 95 |
+
authorization, loaded-state semantics or the required comment/purpose.
|
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/payment_attempt.payment.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# TypeScript Query Field Assist — `payment_attempt.payment`
|
| 4 |
+
|
| 5 |
+
KSML entity: `Payment Attempt`
|
| 6 |
+
KSML field: `Payment`
|
| 7 |
+
Type: `Payment`
|
| 8 |
+
|
| 9 |
+
| Capability | Generated API |
|
| 10 |
+
| --- | --- |
|
| 11 |
+
| Select | `selectPaymentWith(request)` |
|
| 12 |
+
| Filter identity | `filterByPayment(id)`, `filterByPaymentIn(...ids)` |
|
| 13 |
+
| Filter nested request | `withPaymentMatching(request)`, `withoutPaymentMatching(request)` |
|
| 14 |
+
| Group | `groupByPayment()`, `groupByPaymentAs(alias)` |
|
| 15 |
+
| Facet | `facetByPaymentAs(name, request, includeAllFacets)` |
|
| 16 |
+
Execution requires `comment(...)`, `purpose(...)`, and exactly one `context`.
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
---
|
| 20 |
+
|
| 21 |
+
## TeaQL seven-language assist contract
|
| 22 |
+
|
| 23 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 24 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 25 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 26 |
+
|
| 27 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 28 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 29 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 30 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 31 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 32 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 33 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 34 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 35 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 36 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 37 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 38 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 39 |
+
- If the required operation is absent after current entity/action and required field
|
| 40 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 41 |
+
generated library as a fallback.
|
| 42 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 43 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 44 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 45 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 46 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 47 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 48 |
+
|
| 49 |
+
Capability: `query`.
|
| 50 |
+
|
| 51 |
+
- Use generated projection, relation, predicate, sort, and aggregate APIs; never
|
| 52 |
+
concatenate application SQL or silently ignore an unsupported filter.
|
| 53 |
+
- Rows, record count, facets, and aggregates must share the same active filter.
|
| 54 |
+
- Add negative tests for missing purpose/comment and forbidden dynamic fields.
|
| 55 |
+
|
| 56 |
+
### Optional per-parent Top-N optimization
|
| 57 |
+
|
| 58 |
+
- Configure `topNProbeParentThreshold(threshold)` on the nested child request before its intent/execution
|
| 59 |
+
stage. Use the field-specific relation Assist for the exact generated selector.
|
| 60 |
+
- Give the child a per-parent limit and deterministic ordering with an ID tie-breaker;
|
| 61 |
+
bound the parent query separately. A single-parent detail query is not batch Top-N.
|
| 62 |
+
- Server providers default to a window query (`threshold = 0`). A positive threshold
|
| 63 |
+
permits bounded probes only when the already-loaded parent count is at or below it;
|
| 64 |
+
above it, use the window plan. SQLite uses its internal AlwaysProbe policy by default.
|
| 65 |
+
- Measure before opting in. Do not infer a threshold from table size or execute COUNT
|
| 66 |
+
or statistics queries to choose a plan. Keep an index on foreign key + sort + ID.
|
| 67 |
+
- Inspect selected-plan, parent-count, per-parent-limit and probe-count telemetry.
|
| 68 |
+
Runtime-managed probes are not application-owned N+1 loops; neither strategy changes
|
| 69 |
+
authorization, loaded-state semantics or the required comment/purpose.
|
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-query/platform.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# TypeScript Assist — Query `Platform`
|
| 4 |
+
|
| 5 |
+
Use the exact generated `Q.platformsWithMinimalFields()`
|
| 6 |
+
entry point. Trusted runtime and policy state comes only from `UserContext`.
|
| 7 |
+
|
| 8 |
+
```typescript
|
| 9 |
+
import { Q } from './Q';
|
| 10 |
+
import { Platform } from './models/Platform';
|
| 11 |
+
import { SmartList, UserContext } from '../teaql-ts';
|
| 12 |
+
|
| 13 |
+
export async function queryPlatformById(
|
| 14 |
+
context: UserContext,
|
| 15 |
+
entityId: string,
|
| 16 |
+
): Promise<SmartList<Platform>> {
|
| 17 |
+
return Q.platformsWithMinimalFields()
|
| 18 |
+
.withIdIs(entityId)
|
| 19 |
+
.orderByIdAscending()
|
| 20 |
+
.limit(20)
|
| 21 |
+
.comment('what: load the requested Platform row')
|
| 22 |
+
.purpose('why: serve the authorized Platform view')
|
| 23 |
+
.executeForList(context);
|
| 24 |
+
}
|
| 25 |
+
```
|
| 26 |
+
|
| 27 |
+
Compile and execute this source unchanged. Use only generated projection,
|
| 28 |
+
predicate, ordering, and relation-selection APIs. Missing or blank intent,
|
| 29 |
+
unknown fields, unbounded reads, and trusted-context inputs must fail. Use generated
|
| 30 |
+
relation loading rather than handwritten child-query loops; never guess a plural.
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
## Field-specific Query Assist
|
| 34 |
+
|
| 35 |
+
Use the canonical KSML field name from this list. Do not substitute a language member name, JSON name, or database column.
|
| 36 |
+
|
| 37 |
+
| KSML field | Type | Field help |
|
| 38 |
+
| --- | --- | --- |
|
| 39 |
+
| `id` | `id` | `typescript-assist-query/platform.id` |
|
| 40 |
+
| `name` | `string` | `typescript-assist-query/platform.name` |
|
| 41 |
+
| `version` | `version` | `typescript-assist-query/platform.version` |
|
| 42 |
+
|
| 43 |
+
Generated reverse relations are derived from referencing KSML fields. Use their exact generated location for relation selection and access:
|
| 44 |
+
|
| 45 |
+
| Generated reverse relation | Child entity | Field help |
|
| 46 |
+
| --- | --- | --- |
|
| 47 |
+
| `customer_order_list` | `customer_order` | `typescript-assist-query/platform.customer_order_list` |
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
---
|
| 51 |
+
|
| 52 |
+
## TeaQL seven-language assist contract
|
| 53 |
+
|
| 54 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 55 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 56 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 57 |
+
|
| 58 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 59 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 60 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 61 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 62 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 63 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 64 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 65 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 66 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 67 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 68 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 69 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 70 |
+
- If the required operation is absent after current entity/action and required field
|
| 71 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 72 |
+
generated library as a fallback.
|
| 73 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 74 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 75 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 76 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 77 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 78 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 79 |
+
|
| 80 |
+
Capability: `query`.
|
| 81 |
+
|
| 82 |
+
- Use generated projection, relation, predicate, sort, and aggregate APIs; never
|
| 83 |
+
concatenate application SQL or silently ignore an unsupported filter.
|
| 84 |
+
- Rows, record count, facets, and aggregates must share the same active filter.
|
| 85 |
+
- Add negative tests for missing purpose/comment and forbidden dynamic fields.
|
| 86 |
+
|
| 87 |
+
### Optional per-parent Top-N optimization
|
| 88 |
+
|
| 89 |
+
- Configure `topNProbeParentThreshold(threshold)` on the nested child request before its intent/execution
|
| 90 |
+
stage. Use the field-specific relation Assist for the exact generated selector.
|
| 91 |
+
- Give the child a per-parent limit and deterministic ordering with an ID tie-breaker;
|
| 92 |
+
bound the parent query separately. A single-parent detail query is not batch Top-N.
|
| 93 |
+
- Server providers default to a window query (`threshold = 0`). A positive threshold
|
| 94 |
+
permits bounded probes only when the already-loaded parent count is at or below it;
|
| 95 |
+
above it, use the window plan. SQLite uses its internal AlwaysProbe policy by default.
|
| 96 |
+
- Measure before opting in. Do not infer a threshold from table size or execute COUNT
|
| 97 |
+
or statistics queries to choose a plan. Keep an index on foreign key + sort + ID.
|
| 98 |
+
- Inspect selected-plan, parent-count, per-parent-limit and probe-count telemetry.
|
| 99 |
+
Runtime-managed probes are not application-owned N+1 loops; neither strategy changes
|
| 100 |
+
authorization, loaded-state semantics or the required comment/purpose.
|
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-update/customer_order.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# TypeScript Assist — Update `Customer Order`
|
| 4 |
+
|
| 5 |
+
Load the current row and its original optimistic version. Never reconstruct an
|
| 6 |
+
entity from an ID/version supplied by a client. Trusted runtime and policy state
|
| 7 |
+
comes only from `UserContext`.
|
| 8 |
+
|
| 9 |
+
An entity update is not a partial DTO patch. Load every scalar field before
|
| 10 |
+
modification so checker rules can validate the complete business state. Never
|
| 11 |
+
use `WithMinimalFields()` or a reduced projection for an entity that will be saved.
|
| 12 |
+
|
| 13 |
+
```typescript
|
| 14 |
+
import { UserContext } from '../teaql-ts';
|
| 15 |
+
import { Q } from './Q';
|
| 16 |
+
import { CustomerOrder } from './models/CustomerOrder';
|
| 17 |
+
|
| 18 |
+
export interface UpdateCustomerOrderInput {
|
| 19 |
+
orderNumber: string;
|
| 20 |
+
description: string;
|
| 21 |
+
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
export async function updateCustomerOrder(
|
| 25 |
+
id: string,
|
| 26 |
+
input: UpdateCustomerOrderInput,
|
| 27 |
+
context: UserContext,
|
| 28 |
+
throwIfMissing = false,
|
| 29 |
+
): Promise<CustomerOrder | undefined> {
|
| 30 |
+
const entity = await Q.customerOrders()
|
| 31 |
+
.withIdIs(id)
|
| 32 |
+
|
| 33 |
+
.comment('what: load current Customer Order for update')
|
| 34 |
+
.purpose('why: preserve original version for optimistic locking')
|
| 35 |
+
.executeForOne(context);
|
| 36 |
+
if (!entity) {
|
| 37 |
+
if (throwIfMissing) throw new Error('Customer Order not found: ' + id);
|
| 38 |
+
return undefined;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
entity.updateOrderNumber(input.orderNumber);
|
| 42 |
+
entity.updateDescription(input.description);
|
| 43 |
+
|
| 44 |
+
await entity
|
| 45 |
+
.auditAs('Update Customer Order for the requested business operation')
|
| 46 |
+
.save(context);
|
| 47 |
+
return entity;
|
| 48 |
+
}
|
| 49 |
+
```
|
| 50 |
+
|
| 51 |
+
Compile the source unchanged. Prove persistence and query-back, a conflict from
|
| 52 |
+
an independently loaded stale copy, undefined and throwing not-found behavior,
|
| 53 |
+
missing/blank audit rejection, and compilation failure for unknown or trusted
|
| 54 |
+
fields. Constant and relation updates require an explicitly selected generated
|
| 55 |
+
method; do not invent a generic setter.
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
---
|
| 59 |
+
|
| 60 |
+
## TeaQL seven-language assist contract
|
| 61 |
+
|
| 62 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 63 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 64 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 65 |
+
|
| 66 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 67 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 68 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 69 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 70 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 71 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 72 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 73 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 74 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 75 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 76 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 77 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 78 |
+
- If the required operation is absent after current entity/action and required field
|
| 79 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 80 |
+
generated library as a fallback.
|
| 81 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 82 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 83 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 84 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 85 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 86 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 87 |
+
|
| 88 |
+
Capability: `update`.
|
| 89 |
+
|
| 90 |
+
- Load the tenant-scoped current entity first so its original version participates
|
| 91 |
+
in optimistic locking; do not reconstruct versioned state from untrusted JSON.
|
| 92 |
+
- Allow-list writable fields, attach the generated audit-reason API, and save with
|
| 93 |
+
the same UserContext. Add a stale-version rejection test.
|
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-update/order_item.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# TypeScript Assist — Update `Order Item`
|
| 4 |
+
|
| 5 |
+
Load the current row and its original optimistic version. Never reconstruct an
|
| 6 |
+
entity from an ID/version supplied by a client. Trusted runtime and policy state
|
| 7 |
+
comes only from `UserContext`.
|
| 8 |
+
|
| 9 |
+
An entity update is not a partial DTO patch. Load every scalar field before
|
| 10 |
+
modification so checker rules can validate the complete business state. Never
|
| 11 |
+
use `WithMinimalFields()` or a reduced projection for an entity that will be saved.
|
| 12 |
+
|
| 13 |
+
```typescript
|
| 14 |
+
import { UserContext } from '../teaql-ts';
|
| 15 |
+
import { Q } from './Q';
|
| 16 |
+
import { OrderItem } from './models/OrderItem';
|
| 17 |
+
|
| 18 |
+
export interface UpdateOrderItemInput {
|
| 19 |
+
name: string;
|
| 20 |
+
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
export async function updateOrderItem(
|
| 24 |
+
id: string,
|
| 25 |
+
input: UpdateOrderItemInput,
|
| 26 |
+
context: UserContext,
|
| 27 |
+
throwIfMissing = false,
|
| 28 |
+
): Promise<OrderItem | undefined> {
|
| 29 |
+
const entity = await Q.orderItems()
|
| 30 |
+
.withIdIs(id)
|
| 31 |
+
|
| 32 |
+
.comment('what: load current Order Item for update')
|
| 33 |
+
.purpose('why: preserve original version for optimistic locking')
|
| 34 |
+
.executeForOne(context);
|
| 35 |
+
if (!entity) {
|
| 36 |
+
if (throwIfMissing) throw new Error('Order Item not found: ' + id);
|
| 37 |
+
return undefined;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
entity.updateName(input.name);
|
| 41 |
+
|
| 42 |
+
await entity
|
| 43 |
+
.auditAs('Update Order Item for the requested business operation')
|
| 44 |
+
.save(context);
|
| 45 |
+
return entity;
|
| 46 |
+
}
|
| 47 |
+
```
|
| 48 |
+
|
| 49 |
+
Compile the source unchanged. Prove persistence and query-back, a conflict from
|
| 50 |
+
an independently loaded stale copy, undefined and throwing not-found behavior,
|
| 51 |
+
missing/blank audit rejection, and compilation failure for unknown or trusted
|
| 52 |
+
fields. Constant and relation updates require an explicitly selected generated
|
| 53 |
+
method; do not invent a generic setter.
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
---
|
| 57 |
+
|
| 58 |
+
## TeaQL seven-language assist contract
|
| 59 |
+
|
| 60 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 61 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 62 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 63 |
+
|
| 64 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 65 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 66 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 67 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 68 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 69 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 70 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 71 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 72 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 73 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 74 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 75 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 76 |
+
- If the required operation is absent after current entity/action and required field
|
| 77 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 78 |
+
generated library as a fallback.
|
| 79 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 80 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 81 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 82 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 83 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 84 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 85 |
+
|
| 86 |
+
Capability: `update`.
|
| 87 |
+
|
| 88 |
+
- Load the tenant-scoped current entity first so its original version participates
|
| 89 |
+
in optimistic locking; do not reconstruct versioned state from untrusted JSON.
|
| 90 |
+
- Allow-list writable fields, attach the generated audit-reason API, and save with
|
| 91 |
+
the same UserContext. Add a stale-version rejection test.
|
source/teaql-ts/examples/trace-chain/evidence/assist/typescript-assist-update/payment.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
|
| 3 |
+
# TypeScript Assist — Update `Payment`
|
| 4 |
+
|
| 5 |
+
Load the current row and its original optimistic version. Never reconstruct an
|
| 6 |
+
entity from an ID/version supplied by a client. Trusted runtime and policy state
|
| 7 |
+
comes only from `UserContext`.
|
| 8 |
+
|
| 9 |
+
An entity update is not a partial DTO patch. Load every scalar field before
|
| 10 |
+
modification so checker rules can validate the complete business state. Never
|
| 11 |
+
use `WithMinimalFields()` or a reduced projection for an entity that will be saved.
|
| 12 |
+
|
| 13 |
+
```typescript
|
| 14 |
+
import { UserContext } from '../teaql-ts';
|
| 15 |
+
import { Q } from './Q';
|
| 16 |
+
import { Payment } from './models/Payment';
|
| 17 |
+
|
| 18 |
+
export interface UpdatePaymentInput {
|
| 19 |
+
referenceCode: string;
|
| 20 |
+
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
export async function updatePayment(
|
| 24 |
+
id: string,
|
| 25 |
+
input: UpdatePaymentInput,
|
| 26 |
+
context: UserContext,
|
| 27 |
+
throwIfMissing = false,
|
| 28 |
+
): Promise<Payment | undefined> {
|
| 29 |
+
const entity = await Q.payments()
|
| 30 |
+
.withIdIs(id)
|
| 31 |
+
|
| 32 |
+
.comment('what: load current Payment for update')
|
| 33 |
+
.purpose('why: preserve original version for optimistic locking')
|
| 34 |
+
.executeForOne(context);
|
| 35 |
+
if (!entity) {
|
| 36 |
+
if (throwIfMissing) throw new Error('Payment not found: ' + id);
|
| 37 |
+
return undefined;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
entity.updateReferenceCode(input.referenceCode);
|
| 41 |
+
|
| 42 |
+
await entity
|
| 43 |
+
.auditAs('Update Payment for the requested business operation')
|
| 44 |
+
.save(context);
|
| 45 |
+
return entity;
|
| 46 |
+
}
|
| 47 |
+
```
|
| 48 |
+
|
| 49 |
+
Compile the source unchanged. Prove persistence and query-back, a conflict from
|
| 50 |
+
an independently loaded stale copy, undefined and throwing not-found behavior,
|
| 51 |
+
missing/blank audit rejection, and compilation failure for unknown or trusted
|
| 52 |
+
fields. Constant and relation updates require an explicitly selected generated
|
| 53 |
+
method; do not invent a generic setter.
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
---
|
| 57 |
+
|
| 58 |
+
## TeaQL seven-language assist contract
|
| 59 |
+
|
| 60 |
+
Apply the verified Rust semantic ceiling while using only the exact TYPESCRIPT generated and
|
| 61 |
+
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
|
| 62 |
+
model-aware Assist. Do not inspect generated domain-library source.
|
| 63 |
+
|
| 64 |
+
- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
|
| 65 |
+
- Human and non-human entities use different generated predicate vocabularies. Preserve
|
| 66 |
+
forms such as “who are active” and “whose email is”; never infer them from English.
|
| 67 |
+
- Configure filters, projection, paging, and other query options before `purpose(...)`.
|
| 68 |
+
Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
|
| 69 |
+
requires both values, but comment does not have to immediately precede purpose.
|
| 70 |
+
- Every execute/list/stream and every save accepts exactly one context argument:
|
| 71 |
+
`UserContext`. Name that argument `context`, never `runtime`; data services and global
|
| 72 |
+
policy are injected when the context is built. Reserve `runtime` for process-level
|
| 73 |
+
runtime ownership, provider/pool setup, and module assembly.
|
| 74 |
+
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
|
| 75 |
+
and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
|
| 76 |
+
- If the required operation is absent after current entity/action and required field
|
| 77 |
+
Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
|
| 78 |
+
generated library as a fallback.
|
| 79 |
+
- Create each application-owned source file once. After its first compile attempt,
|
| 80 |
+
repair only the smallest block identified by the exact compiler or test diagnostic.
|
| 81 |
+
Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
|
| 82 |
+
- Before a repair that would replace more than 25% of an existing application file,
|
| 83 |
+
stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
|
| 84 |
+
estimated scope. Initial creation and model-driven regeneration are not repairs.
|
| 85 |
+
|
| 86 |
+
Capability: `update`.
|
| 87 |
+
|
| 88 |
+
- Load the tenant-scoped current entity first so its original version participates
|
| 89 |
+
in optimistic locking; do not reconstruct versioned state from untrusted JSON.
|
| 90 |
+
- Allow-list writable fields, attach the generated audit-reason API, and save with
|
| 91 |
+
the same UserContext. Add a stale-version rejection test.
|
source/teaql-ts/examples/trace-chain/evidence/evaluation.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- ephemeral -->
|
| 2 |
+
# KSML Evaluation Report
|
| 3 |
+
## 📊 Summary
|
| 4 |
+
- **Errors**: 0
|
| 5 |
+
- **Warnings**: 0
|
| 6 |
+
- **Suggestions**: 0
|
| 7 |
+
- **Solids**: 17
|
| 8 |
+
|
| 9 |
+
## ✅ Solids
|
| 10 |
+
|
| 11 |
+
| Rule ID | Target | Source | Message |
|
| 12 |
+
|---------|--------|--------|---------|
|
| 13 |
+
| `KSML-UPLOAD-001` | `` | — | The upload contains 1 files. |
|
| 14 |
+
| `KSML-UPLOAD-005` | `` | `model.xml:2` | Resolved entrypoint: model.xml |
|
| 15 |
+
| `KSML-XML-002` | `` | `model.xml:2` | The XML document model.xml was parsed successfully. |
|
| 16 |
+
| `KSML-ROOT-003` | `` | `model.xml:2` | Root name 'trace-chain-service' is well-formed. |
|
| 17 |
+
| `KSML-ROOT-008` | `` | `model.xml:2` | External JSON business fields use the default camelCase profile. |
|
| 18 |
+
| `KSML-OBJECT-001` | `platform` | `model.xml:4` | Object 'platform' defines display name, module, and module key metadata. |
|
| 19 |
+
| `KSML-OBJECT-001` | `customer_order` | `model.xml:6` | Object 'customer_order' defines display name, module, and module key metadata. |
|
| 20 |
+
| `KSML-OBJECT-001` | `order_item` | `model.xml:9` | Object 'order_item' defines display name, module, and module key metadata. |
|
| 21 |
+
| `KSML-OBJECT-001` | `payment` | `model.xml:11` | Object 'payment' defines display name, module, and module key metadata. |
|
| 22 |
+
| `KSML-OBJECT-001` | `payment_attempt` | `model.xml:13` | Object 'payment_attempt' defines display name, module, and module key metadata. |
|
| 23 |
+
| `KSML-OBJECT-001` | `shipment` | `model.xml:15` | Object 'shipment' defines display name, module, and module key metadata. |
|
| 24 |
+
| `KSML-REFERENCE-003` | `customer_order.platform` | `model.xml:7` | Reference 'platform' in 'customer_order' successfully resolves to target object 'platform'. |
|
| 25 |
+
| `KSML-REFERENCE-003` | `order_item.customer_order` | `model.xml:10` | Reference 'customer_order' in 'order_item' successfully resolves to target object 'customer_order'. |
|
| 26 |
+
| `KSML-REFERENCE-003` | `payment.customer_order` | `model.xml:12` | Reference 'customer_order' in 'payment' successfully resolves to target object 'customer_order'. |
|
| 27 |
+
| `KSML-REFERENCE-003` | `payment_attempt.payment` | `model.xml:14` | Reference 'payment' in 'payment_attempt' successfully resolves to target object 'payment'. |
|
| 28 |
+
| `KSML-REFERENCE-003` | `shipment.customer_order` | `model.xml:16` | Reference 'customer_order' in 'shipment' successfully resolves to target object 'customer_order'. |
|
| 29 |
+
| `KSML-DOMAIN-ROOT-003` | `` | `model.xml:2` | Exactly one domain root candidate 'platform' was found. |
|
| 30 |
+
|
source/teaql-ts/examples/trace-chain/evidence/generated-library-manifest.sha256
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
665f49e26ecccfaaac239601a28d07064e6c9d87ec17e90e0e2e34fb7752884c package.json
|
| 2 |
+
d0e703595d462573c4ce298f1f96581dfc76e783c19baedfb1406241e6f2f26f src/generated/E.ts
|
| 3 |
+
d53eca569db8c6c7ed0bb7b76125bdeb0b2799c5ae678149e384bdfe23b03530 src/generated/models/CustomerOrder.ts
|
| 4 |
+
cae0253e18a9f9eff98d1c88c8f4483c839ec6ea70916b7e483b2977ff8ae785 src/generated/models/OrderItem.ts
|
| 5 |
+
a4dc14949d477f7e17a3118bfb7e8a1322a43766a918de439f685a2e3c330362 src/generated/models/Payment.ts
|
| 6 |
+
212167fdf2dcfd211b5eda9cc787150068ebb73c58e12faa4d86c6b4875d9924 src/generated/models/PaymentAttempt.ts
|
| 7 |
+
95913330ac20ceaa057ef965d9852151ea3df3054491d3baa91395ffaff8791c src/generated/models/Platform.ts
|
| 8 |
+
ff2f4ea6457c4f0c20de6fef52e5a6bdafa38b00ce30db028bdb8373a9490812 src/generated/models/Shipment.ts
|
| 9 |
+
ec633c6c5c488e3a2f0dd77a2c9cc5b40cece976f8439caf6782bb9f5cd49833 src/generated/Q.ts
|
| 10 |
+
11b8d4931d251c489e08995ae8a53766f0d567773246a38b32827091eeabaf64 src/generated/requests/CustomerOrderRequest.ts
|
| 11 |
+
4786b92f0fef3a62846e3e25c135dac4a4b7c8e227e24b6e6d3a6de111823582 src/generated/requests/OrderItemRequest.ts
|
| 12 |
+
4b406885fb61a6faa11757e775b041b301d9fbca4d22ce0cb08ade1ea7ec8775 src/generated/requests/PaymentAttemptRequest.ts
|
| 13 |
+
42c698c476bfae5c652eb604c2bde2209d2a085962f5835c6f6795500bb5c3fa src/generated/requests/PaymentRequest.ts
|
| 14 |
+
4336b0288835f02dc04ff0804a843c933f81d10f9d41f7d59c9783f9ae56dc79 src/generated/requests/PlatformRequest.ts
|
| 15 |
+
e38d62798230bd86c4ca5184165c6a9efdc44d506d090b1abb9bf02ea8c1e742 src/generated/requests/ShipmentRequest.ts
|
| 16 |
+
1d69981ee7ba6adcd404004e53c6d20fb4b480d11fafc18f6116930eae6a0783 src/generated-bootstrap.ts
|
| 17 |
+
b2793ced879531ebf0b7d1a87fbbe0357bad746f43b9d8fc900dce458dc07820 src/generated-search-models.ts
|
| 18 |
+
243bf811633ba73903dfa221890d7d6636f237753d595a84df96bd555639f7a0 src/runtime-module.ts
|
| 19 |
+
bf09100425eaa11c09ae3a412cea5706c2c60dcb0e4ed05effc5158b78a6e8a8 src/teaql-schemas.ts
|
| 20 |
+
cc705f9f7873450eae541311317db3402dc40b7cf068c440169bd7ba06dcb1ed src/teaql-ts.ts
|
| 21 |
+
5ff4a2f49563da43619a3bde0da4d3b73105e87824aef4851ba050b0509272d3 teaql-i18n.json
|
| 22 |
+
cf9a9767019ac7f4035a6d16952a5ae75b964b1c10c4584822b90799e6ce2037 tsconfig.json
|
source/teaql-ts/examples/trace-chain/evidence/shared-reference-library.sha256
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
665f49e26ecccfaaac239601a28d07064e6c9d87ec17e90e0e2e34fb7752884c package.json
|
| 2 |
+
d0e703595d462573c4ce298f1f96581dfc76e783c19baedfb1406241e6f2f26f src/generated/E.ts
|
| 3 |
+
d53eca569db8c6c7ed0bb7b76125bdeb0b2799c5ae678149e384bdfe23b03530 src/generated/models/CustomerOrder.ts
|
| 4 |
+
cae0253e18a9f9eff98d1c88c8f4483c839ec6ea70916b7e483b2977ff8ae785 src/generated/models/OrderItem.ts
|
| 5 |
+
a4dc14949d477f7e17a3118bfb7e8a1322a43766a918de439f685a2e3c330362 src/generated/models/Payment.ts
|
| 6 |
+
212167fdf2dcfd211b5eda9cc787150068ebb73c58e12faa4d86c6b4875d9924 src/generated/models/PaymentAttempt.ts
|
| 7 |
+
95913330ac20ceaa057ef965d9852151ea3df3054491d3baa91395ffaff8791c src/generated/models/Platform.ts
|
| 8 |
+
ff2f4ea6457c4f0c20de6fef52e5a6bdafa38b00ce30db028bdb8373a9490812 src/generated/models/Shipment.ts
|
| 9 |
+
ec633c6c5c488e3a2f0dd77a2c9cc5b40cece976f8439caf6782bb9f5cd49833 src/generated/Q.ts
|
| 10 |
+
11b8d4931d251c489e08995ae8a53766f0d567773246a38b32827091eeabaf64 src/generated/requests/CustomerOrderRequest.ts
|
| 11 |
+
4786b92f0fef3a62846e3e25c135dac4a4b7c8e227e24b6e6d3a6de111823582 src/generated/requests/OrderItemRequest.ts
|
| 12 |
+
4b406885fb61a6faa11757e775b041b301d9fbca4d22ce0cb08ade1ea7ec8775 src/generated/requests/PaymentAttemptRequest.ts
|
| 13 |
+
42c698c476bfae5c652eb604c2bde2209d2a085962f5835c6f6795500bb5c3fa src/generated/requests/PaymentRequest.ts
|
| 14 |
+
4336b0288835f02dc04ff0804a843c933f81d10f9d41f7d59c9783f9ae56dc79 src/generated/requests/PlatformRequest.ts
|
| 15 |
+
e38d62798230bd86c4ca5184165c6a9efdc44d506d090b1abb9bf02ea8c1e742 src/generated/requests/ShipmentRequest.ts
|
| 16 |
+
1d69981ee7ba6adcd404004e53c6d20fb4b480d11fafc18f6116930eae6a0783 src/generated-bootstrap.ts
|
| 17 |
+
b2793ced879531ebf0b7d1a87fbbe0357bad746f43b9d8fc900dce458dc07820 src/generated-search-models.ts
|
| 18 |
+
243bf811633ba73903dfa221890d7d6636f237753d595a84df96bd555639f7a0 src/runtime-module.ts
|
| 19 |
+
bf09100425eaa11c09ae3a412cea5706c2c60dcb0e4ed05effc5158b78a6e8a8 src/teaql-schemas.ts
|
| 20 |
+
cc705f9f7873450eae541311317db3402dc40b7cf068c440169bd7ba06dcb1ed src/teaql-ts.ts
|
| 21 |
+
5ff4a2f49563da43619a3bde0da4d3b73105e87824aef4851ba050b0509272d3 teaql-i18n.json
|
| 22 |
+
cf9a9767019ac7f4035a6d16952a5ae75b964b1c10c4584822b90799e6ce2037 tsconfig.json
|
source/teaql-ts/examples/trace-chain/lib/package.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "trace-chain-service-lib",
|
| 3 |
+
"version": "1.0.0",
|
| 4 |
+
"description": "Generated typescript library",
|
| 5 |
+
"main": "src/generated/Q.ts",
|
| 6 |
+
"scripts": {
|
| 7 |
+
"build": "tsc --noEmit"
|
| 8 |
+
},
|
| 9 |
+
"dependencies": {
|
| 10 |
+
"teaql-ts": "npm:@teaql/teaql@0.2.10"},
|
| 11 |
+
"devDependencies": {
|
| 12 |
+
"typescript": "^5.0.0"}
|
| 13 |
+
}
|
source/teaql-ts/examples/trace-chain/lib/src/generated-bootstrap.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { UserContext } from './teaql-ts';
|
| 2 |
+
import { Q } from './generated/Q';
|
| 3 |
+
import { Platform } from './generated/models/Platform';
|
| 4 |
+
|
| 5 |
+
/** @internal Generated typed Mutation bootstrap; never call from application code. */
|
| 6 |
+
export async function ensureGeneratedBootstrap(context: UserContext): Promise<void> {
|
| 7 |
+
let domainRoot = (await Q.platforms().withIdIs('1').comment('what: locate generated Domain Root').purpose('why: idempotent runtime bootstrap').executeForList(context))[0];
|
| 8 |
+
if (!domainRoot) {
|
| 9 |
+
domainRoot = Platform.teaqlBootstrapNew('1');
|
| 10 |
+
domainRoot.updateName("Trace Chain Verification");
|
| 11 |
+
await domainRoot.auditAs('create generated Domain Root Platform').save(context);
|
| 12 |
+
}
|
| 13 |
+
context.withActiveRoot({ entity: 'Platform', id: domainRoot.id! });
|
| 14 |
+
}
|
source/teaql-ts/examples/trace-chain/lib/src/generated-search-models.ts
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import type { GeneratedSearchModel } from "teaql-ts";
|
| 2 |
+
|
| 3 |
+
/** Generated trusted naming/type metadata. No query execution or authorization lives here. */
|
| 4 |
+
export const GENERATED_SEARCH_MODELS: Readonly<Record<string, GeneratedSearchModel>> = Object.freeze({
|
| 5 |
+
"Platform": Object.freeze({
|
| 6 |
+
fields: Object.freeze({
|
| 7 |
+
"id": "integer" as const,
|
| 8 |
+
"name": "string" as const,
|
| 9 |
+
"version": "integer" as const,
|
| 10 |
+
}),
|
| 11 |
+
queryFields: Object.freeze({
|
| 12 |
+
"id": "id",
|
| 13 |
+
"name": "name",
|
| 14 |
+
"version": "version",
|
| 15 |
+
}),
|
| 16 |
+
relations: Object.freeze({
|
| 17 |
+
"customerOrderList": "CustomerOrder",
|
| 18 |
+
}),
|
| 19 |
+
}),
|
| 20 |
+
"CustomerOrder": Object.freeze({
|
| 21 |
+
fields: Object.freeze({
|
| 22 |
+
"id": "integer" as const,
|
| 23 |
+
"platform": "integer" as const,
|
| 24 |
+
"order_number": "string" as const,
|
| 25 |
+
"orderNumber": "string" as const,
|
| 26 |
+
"description": "string" as const,
|
| 27 |
+
"version": "integer" as const,
|
| 28 |
+
}),
|
| 29 |
+
queryFields: Object.freeze({
|
| 30 |
+
"id": "id",
|
| 31 |
+
"platform": "platform",
|
| 32 |
+
"order_number": "orderNumber",
|
| 33 |
+
"orderNumber": "orderNumber",
|
| 34 |
+
"description": "description",
|
| 35 |
+
"version": "version",
|
| 36 |
+
}),
|
| 37 |
+
relations: Object.freeze({
|
| 38 |
+
"platform": "Platform",
|
| 39 |
+
"orderItemList": "OrderItem",
|
| 40 |
+
"paymentList": "Payment",
|
| 41 |
+
"shipmentList": "Shipment",
|
| 42 |
+
}),
|
| 43 |
+
}),
|
| 44 |
+
"OrderItem": Object.freeze({
|
| 45 |
+
fields: Object.freeze({
|
| 46 |
+
"id": "integer" as const,
|
| 47 |
+
"customer_order": "integer" as const,
|
| 48 |
+
"customerOrder": "integer" as const,
|
| 49 |
+
"name": "string" as const,
|
| 50 |
+
"version": "integer" as const,
|
| 51 |
+
}),
|
| 52 |
+
queryFields: Object.freeze({
|
| 53 |
+
"id": "id",
|
| 54 |
+
"customer_order": "customerOrder",
|
| 55 |
+
"customerOrder": "customerOrder",
|
| 56 |
+
"name": "name",
|
| 57 |
+
"version": "version",
|
| 58 |
+
}),
|
| 59 |
+
relations: Object.freeze({
|
| 60 |
+
"customer_order": "CustomerOrder",
|
| 61 |
+
"customerOrder": "CustomerOrder",
|
| 62 |
+
}),
|
| 63 |
+
}),
|
| 64 |
+
"Payment": Object.freeze({
|
| 65 |
+
fields: Object.freeze({
|
| 66 |
+
"id": "integer" as const,
|
| 67 |
+
"customer_order": "integer" as const,
|
| 68 |
+
"customerOrder": "integer" as const,
|
| 69 |
+
"reference_code": "string" as const,
|
| 70 |
+
"referenceCode": "string" as const,
|
| 71 |
+
"version": "integer" as const,
|
| 72 |
+
}),
|
| 73 |
+
queryFields: Object.freeze({
|
| 74 |
+
"id": "id",
|
| 75 |
+
"customer_order": "customerOrder",
|
| 76 |
+
"customerOrder": "customerOrder",
|
| 77 |
+
"reference_code": "referenceCode",
|
| 78 |
+
"referenceCode": "referenceCode",
|
| 79 |
+
"version": "version",
|
| 80 |
+
}),
|
| 81 |
+
relations: Object.freeze({
|
| 82 |
+
"customer_order": "CustomerOrder",
|
| 83 |
+
"customerOrder": "CustomerOrder",
|
| 84 |
+
"paymentAttemptList": "PaymentAttempt",
|
| 85 |
+
}),
|
| 86 |
+
}),
|
| 87 |
+
"PaymentAttempt": Object.freeze({
|
| 88 |
+
fields: Object.freeze({
|
| 89 |
+
"id": "integer" as const,
|
| 90 |
+
"payment": "integer" as const,
|
| 91 |
+
"reference_code": "string" as const,
|
| 92 |
+
"referenceCode": "string" as const,
|
| 93 |
+
"version": "integer" as const,
|
| 94 |
+
}),
|
| 95 |
+
queryFields: Object.freeze({
|
| 96 |
+
"id": "id",
|
| 97 |
+
"payment": "payment",
|
| 98 |
+
"reference_code": "referenceCode",
|
| 99 |
+
"referenceCode": "referenceCode",
|
| 100 |
+
"version": "version",
|
| 101 |
+
}),
|
| 102 |
+
relations: Object.freeze({
|
| 103 |
+
"payment": "Payment",
|
| 104 |
+
}),
|
| 105 |
+
}),
|
| 106 |
+
"Shipment": Object.freeze({
|
| 107 |
+
fields: Object.freeze({
|
| 108 |
+
"id": "integer" as const,
|
| 109 |
+
"customer_order": "integer" as const,
|
| 110 |
+
"customerOrder": "integer" as const,
|
| 111 |
+
"reference_code": "string" as const,
|
| 112 |
+
"referenceCode": "string" as const,
|
| 113 |
+
"version": "integer" as const,
|
| 114 |
+
}),
|
| 115 |
+
queryFields: Object.freeze({
|
| 116 |
+
"id": "id",
|
| 117 |
+
"customer_order": "customerOrder",
|
| 118 |
+
"customerOrder": "customerOrder",
|
| 119 |
+
"reference_code": "referenceCode",
|
| 120 |
+
"referenceCode": "referenceCode",
|
| 121 |
+
"version": "version",
|
| 122 |
+
}),
|
| 123 |
+
relations: Object.freeze({
|
| 124 |
+
"customer_order": "CustomerOrder",
|
| 125 |
+
"customerOrder": "CustomerOrder",
|
| 126 |
+
}),
|
| 127 |
+
}),
|
| 128 |
+
});
|
source/teaql-ts/examples/trace-chain/lib/src/generated/E.ts
ADDED
|
@@ -0,0 +1,893 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Platform } from './models/Platform';
|
| 2 |
+
import { CustomerOrder } from './models/CustomerOrder';
|
| 3 |
+
import { OrderItem } from './models/OrderItem';
|
| 4 |
+
import { Payment } from './models/Payment';
|
| 5 |
+
import { PaymentAttempt } from './models/PaymentAttempt';
|
| 6 |
+
import { Shipment } from './models/Shipment';
|
| 7 |
+
|
| 8 |
+
export class TeaQLNotLoadedError extends Error {
|
| 9 |
+
readonly details: Record<string, unknown>;
|
| 10 |
+
|
| 11 |
+
constructor(
|
| 12 |
+
readonly root: string,
|
| 13 |
+
readonly accessPath: string,
|
| 14 |
+
readonly breakPoint: string,
|
| 15 |
+
) {
|
| 16 |
+
const suggestedFix = `select${breakPoint.charAt(0).toUpperCase()}${breakPoint.slice(1)}(...)`;
|
| 17 |
+
const details = {
|
| 18 |
+
error: 'TeaQLNotLoadedError',
|
| 19 |
+
root,
|
| 20 |
+
accessPath: accessPath.split('.'),
|
| 21 |
+
breakPoint,
|
| 22 |
+
missingPreload: [breakPoint],
|
| 23 |
+
suggestedFix,
|
| 24 |
+
severity: 'error',
|
| 25 |
+
humanMessage: `访问 ${root}.${accessPath} 时缺少预加载。请在查询中加入 ${suggestedFix}`,
|
| 26 |
+
};
|
| 27 |
+
super(JSON.stringify(details));
|
| 28 |
+
this.name = 'TeaQLNotLoadedError';
|
| 29 |
+
this.details = details;
|
| 30 |
+
}
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
function expressionPath(prefix: string, field: string): string {
|
| 34 |
+
return prefix ? `${prefix}.${field}` : field;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
export class ValueExpression<T> {
|
| 38 |
+
constructor(
|
| 39 |
+
private readonly value: T | null | undefined,
|
| 40 |
+
private readonly present = true,
|
| 41 |
+
private readonly notLoaded?: TeaQLNotLoadedError,
|
| 42 |
+
) {}
|
| 43 |
+
|
| 44 |
+
static missing<T>(): ValueExpression<T> {
|
| 45 |
+
return new ValueExpression<T>(undefined, false);
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
static notLoaded<T>(error: TeaQLNotLoadedError): ValueExpression<T> {
|
| 49 |
+
return new ValueExpression<T>(undefined, false, error);
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
eval(): T | null | undefined {
|
| 53 |
+
if (this.notLoaded) throw this.notLoaded;
|
| 54 |
+
return this.present ? this.value : undefined;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
isPresent(): boolean {
|
| 58 |
+
if (this.notLoaded) throw this.notLoaded;
|
| 59 |
+
return this.present;
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
orElse(fallback: T): T {
|
| 63 |
+
const value = this.eval();
|
| 64 |
+
return this.present && value != null ? value : fallback;
|
| 65 |
+
}
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
export class PlatformExpression {
|
| 69 |
+
constructor(
|
| 70 |
+
private readonly value: Platform | null | undefined,
|
| 71 |
+
private readonly root = 'Platform(null)',
|
| 72 |
+
private readonly path = '',
|
| 73 |
+
private readonly notLoaded?: TeaQLNotLoadedError,
|
| 74 |
+
) {}
|
| 75 |
+
|
| 76 |
+
eval(): Platform | null | undefined {
|
| 77 |
+
if (this.notLoaded) throw this.notLoaded;
|
| 78 |
+
return this.value;
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
id(): ValueExpression<string> {
|
| 82 |
+
if (this.notLoaded) return ValueExpression.notLoaded<string>(this.notLoaded);
|
| 83 |
+
if (!this.value) return ValueExpression.missing<string>();
|
| 84 |
+
const path = expressionPath(this.path, 'id');
|
| 85 |
+
if (!this.value.isLoaded('id')) {
|
| 86 |
+
return ValueExpression.notLoaded<string>(
|
| 87 |
+
new TeaQLNotLoadedError(this.root, path, 'id'),
|
| 88 |
+
);
|
| 89 |
+
}
|
| 90 |
+
return new ValueExpression<string>(this.value.id);
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
name(): ValueExpression<string> {
|
| 94 |
+
if (this.notLoaded) return ValueExpression.notLoaded<string>(this.notLoaded);
|
| 95 |
+
if (!this.value) return ValueExpression.missing<string>();
|
| 96 |
+
const path = expressionPath(this.path, 'name');
|
| 97 |
+
if (!this.value.isLoaded('name')) {
|
| 98 |
+
return ValueExpression.notLoaded<string>(
|
| 99 |
+
new TeaQLNotLoadedError(this.root, path, 'name'),
|
| 100 |
+
);
|
| 101 |
+
}
|
| 102 |
+
return new ValueExpression<string>(this.value.name);
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
version(): ValueExpression<number> {
|
| 106 |
+
if (this.notLoaded) return ValueExpression.notLoaded<number>(this.notLoaded);
|
| 107 |
+
if (!this.value) return ValueExpression.missing<number>();
|
| 108 |
+
const path = expressionPath(this.path, 'version');
|
| 109 |
+
if (!this.value.isLoaded('version')) {
|
| 110 |
+
return ValueExpression.notLoaded<number>(
|
| 111 |
+
new TeaQLNotLoadedError(this.root, path, 'version'),
|
| 112 |
+
);
|
| 113 |
+
}
|
| 114 |
+
return new ValueExpression<number>(this.value.version);
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
customerOrderList(): CustomerOrderListExpression {
|
| 120 |
+
const path = expressionPath(this.path, 'customerOrderList');
|
| 121 |
+
if (this.notLoaded) {
|
| 122 |
+
return new CustomerOrderListExpression([], this.root, path, false, this.notLoaded);
|
| 123 |
+
}
|
| 124 |
+
if (!this.value) return CustomerOrderListExpression.missing(this.root, path);
|
| 125 |
+
if (!this.value.isLoaded('customerOrderList')) {
|
| 126 |
+
return new CustomerOrderListExpression([], this.root, path, false,
|
| 127 |
+
new TeaQLNotLoadedError(this.root, path, 'customerOrderList'));
|
| 128 |
+
}
|
| 129 |
+
return new CustomerOrderListExpression(
|
| 130 |
+
this.value.customerOrderList(), this.root, path,
|
| 131 |
+
);
|
| 132 |
+
}
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
export class CustomerOrderExpression {
|
| 136 |
+
constructor(
|
| 137 |
+
private readonly value: CustomerOrder | null | undefined,
|
| 138 |
+
private readonly root = 'CustomerOrder(null)',
|
| 139 |
+
private readonly path = '',
|
| 140 |
+
private readonly notLoaded?: TeaQLNotLoadedError,
|
| 141 |
+
) {}
|
| 142 |
+
|
| 143 |
+
eval(): CustomerOrder | null | undefined {
|
| 144 |
+
if (this.notLoaded) throw this.notLoaded;
|
| 145 |
+
return this.value;
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
id(): ValueExpression<string> {
|
| 149 |
+
if (this.notLoaded) return ValueExpression.notLoaded<string>(this.notLoaded);
|
| 150 |
+
if (!this.value) return ValueExpression.missing<string>();
|
| 151 |
+
const path = expressionPath(this.path, 'id');
|
| 152 |
+
if (!this.value.isLoaded('id')) {
|
| 153 |
+
return ValueExpression.notLoaded<string>(
|
| 154 |
+
new TeaQLNotLoadedError(this.root, path, 'id'),
|
| 155 |
+
);
|
| 156 |
+
}
|
| 157 |
+
return new ValueExpression<string>(this.value.id);
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
orderNumber(): ValueExpression<string> {
|
| 161 |
+
if (this.notLoaded) return ValueExpression.notLoaded<string>(this.notLoaded);
|
| 162 |
+
if (!this.value) return ValueExpression.missing<string>();
|
| 163 |
+
const path = expressionPath(this.path, 'orderNumber');
|
| 164 |
+
if (!this.value.isLoaded('orderNumber')) {
|
| 165 |
+
return ValueExpression.notLoaded<string>(
|
| 166 |
+
new TeaQLNotLoadedError(this.root, path, 'orderNumber'),
|
| 167 |
+
);
|
| 168 |
+
}
|
| 169 |
+
return new ValueExpression<string>(this.value.orderNumber);
|
| 170 |
+
}
|
| 171 |
+
|
| 172 |
+
description(): ValueExpression<string> {
|
| 173 |
+
if (this.notLoaded) return ValueExpression.notLoaded<string>(this.notLoaded);
|
| 174 |
+
if (!this.value) return ValueExpression.missing<string>();
|
| 175 |
+
const path = expressionPath(this.path, 'description');
|
| 176 |
+
if (!this.value.isLoaded('description')) {
|
| 177 |
+
return ValueExpression.notLoaded<string>(
|
| 178 |
+
new TeaQLNotLoadedError(this.root, path, 'description'),
|
| 179 |
+
);
|
| 180 |
+
}
|
| 181 |
+
return new ValueExpression<string>(this.value.description);
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
version(): ValueExpression<number> {
|
| 185 |
+
if (this.notLoaded) return ValueExpression.notLoaded<number>(this.notLoaded);
|
| 186 |
+
if (!this.value) return ValueExpression.missing<number>();
|
| 187 |
+
const path = expressionPath(this.path, 'version');
|
| 188 |
+
if (!this.value.isLoaded('version')) {
|
| 189 |
+
return ValueExpression.notLoaded<number>(
|
| 190 |
+
new TeaQLNotLoadedError(this.root, path, 'version'),
|
| 191 |
+
);
|
| 192 |
+
}
|
| 193 |
+
return new ValueExpression<number>(this.value.version);
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
platformId(): ValueExpression<string | number> {
|
| 197 |
+
if (this.notLoaded) return ValueExpression.notLoaded<string | number>(this.notLoaded);
|
| 198 |
+
if (!this.value) return ValueExpression.missing<string | number>();
|
| 199 |
+
const path = expressionPath(this.path, 'platform');
|
| 200 |
+
if (!this.value.isLoaded('platform')) {
|
| 201 |
+
return ValueExpression.notLoaded<string | number>(
|
| 202 |
+
new TeaQLNotLoadedError(this.root, path, 'platform'),
|
| 203 |
+
);
|
| 204 |
+
}
|
| 205 |
+
const reference = this.value.platform;
|
| 206 |
+
return new ValueExpression<string | number>(
|
| 207 |
+
reference instanceof Platform
|
| 208 |
+
? reference.id : reference as string | number | undefined,
|
| 209 |
+
);
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
platform(): PlatformExpression {
|
| 213 |
+
const path = expressionPath(this.path, 'platform');
|
| 214 |
+
if (this.notLoaded) {
|
| 215 |
+
return new PlatformExpression(undefined, this.root, path, this.notLoaded);
|
| 216 |
+
}
|
| 217 |
+
if (!this.value) return new PlatformExpression(undefined, this.root, path);
|
| 218 |
+
if (!this.value.isLoaded('platform')) {
|
| 219 |
+
return new PlatformExpression(undefined, this.root, path,
|
| 220 |
+
new TeaQLNotLoadedError(this.root, path, 'platform'));
|
| 221 |
+
}
|
| 222 |
+
const relation = this.value.platform;
|
| 223 |
+
const target = relation == null
|
| 224 |
+
? undefined
|
| 225 |
+
: relation instanceof Platform
|
| 226 |
+
? relation
|
| 227 |
+
: Platform.fromRecord({ id: relation });
|
| 228 |
+
return new PlatformExpression(target, this.root, path);
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
orderItemList(): OrderItemListExpression {
|
| 232 |
+
const path = expressionPath(this.path, 'orderItemList');
|
| 233 |
+
if (this.notLoaded) {
|
| 234 |
+
return new OrderItemListExpression([], this.root, path, false, this.notLoaded);
|
| 235 |
+
}
|
| 236 |
+
if (!this.value) return OrderItemListExpression.missing(this.root, path);
|
| 237 |
+
if (!this.value.isLoaded('orderItemList')) {
|
| 238 |
+
return new OrderItemListExpression([], this.root, path, false,
|
| 239 |
+
new TeaQLNotLoadedError(this.root, path, 'orderItemList'));
|
| 240 |
+
}
|
| 241 |
+
return new OrderItemListExpression(
|
| 242 |
+
this.value.orderItemList(), this.root, path,
|
| 243 |
+
);
|
| 244 |
+
}
|
| 245 |
+
|
| 246 |
+
paymentList(): PaymentListExpression {
|
| 247 |
+
const path = expressionPath(this.path, 'paymentList');
|
| 248 |
+
if (this.notLoaded) {
|
| 249 |
+
return new PaymentListExpression([], this.root, path, false, this.notLoaded);
|
| 250 |
+
}
|
| 251 |
+
if (!this.value) return PaymentListExpression.missing(this.root, path);
|
| 252 |
+
if (!this.value.isLoaded('paymentList')) {
|
| 253 |
+
return new PaymentListExpression([], this.root, path, false,
|
| 254 |
+
new TeaQLNotLoadedError(this.root, path, 'paymentList'));
|
| 255 |
+
}
|
| 256 |
+
return new PaymentListExpression(
|
| 257 |
+
this.value.paymentList(), this.root, path,
|
| 258 |
+
);
|
| 259 |
+
}
|
| 260 |
+
|
| 261 |
+
shipmentList(): ShipmentListExpression {
|
| 262 |
+
const path = expressionPath(this.path, 'shipmentList');
|
| 263 |
+
if (this.notLoaded) {
|
| 264 |
+
return new ShipmentListExpression([], this.root, path, false, this.notLoaded);
|
| 265 |
+
}
|
| 266 |
+
if (!this.value) return ShipmentListExpression.missing(this.root, path);
|
| 267 |
+
if (!this.value.isLoaded('shipmentList')) {
|
| 268 |
+
return new ShipmentListExpression([], this.root, path, false,
|
| 269 |
+
new TeaQLNotLoadedError(this.root, path, 'shipmentList'));
|
| 270 |
+
}
|
| 271 |
+
return new ShipmentListExpression(
|
| 272 |
+
this.value.shipmentList(), this.root, path,
|
| 273 |
+
);
|
| 274 |
+
}
|
| 275 |
+
}
|
| 276 |
+
|
| 277 |
+
export class OrderItemExpression {
|
| 278 |
+
constructor(
|
| 279 |
+
private readonly value: OrderItem | null | undefined,
|
| 280 |
+
private readonly root = 'OrderItem(null)',
|
| 281 |
+
private readonly path = '',
|
| 282 |
+
private readonly notLoaded?: TeaQLNotLoadedError,
|
| 283 |
+
) {}
|
| 284 |
+
|
| 285 |
+
eval(): OrderItem | null | undefined {
|
| 286 |
+
if (this.notLoaded) throw this.notLoaded;
|
| 287 |
+
return this.value;
|
| 288 |
+
}
|
| 289 |
+
|
| 290 |
+
id(): ValueExpression<string> {
|
| 291 |
+
if (this.notLoaded) return ValueExpression.notLoaded<string>(this.notLoaded);
|
| 292 |
+
if (!this.value) return ValueExpression.missing<string>();
|
| 293 |
+
const path = expressionPath(this.path, 'id');
|
| 294 |
+
if (!this.value.isLoaded('id')) {
|
| 295 |
+
return ValueExpression.notLoaded<string>(
|
| 296 |
+
new TeaQLNotLoadedError(this.root, path, 'id'),
|
| 297 |
+
);
|
| 298 |
+
}
|
| 299 |
+
return new ValueExpression<string>(this.value.id);
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
name(): ValueExpression<string> {
|
| 303 |
+
if (this.notLoaded) return ValueExpression.notLoaded<string>(this.notLoaded);
|
| 304 |
+
if (!this.value) return ValueExpression.missing<string>();
|
| 305 |
+
const path = expressionPath(this.path, 'name');
|
| 306 |
+
if (!this.value.isLoaded('name')) {
|
| 307 |
+
return ValueExpression.notLoaded<string>(
|
| 308 |
+
new TeaQLNotLoadedError(this.root, path, 'name'),
|
| 309 |
+
);
|
| 310 |
+
}
|
| 311 |
+
return new ValueExpression<string>(this.value.name);
|
| 312 |
+
}
|
| 313 |
+
|
| 314 |
+
version(): ValueExpression<number> {
|
| 315 |
+
if (this.notLoaded) return ValueExpression.notLoaded<number>(this.notLoaded);
|
| 316 |
+
if (!this.value) return ValueExpression.missing<number>();
|
| 317 |
+
const path = expressionPath(this.path, 'version');
|
| 318 |
+
if (!this.value.isLoaded('version')) {
|
| 319 |
+
return ValueExpression.notLoaded<number>(
|
| 320 |
+
new TeaQLNotLoadedError(this.root, path, 'version'),
|
| 321 |
+
);
|
| 322 |
+
}
|
| 323 |
+
return new ValueExpression<number>(this.value.version);
|
| 324 |
+
}
|
| 325 |
+
|
| 326 |
+
customerOrderId(): ValueExpression<string | number> {
|
| 327 |
+
if (this.notLoaded) return ValueExpression.notLoaded<string | number>(this.notLoaded);
|
| 328 |
+
if (!this.value) return ValueExpression.missing<string | number>();
|
| 329 |
+
const path = expressionPath(this.path, 'customerOrder');
|
| 330 |
+
if (!this.value.isLoaded('customerOrder')) {
|
| 331 |
+
return ValueExpression.notLoaded<string | number>(
|
| 332 |
+
new TeaQLNotLoadedError(this.root, path, 'customerOrder'),
|
| 333 |
+
);
|
| 334 |
+
}
|
| 335 |
+
const reference = this.value.customerOrder;
|
| 336 |
+
return new ValueExpression<string | number>(
|
| 337 |
+
reference instanceof CustomerOrder
|
| 338 |
+
? reference.id : reference as string | number | undefined,
|
| 339 |
+
);
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
customerOrder(): CustomerOrderExpression {
|
| 343 |
+
const path = expressionPath(this.path, 'customerOrder');
|
| 344 |
+
if (this.notLoaded) {
|
| 345 |
+
return new CustomerOrderExpression(undefined, this.root, path, this.notLoaded);
|
| 346 |
+
}
|
| 347 |
+
if (!this.value) return new CustomerOrderExpression(undefined, this.root, path);
|
| 348 |
+
if (!this.value.isLoaded('customerOrder')) {
|
| 349 |
+
return new CustomerOrderExpression(undefined, this.root, path,
|
| 350 |
+
new TeaQLNotLoadedError(this.root, path, 'customerOrder'));
|
| 351 |
+
}
|
| 352 |
+
const relation = this.value.customerOrder;
|
| 353 |
+
const target = relation == null
|
| 354 |
+
? undefined
|
| 355 |
+
: relation instanceof CustomerOrder
|
| 356 |
+
? relation
|
| 357 |
+
: CustomerOrder.fromRecord({ id: relation });
|
| 358 |
+
return new CustomerOrderExpression(target, this.root, path);
|
| 359 |
+
}
|
| 360 |
+
|
| 361 |
+
}
|
| 362 |
+
|
| 363 |
+
export class PaymentExpression {
|
| 364 |
+
constructor(
|
| 365 |
+
private readonly value: Payment | null | undefined,
|
| 366 |
+
private readonly root = 'Payment(null)',
|
| 367 |
+
private readonly path = '',
|
| 368 |
+
private readonly notLoaded?: TeaQLNotLoadedError,
|
| 369 |
+
) {}
|
| 370 |
+
|
| 371 |
+
eval(): Payment | null | undefined {
|
| 372 |
+
if (this.notLoaded) throw this.notLoaded;
|
| 373 |
+
return this.value;
|
| 374 |
+
}
|
| 375 |
+
|
| 376 |
+
id(): ValueExpression<string> {
|
| 377 |
+
if (this.notLoaded) return ValueExpression.notLoaded<string>(this.notLoaded);
|
| 378 |
+
if (!this.value) return ValueExpression.missing<string>();
|
| 379 |
+
const path = expressionPath(this.path, 'id');
|
| 380 |
+
if (!this.value.isLoaded('id')) {
|
| 381 |
+
return ValueExpression.notLoaded<string>(
|
| 382 |
+
new TeaQLNotLoadedError(this.root, path, 'id'),
|
| 383 |
+
);
|
| 384 |
+
}
|
| 385 |
+
return new ValueExpression<string>(this.value.id);
|
| 386 |
+
}
|
| 387 |
+
|
| 388 |
+
referenceCode(): ValueExpression<string> {
|
| 389 |
+
if (this.notLoaded) return ValueExpression.notLoaded<string>(this.notLoaded);
|
| 390 |
+
if (!this.value) return ValueExpression.missing<string>();
|
| 391 |
+
const path = expressionPath(this.path, 'referenceCode');
|
| 392 |
+
if (!this.value.isLoaded('referenceCode')) {
|
| 393 |
+
return ValueExpression.notLoaded<string>(
|
| 394 |
+
new TeaQLNotLoadedError(this.root, path, 'referenceCode'),
|
| 395 |
+
);
|
| 396 |
+
}
|
| 397 |
+
return new ValueExpression<string>(this.value.referenceCode);
|
| 398 |
+
}
|
| 399 |
+
|
| 400 |
+
version(): ValueExpression<number> {
|
| 401 |
+
if (this.notLoaded) return ValueExpression.notLoaded<number>(this.notLoaded);
|
| 402 |
+
if (!this.value) return ValueExpression.missing<number>();
|
| 403 |
+
const path = expressionPath(this.path, 'version');
|
| 404 |
+
if (!this.value.isLoaded('version')) {
|
| 405 |
+
return ValueExpression.notLoaded<number>(
|
| 406 |
+
new TeaQLNotLoadedError(this.root, path, 'version'),
|
| 407 |
+
);
|
| 408 |
+
}
|
| 409 |
+
return new ValueExpression<number>(this.value.version);
|
| 410 |
+
}
|
| 411 |
+
|
| 412 |
+
customerOrderId(): ValueExpression<string | number> {
|
| 413 |
+
if (this.notLoaded) return ValueExpression.notLoaded<string | number>(this.notLoaded);
|
| 414 |
+
if (!this.value) return ValueExpression.missing<string | number>();
|
| 415 |
+
const path = expressionPath(this.path, 'customerOrder');
|
| 416 |
+
if (!this.value.isLoaded('customerOrder')) {
|
| 417 |
+
return ValueExpression.notLoaded<string | number>(
|
| 418 |
+
new TeaQLNotLoadedError(this.root, path, 'customerOrder'),
|
| 419 |
+
);
|
| 420 |
+
}
|
| 421 |
+
const reference = this.value.customerOrder;
|
| 422 |
+
return new ValueExpression<string | number>(
|
| 423 |
+
reference instanceof CustomerOrder
|
| 424 |
+
? reference.id : reference as string | number | undefined,
|
| 425 |
+
);
|
| 426 |
+
}
|
| 427 |
+
|
| 428 |
+
customerOrder(): CustomerOrderExpression {
|
| 429 |
+
const path = expressionPath(this.path, 'customerOrder');
|
| 430 |
+
if (this.notLoaded) {
|
| 431 |
+
return new CustomerOrderExpression(undefined, this.root, path, this.notLoaded);
|
| 432 |
+
}
|
| 433 |
+
if (!this.value) return new CustomerOrderExpression(undefined, this.root, path);
|
| 434 |
+
if (!this.value.isLoaded('customerOrder')) {
|
| 435 |
+
return new CustomerOrderExpression(undefined, this.root, path,
|
| 436 |
+
new TeaQLNotLoadedError(this.root, path, 'customerOrder'));
|
| 437 |
+
}
|
| 438 |
+
const relation = this.value.customerOrder;
|
| 439 |
+
const target = relation == null
|
| 440 |
+
? undefined
|
| 441 |
+
: relation instanceof CustomerOrder
|
| 442 |
+
? relation
|
| 443 |
+
: CustomerOrder.fromRecord({ id: relation });
|
| 444 |
+
return new CustomerOrderExpression(target, this.root, path);
|
| 445 |
+
}
|
| 446 |
+
|
| 447 |
+
paymentAttemptList(): PaymentAttemptListExpression {
|
| 448 |
+
const path = expressionPath(this.path, 'paymentAttemptList');
|
| 449 |
+
if (this.notLoaded) {
|
| 450 |
+
return new PaymentAttemptListExpression([], this.root, path, false, this.notLoaded);
|
| 451 |
+
}
|
| 452 |
+
if (!this.value) return PaymentAttemptListExpression.missing(this.root, path);
|
| 453 |
+
if (!this.value.isLoaded('paymentAttemptList')) {
|
| 454 |
+
return new PaymentAttemptListExpression([], this.root, path, false,
|
| 455 |
+
new TeaQLNotLoadedError(this.root, path, 'paymentAttemptList'));
|
| 456 |
+
}
|
| 457 |
+
return new PaymentAttemptListExpression(
|
| 458 |
+
this.value.paymentAttemptList(), this.root, path,
|
| 459 |
+
);
|
| 460 |
+
}
|
| 461 |
+
}
|
| 462 |
+
|
| 463 |
+
export class PaymentAttemptExpression {
|
| 464 |
+
constructor(
|
| 465 |
+
private readonly value: PaymentAttempt | null | undefined,
|
| 466 |
+
private readonly root = 'PaymentAttempt(null)',
|
| 467 |
+
private readonly path = '',
|
| 468 |
+
private readonly notLoaded?: TeaQLNotLoadedError,
|
| 469 |
+
) {}
|
| 470 |
+
|
| 471 |
+
eval(): PaymentAttempt | null | undefined {
|
| 472 |
+
if (this.notLoaded) throw this.notLoaded;
|
| 473 |
+
return this.value;
|
| 474 |
+
}
|
| 475 |
+
|
| 476 |
+
id(): ValueExpression<string> {
|
| 477 |
+
if (this.notLoaded) return ValueExpression.notLoaded<string>(this.notLoaded);
|
| 478 |
+
if (!this.value) return ValueExpression.missing<string>();
|
| 479 |
+
const path = expressionPath(this.path, 'id');
|
| 480 |
+
if (!this.value.isLoaded('id')) {
|
| 481 |
+
return ValueExpression.notLoaded<string>(
|
| 482 |
+
new TeaQLNotLoadedError(this.root, path, 'id'),
|
| 483 |
+
);
|
| 484 |
+
}
|
| 485 |
+
return new ValueExpression<string>(this.value.id);
|
| 486 |
+
}
|
| 487 |
+
|
| 488 |
+
referenceCode(): ValueExpression<string> {
|
| 489 |
+
if (this.notLoaded) return ValueExpression.notLoaded<string>(this.notLoaded);
|
| 490 |
+
if (!this.value) return ValueExpression.missing<string>();
|
| 491 |
+
const path = expressionPath(this.path, 'referenceCode');
|
| 492 |
+
if (!this.value.isLoaded('referenceCode')) {
|
| 493 |
+
return ValueExpression.notLoaded<string>(
|
| 494 |
+
new TeaQLNotLoadedError(this.root, path, 'referenceCode'),
|
| 495 |
+
);
|
| 496 |
+
}
|
| 497 |
+
return new ValueExpression<string>(this.value.referenceCode);
|
| 498 |
+
}
|
| 499 |
+
|
| 500 |
+
version(): ValueExpression<number> {
|
| 501 |
+
if (this.notLoaded) return ValueExpression.notLoaded<number>(this.notLoaded);
|
| 502 |
+
if (!this.value) return ValueExpression.missing<number>();
|
| 503 |
+
const path = expressionPath(this.path, 'version');
|
| 504 |
+
if (!this.value.isLoaded('version')) {
|
| 505 |
+
return ValueExpression.notLoaded<number>(
|
| 506 |
+
new TeaQLNotLoadedError(this.root, path, 'version'),
|
| 507 |
+
);
|
| 508 |
+
}
|
| 509 |
+
return new ValueExpression<number>(this.value.version);
|
| 510 |
+
}
|
| 511 |
+
|
| 512 |
+
paymentId(): ValueExpression<string | number> {
|
| 513 |
+
if (this.notLoaded) return ValueExpression.notLoaded<string | number>(this.notLoaded);
|
| 514 |
+
if (!this.value) return ValueExpression.missing<string | number>();
|
| 515 |
+
const path = expressionPath(this.path, 'payment');
|
| 516 |
+
if (!this.value.isLoaded('payment')) {
|
| 517 |
+
return ValueExpression.notLoaded<string | number>(
|
| 518 |
+
new TeaQLNotLoadedError(this.root, path, 'payment'),
|
| 519 |
+
);
|
| 520 |
+
}
|
| 521 |
+
const reference = this.value.payment;
|
| 522 |
+
return new ValueExpression<string | number>(
|
| 523 |
+
reference instanceof Payment
|
| 524 |
+
? reference.id : reference as string | number | undefined,
|
| 525 |
+
);
|
| 526 |
+
}
|
| 527 |
+
|
| 528 |
+
payment(): PaymentExpression {
|
| 529 |
+
const path = expressionPath(this.path, 'payment');
|
| 530 |
+
if (this.notLoaded) {
|
| 531 |
+
return new PaymentExpression(undefined, this.root, path, this.notLoaded);
|
| 532 |
+
}
|
| 533 |
+
if (!this.value) return new PaymentExpression(undefined, this.root, path);
|
| 534 |
+
if (!this.value.isLoaded('payment')) {
|
| 535 |
+
return new PaymentExpression(undefined, this.root, path,
|
| 536 |
+
new TeaQLNotLoadedError(this.root, path, 'payment'));
|
| 537 |
+
}
|
| 538 |
+
const relation = this.value.payment;
|
| 539 |
+
const target = relation == null
|
| 540 |
+
? undefined
|
| 541 |
+
: relation instanceof Payment
|
| 542 |
+
? relation
|
| 543 |
+
: Payment.fromRecord({ id: relation });
|
| 544 |
+
return new PaymentExpression(target, this.root, path);
|
| 545 |
+
}
|
| 546 |
+
|
| 547 |
+
}
|
| 548 |
+
|
| 549 |
+
export class ShipmentExpression {
|
| 550 |
+
constructor(
|
| 551 |
+
private readonly value: Shipment | null | undefined,
|
| 552 |
+
private readonly root = 'Shipment(null)',
|
| 553 |
+
private readonly path = '',
|
| 554 |
+
private readonly notLoaded?: TeaQLNotLoadedError,
|
| 555 |
+
) {}
|
| 556 |
+
|
| 557 |
+
eval(): Shipment | null | undefined {
|
| 558 |
+
if (this.notLoaded) throw this.notLoaded;
|
| 559 |
+
return this.value;
|
| 560 |
+
}
|
| 561 |
+
|
| 562 |
+
id(): ValueExpression<string> {
|
| 563 |
+
if (this.notLoaded) return ValueExpression.notLoaded<string>(this.notLoaded);
|
| 564 |
+
if (!this.value) return ValueExpression.missing<string>();
|
| 565 |
+
const path = expressionPath(this.path, 'id');
|
| 566 |
+
if (!this.value.isLoaded('id')) {
|
| 567 |
+
return ValueExpression.notLoaded<string>(
|
| 568 |
+
new TeaQLNotLoadedError(this.root, path, 'id'),
|
| 569 |
+
);
|
| 570 |
+
}
|
| 571 |
+
return new ValueExpression<string>(this.value.id);
|
| 572 |
+
}
|
| 573 |
+
|
| 574 |
+
referenceCode(): ValueExpression<string> {
|
| 575 |
+
if (this.notLoaded) return ValueExpression.notLoaded<string>(this.notLoaded);
|
| 576 |
+
if (!this.value) return ValueExpression.missing<string>();
|
| 577 |
+
const path = expressionPath(this.path, 'referenceCode');
|
| 578 |
+
if (!this.value.isLoaded('referenceCode')) {
|
| 579 |
+
return ValueExpression.notLoaded<string>(
|
| 580 |
+
new TeaQLNotLoadedError(this.root, path, 'referenceCode'),
|
| 581 |
+
);
|
| 582 |
+
}
|
| 583 |
+
return new ValueExpression<string>(this.value.referenceCode);
|
| 584 |
+
}
|
| 585 |
+
|
| 586 |
+
version(): ValueExpression<number> {
|
| 587 |
+
if (this.notLoaded) return ValueExpression.notLoaded<number>(this.notLoaded);
|
| 588 |
+
if (!this.value) return ValueExpression.missing<number>();
|
| 589 |
+
const path = expressionPath(this.path, 'version');
|
| 590 |
+
if (!this.value.isLoaded('version')) {
|
| 591 |
+
return ValueExpression.notLoaded<number>(
|
| 592 |
+
new TeaQLNotLoadedError(this.root, path, 'version'),
|
| 593 |
+
);
|
| 594 |
+
}
|
| 595 |
+
return new ValueExpression<number>(this.value.version);
|
| 596 |
+
}
|
| 597 |
+
|
| 598 |
+
customerOrderId(): ValueExpression<string | number> {
|
| 599 |
+
if (this.notLoaded) return ValueExpression.notLoaded<string | number>(this.notLoaded);
|
| 600 |
+
if (!this.value) return ValueExpression.missing<string | number>();
|
| 601 |
+
const path = expressionPath(this.path, 'customerOrder');
|
| 602 |
+
if (!this.value.isLoaded('customerOrder')) {
|
| 603 |
+
return ValueExpression.notLoaded<string | number>(
|
| 604 |
+
new TeaQLNotLoadedError(this.root, path, 'customerOrder'),
|
| 605 |
+
);
|
| 606 |
+
}
|
| 607 |
+
const reference = this.value.customerOrder;
|
| 608 |
+
return new ValueExpression<string | number>(
|
| 609 |
+
reference instanceof CustomerOrder
|
| 610 |
+
? reference.id : reference as string | number | undefined,
|
| 611 |
+
);
|
| 612 |
+
}
|
| 613 |
+
|
| 614 |
+
customerOrder(): CustomerOrderExpression {
|
| 615 |
+
const path = expressionPath(this.path, 'customerOrder');
|
| 616 |
+
if (this.notLoaded) {
|
| 617 |
+
return new CustomerOrderExpression(undefined, this.root, path, this.notLoaded);
|
| 618 |
+
}
|
| 619 |
+
if (!this.value) return new CustomerOrderExpression(undefined, this.root, path);
|
| 620 |
+
if (!this.value.isLoaded('customerOrder')) {
|
| 621 |
+
return new CustomerOrderExpression(undefined, this.root, path,
|
| 622 |
+
new TeaQLNotLoadedError(this.root, path, 'customerOrder'));
|
| 623 |
+
}
|
| 624 |
+
const relation = this.value.customerOrder;
|
| 625 |
+
const target = relation == null
|
| 626 |
+
? undefined
|
| 627 |
+
: relation instanceof CustomerOrder
|
| 628 |
+
? relation
|
| 629 |
+
: CustomerOrder.fromRecord({ id: relation });
|
| 630 |
+
return new CustomerOrderExpression(target, this.root, path);
|
| 631 |
+
}
|
| 632 |
+
|
| 633 |
+
}
|
| 634 |
+
|
| 635 |
+
export class PlatformListExpression {
|
| 636 |
+
constructor(
|
| 637 |
+
private readonly items: readonly Platform[],
|
| 638 |
+
private readonly root = 'Platform(null)',
|
| 639 |
+
private readonly path = '',
|
| 640 |
+
private readonly present = true,
|
| 641 |
+
private readonly notLoaded?: TeaQLNotLoadedError,
|
| 642 |
+
) {}
|
| 643 |
+
|
| 644 |
+
static missing(root?: string, path = ''): PlatformListExpression {
|
| 645 |
+
return new PlatformListExpression([], root, path, false);
|
| 646 |
+
}
|
| 647 |
+
|
| 648 |
+
size(): ValueExpression<number> {
|
| 649 |
+
if (this.notLoaded) return ValueExpression.notLoaded<number>(this.notLoaded);
|
| 650 |
+
return this.present
|
| 651 |
+
? new ValueExpression<number>(this.items.length)
|
| 652 |
+
: ValueExpression.missing<number>();
|
| 653 |
+
}
|
| 654 |
+
|
| 655 |
+
first(): PlatformExpression {
|
| 656 |
+
return this.get(0);
|
| 657 |
+
}
|
| 658 |
+
|
| 659 |
+
get(index: number): PlatformExpression {
|
| 660 |
+
const itemPath = expressionPath(this.path, `get(${index})`);
|
| 661 |
+
if (this.notLoaded) {
|
| 662 |
+
return new PlatformExpression(undefined, this.root, itemPath, this.notLoaded);
|
| 663 |
+
}
|
| 664 |
+
return !this.present || index < 0 || index >= this.items.length
|
| 665 |
+
? new PlatformExpression(undefined, this.root, itemPath)
|
| 666 |
+
: new PlatformExpression(this.items[index], this.root, itemPath);
|
| 667 |
+
}
|
| 668 |
+
}
|
| 669 |
+
|
| 670 |
+
export class CustomerOrderListExpression {
|
| 671 |
+
constructor(
|
| 672 |
+
private readonly items: readonly CustomerOrder[],
|
| 673 |
+
private readonly root = 'CustomerOrder(null)',
|
| 674 |
+
private readonly path = '',
|
| 675 |
+
private readonly present = true,
|
| 676 |
+
private readonly notLoaded?: TeaQLNotLoadedError,
|
| 677 |
+
) {}
|
| 678 |
+
|
| 679 |
+
static missing(root?: string, path = ''): CustomerOrderListExpression {
|
| 680 |
+
return new CustomerOrderListExpression([], root, path, false);
|
| 681 |
+
}
|
| 682 |
+
|
| 683 |
+
size(): ValueExpression<number> {
|
| 684 |
+
if (this.notLoaded) return ValueExpression.notLoaded<number>(this.notLoaded);
|
| 685 |
+
return this.present
|
| 686 |
+
? new ValueExpression<number>(this.items.length)
|
| 687 |
+
: ValueExpression.missing<number>();
|
| 688 |
+
}
|
| 689 |
+
|
| 690 |
+
first(): CustomerOrderExpression {
|
| 691 |
+
return this.get(0);
|
| 692 |
+
}
|
| 693 |
+
|
| 694 |
+
get(index: number): CustomerOrderExpression {
|
| 695 |
+
const itemPath = expressionPath(this.path, `get(${index})`);
|
| 696 |
+
if (this.notLoaded) {
|
| 697 |
+
return new CustomerOrderExpression(undefined, this.root, itemPath, this.notLoaded);
|
| 698 |
+
}
|
| 699 |
+
return !this.present || index < 0 || index >= this.items.length
|
| 700 |
+
? new CustomerOrderExpression(undefined, this.root, itemPath)
|
| 701 |
+
: new CustomerOrderExpression(this.items[index], this.root, itemPath);
|
| 702 |
+
}
|
| 703 |
+
}
|
| 704 |
+
|
| 705 |
+
export class OrderItemListExpression {
|
| 706 |
+
constructor(
|
| 707 |
+
private readonly items: readonly OrderItem[],
|
| 708 |
+
private readonly root = 'OrderItem(null)',
|
| 709 |
+
private readonly path = '',
|
| 710 |
+
private readonly present = true,
|
| 711 |
+
private readonly notLoaded?: TeaQLNotLoadedError,
|
| 712 |
+
) {}
|
| 713 |
+
|
| 714 |
+
static missing(root?: string, path = ''): OrderItemListExpression {
|
| 715 |
+
return new OrderItemListExpression([], root, path, false);
|
| 716 |
+
}
|
| 717 |
+
|
| 718 |
+
size(): ValueExpression<number> {
|
| 719 |
+
if (this.notLoaded) return ValueExpression.notLoaded<number>(this.notLoaded);
|
| 720 |
+
return this.present
|
| 721 |
+
? new ValueExpression<number>(this.items.length)
|
| 722 |
+
: ValueExpression.missing<number>();
|
| 723 |
+
}
|
| 724 |
+
|
| 725 |
+
first(): OrderItemExpression {
|
| 726 |
+
return this.get(0);
|
| 727 |
+
}
|
| 728 |
+
|
| 729 |
+
get(index: number): OrderItemExpression {
|
| 730 |
+
const itemPath = expressionPath(this.path, `get(${index})`);
|
| 731 |
+
if (this.notLoaded) {
|
| 732 |
+
return new OrderItemExpression(undefined, this.root, itemPath, this.notLoaded);
|
| 733 |
+
}
|
| 734 |
+
return !this.present || index < 0 || index >= this.items.length
|
| 735 |
+
? new OrderItemExpression(undefined, this.root, itemPath)
|
| 736 |
+
: new OrderItemExpression(this.items[index], this.root, itemPath);
|
| 737 |
+
}
|
| 738 |
+
}
|
| 739 |
+
|
| 740 |
+
export class PaymentListExpression {
|
| 741 |
+
constructor(
|
| 742 |
+
private readonly items: readonly Payment[],
|
| 743 |
+
private readonly root = 'Payment(null)',
|
| 744 |
+
private readonly path = '',
|
| 745 |
+
private readonly present = true,
|
| 746 |
+
private readonly notLoaded?: TeaQLNotLoadedError,
|
| 747 |
+
) {}
|
| 748 |
+
|
| 749 |
+
static missing(root?: string, path = ''): PaymentListExpression {
|
| 750 |
+
return new PaymentListExpression([], root, path, false);
|
| 751 |
+
}
|
| 752 |
+
|
| 753 |
+
size(): ValueExpression<number> {
|
| 754 |
+
if (this.notLoaded) return ValueExpression.notLoaded<number>(this.notLoaded);
|
| 755 |
+
return this.present
|
| 756 |
+
? new ValueExpression<number>(this.items.length)
|
| 757 |
+
: ValueExpression.missing<number>();
|
| 758 |
+
}
|
| 759 |
+
|
| 760 |
+
first(): PaymentExpression {
|
| 761 |
+
return this.get(0);
|
| 762 |
+
}
|
| 763 |
+
|
| 764 |
+
get(index: number): PaymentExpression {
|
| 765 |
+
const itemPath = expressionPath(this.path, `get(${index})`);
|
| 766 |
+
if (this.notLoaded) {
|
| 767 |
+
return new PaymentExpression(undefined, this.root, itemPath, this.notLoaded);
|
| 768 |
+
}
|
| 769 |
+
return !this.present || index < 0 || index >= this.items.length
|
| 770 |
+
? new PaymentExpression(undefined, this.root, itemPath)
|
| 771 |
+
: new PaymentExpression(this.items[index], this.root, itemPath);
|
| 772 |
+
}
|
| 773 |
+
}
|
| 774 |
+
|
| 775 |
+
export class PaymentAttemptListExpression {
|
| 776 |
+
constructor(
|
| 777 |
+
private readonly items: readonly PaymentAttempt[],
|
| 778 |
+
private readonly root = 'PaymentAttempt(null)',
|
| 779 |
+
private readonly path = '',
|
| 780 |
+
private readonly present = true,
|
| 781 |
+
private readonly notLoaded?: TeaQLNotLoadedError,
|
| 782 |
+
) {}
|
| 783 |
+
|
| 784 |
+
static missing(root?: string, path = ''): PaymentAttemptListExpression {
|
| 785 |
+
return new PaymentAttemptListExpression([], root, path, false);
|
| 786 |
+
}
|
| 787 |
+
|
| 788 |
+
size(): ValueExpression<number> {
|
| 789 |
+
if (this.notLoaded) return ValueExpression.notLoaded<number>(this.notLoaded);
|
| 790 |
+
return this.present
|
| 791 |
+
? new ValueExpression<number>(this.items.length)
|
| 792 |
+
: ValueExpression.missing<number>();
|
| 793 |
+
}
|
| 794 |
+
|
| 795 |
+
first(): PaymentAttemptExpression {
|
| 796 |
+
return this.get(0);
|
| 797 |
+
}
|
| 798 |
+
|
| 799 |
+
get(index: number): PaymentAttemptExpression {
|
| 800 |
+
const itemPath = expressionPath(this.path, `get(${index})`);
|
| 801 |
+
if (this.notLoaded) {
|
| 802 |
+
return new PaymentAttemptExpression(undefined, this.root, itemPath, this.notLoaded);
|
| 803 |
+
}
|
| 804 |
+
return !this.present || index < 0 || index >= this.items.length
|
| 805 |
+
? new PaymentAttemptExpression(undefined, this.root, itemPath)
|
| 806 |
+
: new PaymentAttemptExpression(this.items[index], this.root, itemPath);
|
| 807 |
+
}
|
| 808 |
+
}
|
| 809 |
+
|
| 810 |
+
export class ShipmentListExpression {
|
| 811 |
+
constructor(
|
| 812 |
+
private readonly items: readonly Shipment[],
|
| 813 |
+
private readonly root = 'Shipment(null)',
|
| 814 |
+
private readonly path = '',
|
| 815 |
+
private readonly present = true,
|
| 816 |
+
private readonly notLoaded?: TeaQLNotLoadedError,
|
| 817 |
+
) {}
|
| 818 |
+
|
| 819 |
+
static missing(root?: string, path = ''): ShipmentListExpression {
|
| 820 |
+
return new ShipmentListExpression([], root, path, false);
|
| 821 |
+
}
|
| 822 |
+
|
| 823 |
+
size(): ValueExpression<number> {
|
| 824 |
+
if (this.notLoaded) return ValueExpression.notLoaded<number>(this.notLoaded);
|
| 825 |
+
return this.present
|
| 826 |
+
? new ValueExpression<number>(this.items.length)
|
| 827 |
+
: ValueExpression.missing<number>();
|
| 828 |
+
}
|
| 829 |
+
|
| 830 |
+
first(): ShipmentExpression {
|
| 831 |
+
return this.get(0);
|
| 832 |
+
}
|
| 833 |
+
|
| 834 |
+
get(index: number): ShipmentExpression {
|
| 835 |
+
const itemPath = expressionPath(this.path, `get(${index})`);
|
| 836 |
+
if (this.notLoaded) {
|
| 837 |
+
return new ShipmentExpression(undefined, this.root, itemPath, this.notLoaded);
|
| 838 |
+
}
|
| 839 |
+
return !this.present || index < 0 || index >= this.items.length
|
| 840 |
+
? new ShipmentExpression(undefined, this.root, itemPath)
|
| 841 |
+
: new ShipmentExpression(this.items[index], this.root, itemPath);
|
| 842 |
+
}
|
| 843 |
+
}
|
| 844 |
+
|
| 845 |
+
export class E {
|
| 846 |
+
static platform(
|
| 847 |
+
value: Platform | null | undefined,
|
| 848 |
+
): PlatformExpression {
|
| 849 |
+
return new PlatformExpression(
|
| 850 |
+
value, `Platform(id=${value?.id ?? 'null'})`,
|
| 851 |
+
);
|
| 852 |
+
}
|
| 853 |
+
|
| 854 |
+
static customerOrder(
|
| 855 |
+
value: CustomerOrder | null | undefined,
|
| 856 |
+
): CustomerOrderExpression {
|
| 857 |
+
return new CustomerOrderExpression(
|
| 858 |
+
value, `CustomerOrder(id=${value?.id ?? 'null'})`,
|
| 859 |
+
);
|
| 860 |
+
}
|
| 861 |
+
|
| 862 |
+
static orderItem(
|
| 863 |
+
value: OrderItem | null | undefined,
|
| 864 |
+
): OrderItemExpression {
|
| 865 |
+
return new OrderItemExpression(
|
| 866 |
+
value, `OrderItem(id=${value?.id ?? 'null'})`,
|
| 867 |
+
);
|
| 868 |
+
}
|
| 869 |
+
|
| 870 |
+
static payment(
|
| 871 |
+
value: Payment | null | undefined,
|
| 872 |
+
): PaymentExpression {
|
| 873 |
+
return new PaymentExpression(
|
| 874 |
+
value, `Payment(id=${value?.id ?? 'null'})`,
|
| 875 |
+
);
|
| 876 |
+
}
|
| 877 |
+
|
| 878 |
+
static paymentAttempt(
|
| 879 |
+
value: PaymentAttempt | null | undefined,
|
| 880 |
+
): PaymentAttemptExpression {
|
| 881 |
+
return new PaymentAttemptExpression(
|
| 882 |
+
value, `PaymentAttempt(id=${value?.id ?? 'null'})`,
|
| 883 |
+
);
|
| 884 |
+
}
|
| 885 |
+
|
| 886 |
+
static shipment(
|
| 887 |
+
value: Shipment | null | undefined,
|
| 888 |
+
): ShipmentExpression {
|
| 889 |
+
return new ShipmentExpression(
|
| 890 |
+
value, `Shipment(id=${value?.id ?? 'null'})`,
|
| 891 |
+
);
|
| 892 |
+
}
|
| 893 |
+
}
|
source/teaql-ts/examples/trace-chain/lib/src/generated/Q.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { TeaQLClient } from '../teaql-ts';
|
| 2 |
+
import { PlatformRequest } from './requests/PlatformRequest';
|
| 3 |
+
import { CustomerOrderRequest } from './requests/CustomerOrderRequest';
|
| 4 |
+
import { OrderItemRequest } from './requests/OrderItemRequest';
|
| 5 |
+
import { PaymentRequest } from './requests/PaymentRequest';
|
| 6 |
+
import { PaymentAttemptRequest } from './requests/PaymentAttemptRequest';
|
| 7 |
+
import { ShipmentRequest } from './requests/ShipmentRequest';
|
| 8 |
+
|
| 9 |
+
export class Q {
|
| 10 |
+
static platforms(): PlatformRequest {
|
| 11 |
+
return new PlatformRequest(false);
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
static platformsWithMinimalFields(): PlatformRequest {
|
| 15 |
+
return new PlatformRequest(true);
|
| 16 |
+
}
|
| 17 |
+
static customerOrders(): CustomerOrderRequest {
|
| 18 |
+
return new CustomerOrderRequest(false);
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
static customerOrdersWithMinimalFields(): CustomerOrderRequest {
|
| 22 |
+
return new CustomerOrderRequest(true);
|
| 23 |
+
}
|
| 24 |
+
static orderItems(): OrderItemRequest {
|
| 25 |
+
return new OrderItemRequest(false);
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
static orderItemsWithMinimalFields(): OrderItemRequest {
|
| 29 |
+
return new OrderItemRequest(true);
|
| 30 |
+
}
|
| 31 |
+
static payments(): PaymentRequest {
|
| 32 |
+
return new PaymentRequest(false);
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
static paymentsWithMinimalFields(): PaymentRequest {
|
| 36 |
+
return new PaymentRequest(true);
|
| 37 |
+
}
|
| 38 |
+
static paymentAttempts(): PaymentAttemptRequest {
|
| 39 |
+
return new PaymentAttemptRequest(false);
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
static paymentAttemptsWithMinimalFields(): PaymentAttemptRequest {
|
| 43 |
+
return new PaymentAttemptRequest(true);
|
| 44 |
+
}
|
| 45 |
+
static shipments(): ShipmentRequest {
|
| 46 |
+
return new ShipmentRequest(false);
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
static shipmentsWithMinimalFields(): ShipmentRequest {
|
| 50 |
+
return new ShipmentRequest(true);
|
| 51 |
+
}
|
| 52 |
+
}
|
source/teaql-ts/examples/trace-chain/lib/src/generated/models/CustomerOrder.ts
ADDED
|
@@ -0,0 +1,407 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { CheckException, EntityKey, EntityRoot, GraphMutationSession, LoadedScalarSnapshot, MutationIntent, MutationTraceScope, ObjectLocation, SmartList, TeaQLDataService, UserContext } from '../../teaql-ts';
|
| 2 |
+
import { Platform } from './Platform';
|
| 3 |
+
import { OrderItem } from './OrderItem';
|
| 4 |
+
import { Payment } from './Payment';
|
| 5 |
+
import { Shipment } from './Shipment';
|
| 6 |
+
|
| 7 |
+
export class CustomerOrder {
|
| 8 |
+
private static teaqlTemporaryId = 0;
|
| 9 |
+
id?: string;
|
| 10 |
+
platform?: Platform | string;
|
| 11 |
+
orderNumber?: string;
|
| 12 |
+
description?: string;
|
| 13 |
+
version?: number;
|
| 14 |
+
|
| 15 |
+
constructor(init?: Partial<CustomerOrder>) {
|
| 16 |
+
Object.defineProperty(this, "_action", { value: init && init.id ? "Update" : "Create", writable: true, enumerable: false });
|
| 17 |
+
Object.defineProperty(this, "_comment", { value: undefined, writable: true, enumerable: false });
|
| 18 |
+
Object.defineProperty(this, "_fullyLoaded", { value: !init || !init.id, writable: true, enumerable: false });
|
| 19 |
+
Object.defineProperty(this, "_loadedFields", { value: new Set(Object.keys(init || {})), writable: true, enumerable: false });
|
| 20 |
+
Object.defineProperty(this, "_root", { value: new EntityRoot(), writable: true, enumerable: false });
|
| 21 |
+
Object.defineProperty(this, "_ledgerId", { value: init?.id ?? --CustomerOrder.teaqlTemporaryId, writable: true, enumerable: false });
|
| 22 |
+
Object.defineProperty(this, "_orderItemList", { value: init?.id ? SmartList.empty() : new SmartList(), writable: true, enumerable: false });
|
| 23 |
+
Object.defineProperty(this, "_paymentList", { value: init?.id ? SmartList.empty() : new SmartList(), writable: true, enumerable: false });
|
| 24 |
+
Object.defineProperty(this, "_shipmentList", { value: init?.id ? SmartList.empty() : new SmartList(), writable: true, enumerable: false });
|
| 25 |
+
if (init) {
|
| 26 |
+
const fields: Record<string, unknown> = { ...(init as Record<string, unknown>) };
|
| 27 |
+
delete fields["orderItemList"];
|
| 28 |
+
delete fields["paymentList"];
|
| 29 |
+
delete fields["shipmentList"];
|
| 30 |
+
Object.assign(this, fields);
|
| 31 |
+
if ((init as any).platform && typeof (init as any).platform === "object") {
|
| 32 |
+
this.platform = (init as any).platform instanceof Platform
|
| 33 |
+
? (init as any).platform
|
| 34 |
+
: Platform.fromRecord((init as any).platform);
|
| 35 |
+
this.markLoaded("platform");
|
| 36 |
+
}
|
| 37 |
+
if (Array.isArray((init as any).orderItemList)) {
|
| 38 |
+
const selected = (init as any).orderItemList;
|
| 39 |
+
(this as any)._orderItemList = new SmartList(selected.map(
|
| 40 |
+
(child: unknown) => child instanceof OrderItem
|
| 41 |
+
? child
|
| 42 |
+
: OrderItem.fromRecord(child as Record<string, unknown>),
|
| 43 |
+
), { totalCount: selected.totalCount, aggregations: selected.aggregations,
|
| 44 |
+
summary: selected.summary, facets: selected.facets, isLoaded: selected.isLoaded ?? true });
|
| 45 |
+
this.markLoaded("orderItemList");
|
| 46 |
+
}
|
| 47 |
+
if (Array.isArray((init as any).paymentList)) {
|
| 48 |
+
const selected = (init as any).paymentList;
|
| 49 |
+
(this as any)._paymentList = new SmartList(selected.map(
|
| 50 |
+
(child: unknown) => child instanceof Payment
|
| 51 |
+
? child
|
| 52 |
+
: Payment.fromRecord(child as Record<string, unknown>),
|
| 53 |
+
), { totalCount: selected.totalCount, aggregations: selected.aggregations,
|
| 54 |
+
summary: selected.summary, facets: selected.facets, isLoaded: selected.isLoaded ?? true });
|
| 55 |
+
this.markLoaded("paymentList");
|
| 56 |
+
}
|
| 57 |
+
if (Array.isArray((init as any).shipmentList)) {
|
| 58 |
+
const selected = (init as any).shipmentList;
|
| 59 |
+
(this as any)._shipmentList = new SmartList(selected.map(
|
| 60 |
+
(child: unknown) => child instanceof Shipment
|
| 61 |
+
? child
|
| 62 |
+
: Shipment.fromRecord(child as Record<string, unknown>),
|
| 63 |
+
), { totalCount: selected.totalCount, aggregations: selected.aggregations,
|
| 64 |
+
summary: selected.summary, facets: selected.facets, isLoaded: selected.isLoaded ?? true });
|
| 65 |
+
this.markLoaded("shipmentList");
|
| 66 |
+
}
|
| 67 |
+
}
|
| 68 |
+
const key = this.teaqlEntityKey();
|
| 69 |
+
if ((this as any)._action === "Create") (this as any)._root.markAsNew(key);
|
| 70 |
+
else if ((this as any).version !== undefined) (this as any)._root.setOriginalVersion(key, Number((this as any).version));
|
| 71 |
+
LoadedScalarSnapshot.captureFor(this, this.teaqlMutationPayload());
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
private teaqlEntityKey(): EntityKey { return { entity: "CustomerOrder", id: (this as any)._ledgerId }; }
|
| 75 |
+
private teaqlAttachRoot(root: EntityRoot): this {
|
| 76 |
+
if ((this as any)._root !== root) {
|
| 77 |
+
root.mergeEntityFrom((this as any)._root, this.teaqlEntityKey());
|
| 78 |
+
(this as any)._root = root;
|
| 79 |
+
}
|
| 80 |
+
for (const child of (this as any)._orderItemList) child.teaqlAttachRoot(root);
|
| 81 |
+
for (const child of (this as any)._paymentList) child.teaqlAttachRoot(root);
|
| 82 |
+
for (const child of (this as any)._shipmentList) child.teaqlAttachRoot(root);
|
| 83 |
+
return this;
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
static fromRecord(record: Record<string, unknown>, root?: EntityRoot): CustomerOrder {
|
| 87 |
+
const entity = new CustomerOrder(record as Partial<CustomerOrder>);
|
| 88 |
+
return root ? entity.teaqlAttachRoot(root) : entity;
|
| 89 |
+
}
|
| 90 |
+
|
| 91 |
+
isLoaded(field: string): boolean {
|
| 92 |
+
return (this as any)._fullyLoaded || (this as any)._loadedFields.has(field);
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
markLoaded(...fields: string[]): this {
|
| 96 |
+
for (const field of fields) (this as any)._loadedFields.add(field);
|
| 97 |
+
return this;
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
markLoadedOnly(...fields: string[]): this {
|
| 101 |
+
(this as any)._fullyLoaded = false;
|
| 102 |
+
(this as any)._loadedFields = new Set(fields);
|
| 103 |
+
return this;
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
static refer(id: string | number): CustomerOrder {
|
| 107 |
+
return new CustomerOrder({ id: String(id) } as Partial<CustomerOrder>);
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
/** @internal Generated Runtime Module fixed-ID construction capability. */
|
| 111 |
+
static teaqlBootstrapNew(id: string | number): CustomerOrder {
|
| 112 |
+
return new CustomerOrder().updateId(String(id));
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
markForDeletion(): this {
|
| 116 |
+
(this as any)._action = "Delete";
|
| 117 |
+
(this as any)._root.markAsDeleted(this.teaqlEntityKey());
|
| 118 |
+
return this;
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
auditAs(comment: string): this {
|
| 122 |
+
new MutationIntent(comment);
|
| 123 |
+
(this as any)._comment = comment;
|
| 124 |
+
return this;
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
async save(context: UserContext): Promise<CustomerOrder> {
|
| 128 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 129 |
+
return service.executeGraphSave(new MutationIntent((this as any)._comment), async (graph) => {
|
| 130 |
+
this.teaqlPreflightGraph(context, service, graph);
|
| 131 |
+
return this.teaqlSaveWithinGraph(context, service, graph);
|
| 132 |
+
});
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
/** @internal Validates and fixes the complete graph before its first mutation. */
|
| 136 |
+
teaqlPreflightGraph(context: UserContext, service: TeaQLDataService, graph: GraphMutationSession, parent?: MutationTraceScope): void {
|
| 137 |
+
if (!parent) new MutationIntent((this as any)._comment);
|
| 138 |
+
const action = (this as any)._action;
|
| 139 |
+
const pending = action !== "Update" || (this as any)._root.hasPending(this.teaqlEntityKey());
|
| 140 |
+
if (action === "Update" && pending) {
|
| 141 |
+
const notLoaded = [{ member: "id", canonical: "id" }, { member: "platform", canonical: "platform" }, { member: "orderNumber", canonical: "order_number" }, { member: "description", canonical: "description" }, { member: "version", canonical: "version" }]
|
| 142 |
+
.find(field => !this.isLoaded(field.member));
|
| 143 |
+
if (notLoaded) {
|
| 144 |
+
throw new CheckException([{
|
| 145 |
+
ruleId: "invalid_type",
|
| 146 |
+
location: ObjectLocation.property(notLoaded.canonical),
|
| 147 |
+
message: "Mutation requires a fully loaded entity",
|
| 148 |
+
}]);
|
| 149 |
+
}
|
| 150 |
+
}
|
| 151 |
+
const request = graph.request({
|
| 152 |
+
entity: "CustomerOrder", action,
|
| 153 |
+
payload: action === "Update"
|
| 154 |
+
? (this as any)._root.change(this.teaqlEntityKey())
|
| 155 |
+
: this.teaqlMutationPayload(),
|
| 156 |
+
id: (this as any).id, version: (this as any).version,
|
| 157 |
+
comment: (this as any)._comment,
|
| 158 |
+
ledgerKey: this.teaqlEntityKey(), ledgerRoot: (this as any)._root,
|
| 159 |
+
}, parent, (this as any)._comment).withLoadedSnapshot(LoadedScalarSnapshot.forEntity(this) ?? new LoadedScalarSnapshot());
|
| 160 |
+
if (pending) service.preflightMutation(request);
|
| 161 |
+
const scope = request.scopeFor(this.teaqlEntityKey());
|
| 162 |
+
for (const [index, child] of (this as any)._orderItemList.entries()) {
|
| 163 |
+
child.teaqlAttachRoot((this as any)._root);
|
| 164 |
+
const currentParent = child.customerOrder;
|
| 165 |
+
if (this.id === undefined || !child.isLoaded("customerOrder") || (typeof currentParent === "object" && currentParent !== null
|
| 166 |
+
? currentParent.id : currentParent) !== this.id) child.updateCustomerOrder(this);
|
| 167 |
+
try { child.teaqlPreflightGraph(context, service, graph, scope); }
|
| 168 |
+
catch (error) {
|
| 169 |
+
if (!(error instanceof CheckException)) throw error;
|
| 170 |
+
const prefix = ObjectLocation.property("order_item_list").index(index);
|
| 171 |
+
throw new CheckException(error.violations.map(violation => ({
|
| 172 |
+
...violation, location: violation.location.prefixedBy(prefix),
|
| 173 |
+
})));
|
| 174 |
+
}
|
| 175 |
+
}
|
| 176 |
+
for (const [index, child] of (this as any)._paymentList.entries()) {
|
| 177 |
+
child.teaqlAttachRoot((this as any)._root);
|
| 178 |
+
const currentParent = child.customerOrder;
|
| 179 |
+
if (this.id === undefined || !child.isLoaded("customerOrder") || (typeof currentParent === "object" && currentParent !== null
|
| 180 |
+
? currentParent.id : currentParent) !== this.id) child.updateCustomerOrder(this);
|
| 181 |
+
try { child.teaqlPreflightGraph(context, service, graph, scope); }
|
| 182 |
+
catch (error) {
|
| 183 |
+
if (!(error instanceof CheckException)) throw error;
|
| 184 |
+
const prefix = ObjectLocation.property("payment_list").index(index);
|
| 185 |
+
throw new CheckException(error.violations.map(violation => ({
|
| 186 |
+
...violation, location: violation.location.prefixedBy(prefix),
|
| 187 |
+
})));
|
| 188 |
+
}
|
| 189 |
+
}
|
| 190 |
+
for (const [index, child] of (this as any)._shipmentList.entries()) {
|
| 191 |
+
child.teaqlAttachRoot((this as any)._root);
|
| 192 |
+
const currentParent = child.customerOrder;
|
| 193 |
+
if (this.id === undefined || !child.isLoaded("customerOrder") || (typeof currentParent === "object" && currentParent !== null
|
| 194 |
+
? currentParent.id : currentParent) !== this.id) child.updateCustomerOrder(this);
|
| 195 |
+
try { child.teaqlPreflightGraph(context, service, graph, scope); }
|
| 196 |
+
catch (error) {
|
| 197 |
+
if (!(error instanceof CheckException)) throw error;
|
| 198 |
+
const prefix = ObjectLocation.property("shipment_list").index(index);
|
| 199 |
+
throw new CheckException(error.violations.map(violation => ({
|
| 200 |
+
...violation, location: violation.location.prefixedBy(prefix),
|
| 201 |
+
})));
|
| 202 |
+
}
|
| 203 |
+
}
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
/** @internal Used by generated relation cascades inside the root graph transaction. */
|
| 207 |
+
async teaqlSaveWithinGraph(context: UserContext, service: TeaQLDataService, graph: GraphMutationSession, parent?: MutationTraceScope): Promise<CustomerOrder> {
|
| 208 |
+
if (!parent) new MutationIntent((this as any)._comment);
|
| 209 |
+
const action = (this as any)._action;
|
| 210 |
+
const ledgerPayload = (this as any)._root.change(this.teaqlEntityKey());
|
| 211 |
+
const mutation = {
|
| 212 |
+
entity: "CustomerOrder",
|
| 213 |
+
action: (this as any)._action,
|
| 214 |
+
payload: action === "Update" ? ledgerPayload : this.teaqlMutationPayload(),
|
| 215 |
+
id: (this as any).id,
|
| 216 |
+
version: (this as any).version,
|
| 217 |
+
comment: (this as any)._comment
|
| 218 |
+
,ledgerKey: this.teaqlEntityKey()
|
| 219 |
+
,ledgerRoot: (this as any)._root
|
| 220 |
+
};
|
| 221 |
+
const request = graph.request(mutation, parent, (this as any)._comment)
|
| 222 |
+
.withLoadedSnapshot(LoadedScalarSnapshot.forEntity(this) ?? new LoadedScalarSnapshot());
|
| 223 |
+
if (action === "Update" && !(this as any)._root.hasPending(this.teaqlEntityKey())) {
|
| 224 |
+
const scope = request.scopeFor(this.teaqlEntityKey());
|
| 225 |
+
for (const [index, child] of (this as any)._orderItemList.entries()) {
|
| 226 |
+
child.teaqlAttachRoot((this as any)._root);
|
| 227 |
+
const currentParent = child.customerOrder;
|
| 228 |
+
if (this.id === undefined || !child.isLoaded("customerOrder") || (typeof currentParent === "object" && currentParent !== null
|
| 229 |
+
? currentParent.id : currentParent) !== this.id) child.updateCustomerOrder(this);
|
| 230 |
+
try { await child.teaqlSaveWithinGraph(context, service, graph, scope); }
|
| 231 |
+
catch (error) {
|
| 232 |
+
if (!(error instanceof CheckException)) throw error;
|
| 233 |
+
const prefix = ObjectLocation.property("order_item_list").index(index);
|
| 234 |
+
throw new CheckException(error.violations.map(violation => ({
|
| 235 |
+
...violation, location: violation.location.prefixedBy(prefix),
|
| 236 |
+
})));
|
| 237 |
+
}
|
| 238 |
+
}
|
| 239 |
+
for (const [index, child] of (this as any)._paymentList.entries()) {
|
| 240 |
+
child.teaqlAttachRoot((this as any)._root);
|
| 241 |
+
const currentParent = child.customerOrder;
|
| 242 |
+
if (this.id === undefined || !child.isLoaded("customerOrder") || (typeof currentParent === "object" && currentParent !== null
|
| 243 |
+
? currentParent.id : currentParent) !== this.id) child.updateCustomerOrder(this);
|
| 244 |
+
try { await child.teaqlSaveWithinGraph(context, service, graph, scope); }
|
| 245 |
+
catch (error) {
|
| 246 |
+
if (!(error instanceof CheckException)) throw error;
|
| 247 |
+
const prefix = ObjectLocation.property("payment_list").index(index);
|
| 248 |
+
throw new CheckException(error.violations.map(violation => ({
|
| 249 |
+
...violation, location: violation.location.prefixedBy(prefix),
|
| 250 |
+
})));
|
| 251 |
+
}
|
| 252 |
+
}
|
| 253 |
+
for (const [index, child] of (this as any)._shipmentList.entries()) {
|
| 254 |
+
child.teaqlAttachRoot((this as any)._root);
|
| 255 |
+
const currentParent = child.customerOrder;
|
| 256 |
+
if (this.id === undefined || !child.isLoaded("customerOrder") || (typeof currentParent === "object" && currentParent !== null
|
| 257 |
+
? currentParent.id : currentParent) !== this.id) child.updateCustomerOrder(this);
|
| 258 |
+
try { await child.teaqlSaveWithinGraph(context, service, graph, scope); }
|
| 259 |
+
catch (error) {
|
| 260 |
+
if (!(error instanceof CheckException)) throw error;
|
| 261 |
+
const prefix = ObjectLocation.property("shipment_list").index(index);
|
| 262 |
+
throw new CheckException(error.violations.map(violation => ({
|
| 263 |
+
...violation, location: violation.location.prefixedBy(prefix),
|
| 264 |
+
})));
|
| 265 |
+
}
|
| 266 |
+
}
|
| 267 |
+
return this;
|
| 268 |
+
}
|
| 269 |
+
const result = await service.executeMutation(request);
|
| 270 |
+
for (const [field, value] of Object.entries(mutation.payload as Record<string, unknown>)) {
|
| 271 |
+
if (field !== "id" && field !== "version") (this as any)._root.set(this.teaqlEntityKey(), field, value);
|
| 272 |
+
}
|
| 273 |
+
if (!result.persistedRecord) {
|
| 274 |
+
throw new Error("Mutation did not return the authoritative persisted record");
|
| 275 |
+
}
|
| 276 |
+
const rollbackState = {
|
| 277 |
+
payload: this.teaqlMutationPayload(),
|
| 278 |
+
ledgerId: (this as any)._ledgerId,
|
| 279 |
+
action: (this as any)._action,
|
| 280 |
+
loadedFields: new Set((this as any)._loadedFields),
|
| 281 |
+
fullyLoaded: (this as any)._fullyLoaded,
|
| 282 |
+
loadedSnapshot: LoadedScalarSnapshot.forEntity(this),
|
| 283 |
+
};
|
| 284 |
+
const oldKey = this.teaqlEntityKey();
|
| 285 |
+
Object.assign(this, result.persistedRecord);
|
| 286 |
+
LoadedScalarSnapshot.captureFor(this, this.teaqlMutationPayload());
|
| 287 |
+
(this as any)._ledgerId = (this as any).id ?? (this as any)._ledgerId;
|
| 288 |
+
const newKey = this.teaqlEntityKey();
|
| 289 |
+
(this as any)._root.rekey(oldKey, newKey);
|
| 290 |
+
service.afterGraphRollback(() => {
|
| 291 |
+
Object.assign(this, rollbackState.payload);
|
| 292 |
+
(this as any)._ledgerId = rollbackState.ledgerId;
|
| 293 |
+
(this as any)._action = rollbackState.action;
|
| 294 |
+
(this as any)._loadedFields = rollbackState.loadedFields;
|
| 295 |
+
(this as any)._fullyLoaded = rollbackState.fullyLoaded;
|
| 296 |
+
LoadedScalarSnapshot.restoreFor(this, rollbackState.loadedSnapshot);
|
| 297 |
+
(this as any)._root.rekey(newKey, oldKey);
|
| 298 |
+
});
|
| 299 |
+
(this as any)._loadedFields = new Set(Object.keys(result.persistedRecord));
|
| 300 |
+
(this as any)._fullyLoaded = false;
|
| 301 |
+
if (mutation.action !== "Delete") (this as any)._action = "Update";
|
| 302 |
+
const scope = request.scopeFor(newKey);
|
| 303 |
+
for (const [index, child] of (this as any)._orderItemList.entries()) {
|
| 304 |
+
child.teaqlAttachRoot((this as any)._root);
|
| 305 |
+
const currentParent = child.customerOrder;
|
| 306 |
+
if (this.id === undefined || !child.isLoaded("customerOrder") || (typeof currentParent === "object" && currentParent !== null
|
| 307 |
+
? currentParent.id : currentParent) !== this.id) child.updateCustomerOrder(this);
|
| 308 |
+
try { await child.teaqlSaveWithinGraph(context, service, graph, scope); }
|
| 309 |
+
catch (error) {
|
| 310 |
+
if (!(error instanceof CheckException)) throw error;
|
| 311 |
+
const prefix = ObjectLocation.property("order_item_list").index(index);
|
| 312 |
+
throw new CheckException(error.violations.map(violation => ({
|
| 313 |
+
...violation, location: violation.location.prefixedBy(prefix),
|
| 314 |
+
})));
|
| 315 |
+
}
|
| 316 |
+
}
|
| 317 |
+
for (const [index, child] of (this as any)._paymentList.entries()) {
|
| 318 |
+
child.teaqlAttachRoot((this as any)._root);
|
| 319 |
+
const currentParent = child.customerOrder;
|
| 320 |
+
if (this.id === undefined || !child.isLoaded("customerOrder") || (typeof currentParent === "object" && currentParent !== null
|
| 321 |
+
? currentParent.id : currentParent) !== this.id) child.updateCustomerOrder(this);
|
| 322 |
+
try { await child.teaqlSaveWithinGraph(context, service, graph, scope); }
|
| 323 |
+
catch (error) {
|
| 324 |
+
if (!(error instanceof CheckException)) throw error;
|
| 325 |
+
const prefix = ObjectLocation.property("payment_list").index(index);
|
| 326 |
+
throw new CheckException(error.violations.map(violation => ({
|
| 327 |
+
...violation, location: violation.location.prefixedBy(prefix),
|
| 328 |
+
})));
|
| 329 |
+
}
|
| 330 |
+
}
|
| 331 |
+
for (const [index, child] of (this as any)._shipmentList.entries()) {
|
| 332 |
+
child.teaqlAttachRoot((this as any)._root);
|
| 333 |
+
const currentParent = child.customerOrder;
|
| 334 |
+
if (this.id === undefined || !child.isLoaded("customerOrder") || (typeof currentParent === "object" && currentParent !== null
|
| 335 |
+
? currentParent.id : currentParent) !== this.id) child.updateCustomerOrder(this);
|
| 336 |
+
try { await child.teaqlSaveWithinGraph(context, service, graph, scope); }
|
| 337 |
+
catch (error) {
|
| 338 |
+
if (!(error instanceof CheckException)) throw error;
|
| 339 |
+
const prefix = ObjectLocation.property("shipment_list").index(index);
|
| 340 |
+
throw new CheckException(error.violations.map(violation => ({
|
| 341 |
+
...violation, location: violation.location.prefixedBy(prefix),
|
| 342 |
+
})));
|
| 343 |
+
}
|
| 344 |
+
}
|
| 345 |
+
service.afterGraphCommit(() => {
|
| 346 |
+
(this as any)._root.clearEntity(newKey);
|
| 347 |
+
if ((this as any).version !== undefined) (this as any)._root.acceptCommittedVersion(newKey, Number((this as any).version));
|
| 348 |
+
});
|
| 349 |
+
return this;
|
| 350 |
+
}
|
| 351 |
+
|
| 352 |
+
private teaqlMutationPayload(): Record<string, unknown> {
|
| 353 |
+
return {
|
| 354 |
+
"id": this.id,
|
| 355 |
+
"platform": this.platform,
|
| 356 |
+
"order_number": this.orderNumber,
|
| 357 |
+
"description": this.description,
|
| 358 |
+
"version": this.version
|
| 359 |
+
};
|
| 360 |
+
}
|
| 361 |
+
|
| 362 |
+
updateId(value: string): this {
|
| 363 |
+
this.id = value;
|
| 364 |
+
this.markLoaded("id");
|
| 365 |
+
(this as any)._root.set(this.teaqlEntityKey(), "id", value);
|
| 366 |
+
return this;
|
| 367 |
+
}
|
| 368 |
+
|
| 369 |
+
updateOrderNumber(value: string): this {
|
| 370 |
+
this.orderNumber = value;
|
| 371 |
+
this.markLoaded("orderNumber");
|
| 372 |
+
(this as any)._root.set(this.teaqlEntityKey(), "order_number", value);
|
| 373 |
+
return this;
|
| 374 |
+
}
|
| 375 |
+
|
| 376 |
+
updateDescription(value: string): this {
|
| 377 |
+
this.description = value;
|
| 378 |
+
this.markLoaded("description");
|
| 379 |
+
(this as any)._root.set(this.teaqlEntityKey(), "description", value);
|
| 380 |
+
return this;
|
| 381 |
+
}
|
| 382 |
+
|
| 383 |
+
updateVersion(value: number): this {
|
| 384 |
+
this.version = value;
|
| 385 |
+
this.markLoaded("version");
|
| 386 |
+
(this as any)._root.set(this.teaqlEntityKey(), "version", value);
|
| 387 |
+
return this;
|
| 388 |
+
}
|
| 389 |
+
updatePlatform(value: any): this {
|
| 390 |
+
this.platform = value?.id ?? value;
|
| 391 |
+
this.markLoaded("platform");
|
| 392 |
+
(this as any)._root.set(this.teaqlEntityKey(), "platform", this.platform);
|
| 393 |
+
return this;
|
| 394 |
+
}
|
| 395 |
+
|
| 396 |
+
orderItemList(): SmartList<OrderItem> {
|
| 397 |
+
return (this as any)._orderItemList;
|
| 398 |
+
}
|
| 399 |
+
|
| 400 |
+
paymentList(): SmartList<Payment> {
|
| 401 |
+
return (this as any)._paymentList;
|
| 402 |
+
}
|
| 403 |
+
|
| 404 |
+
shipmentList(): SmartList<Shipment> {
|
| 405 |
+
return (this as any)._shipmentList;
|
| 406 |
+
}
|
| 407 |
+
}
|
source/teaql-ts/examples/trace-chain/lib/src/generated/models/OrderItem.ts
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { CheckException, EntityKey, EntityRoot, GraphMutationSession, LoadedScalarSnapshot, MutationIntent, MutationTraceScope, ObjectLocation, SmartList, TeaQLDataService, UserContext } from '../../teaql-ts';
|
| 2 |
+
import { CustomerOrder } from './CustomerOrder';
|
| 3 |
+
|
| 4 |
+
export class OrderItem {
|
| 5 |
+
private static teaqlTemporaryId = 0;
|
| 6 |
+
id?: string;
|
| 7 |
+
customerOrder?: CustomerOrder | string;
|
| 8 |
+
name?: string;
|
| 9 |
+
version?: number;
|
| 10 |
+
|
| 11 |
+
constructor(init?: Partial<OrderItem>) {
|
| 12 |
+
Object.defineProperty(this, "_action", { value: init && init.id ? "Update" : "Create", writable: true, enumerable: false });
|
| 13 |
+
Object.defineProperty(this, "_comment", { value: undefined, writable: true, enumerable: false });
|
| 14 |
+
Object.defineProperty(this, "_fullyLoaded", { value: !init || !init.id, writable: true, enumerable: false });
|
| 15 |
+
Object.defineProperty(this, "_loadedFields", { value: new Set(Object.keys(init || {})), writable: true, enumerable: false });
|
| 16 |
+
Object.defineProperty(this, "_root", { value: new EntityRoot(), writable: true, enumerable: false });
|
| 17 |
+
Object.defineProperty(this, "_ledgerId", { value: init?.id ?? --OrderItem.teaqlTemporaryId, writable: true, enumerable: false });
|
| 18 |
+
if (init) {
|
| 19 |
+
const fields: Record<string, unknown> = { ...(init as Record<string, unknown>) };
|
| 20 |
+
Object.assign(this, fields);
|
| 21 |
+
if ((init as any).customerOrder && typeof (init as any).customerOrder === "object") {
|
| 22 |
+
this.customerOrder = (init as any).customerOrder instanceof CustomerOrder
|
| 23 |
+
? (init as any).customerOrder
|
| 24 |
+
: CustomerOrder.fromRecord((init as any).customerOrder);
|
| 25 |
+
this.markLoaded("customerOrder");
|
| 26 |
+
}
|
| 27 |
+
}
|
| 28 |
+
const key = this.teaqlEntityKey();
|
| 29 |
+
if ((this as any)._action === "Create") (this as any)._root.markAsNew(key);
|
| 30 |
+
else if ((this as any).version !== undefined) (this as any)._root.setOriginalVersion(key, Number((this as any).version));
|
| 31 |
+
LoadedScalarSnapshot.captureFor(this, this.teaqlMutationPayload());
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
private teaqlEntityKey(): EntityKey { return { entity: "OrderItem", id: (this as any)._ledgerId }; }
|
| 35 |
+
private teaqlAttachRoot(root: EntityRoot): this {
|
| 36 |
+
if ((this as any)._root !== root) {
|
| 37 |
+
root.mergeEntityFrom((this as any)._root, this.teaqlEntityKey());
|
| 38 |
+
(this as any)._root = root;
|
| 39 |
+
}
|
| 40 |
+
return this;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
static fromRecord(record: Record<string, unknown>, root?: EntityRoot): OrderItem {
|
| 44 |
+
const entity = new OrderItem(record as Partial<OrderItem>);
|
| 45 |
+
return root ? entity.teaqlAttachRoot(root) : entity;
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
isLoaded(field: string): boolean {
|
| 49 |
+
return (this as any)._fullyLoaded || (this as any)._loadedFields.has(field);
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
markLoaded(...fields: string[]): this {
|
| 53 |
+
for (const field of fields) (this as any)._loadedFields.add(field);
|
| 54 |
+
return this;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
markLoadedOnly(...fields: string[]): this {
|
| 58 |
+
(this as any)._fullyLoaded = false;
|
| 59 |
+
(this as any)._loadedFields = new Set(fields);
|
| 60 |
+
return this;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
static refer(id: string | number): OrderItem {
|
| 64 |
+
return new OrderItem({ id: String(id) } as Partial<OrderItem>);
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
/** @internal Generated Runtime Module fixed-ID construction capability. */
|
| 68 |
+
static teaqlBootstrapNew(id: string | number): OrderItem {
|
| 69 |
+
return new OrderItem().updateId(String(id));
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
markForDeletion(): this {
|
| 73 |
+
(this as any)._action = "Delete";
|
| 74 |
+
(this as any)._root.markAsDeleted(this.teaqlEntityKey());
|
| 75 |
+
return this;
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
auditAs(comment: string): this {
|
| 79 |
+
new MutationIntent(comment);
|
| 80 |
+
(this as any)._comment = comment;
|
| 81 |
+
return this;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
async save(context: UserContext): Promise<OrderItem> {
|
| 85 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 86 |
+
return service.executeGraphSave(new MutationIntent((this as any)._comment), async (graph) => {
|
| 87 |
+
this.teaqlPreflightGraph(context, service, graph);
|
| 88 |
+
return this.teaqlSaveWithinGraph(context, service, graph);
|
| 89 |
+
});
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
/** @internal Validates and fixes the complete graph before its first mutation. */
|
| 93 |
+
teaqlPreflightGraph(context: UserContext, service: TeaQLDataService, graph: GraphMutationSession, parent?: MutationTraceScope): void {
|
| 94 |
+
if (!parent) new MutationIntent((this as any)._comment);
|
| 95 |
+
const action = (this as any)._action;
|
| 96 |
+
const pending = action !== "Update" || (this as any)._root.hasPending(this.teaqlEntityKey());
|
| 97 |
+
if (action === "Update" && pending) {
|
| 98 |
+
const notLoaded = [{ member: "id", canonical: "id" }, { member: "customerOrder", canonical: "customer_order" }, { member: "name", canonical: "name" }, { member: "version", canonical: "version" }]
|
| 99 |
+
.find(field => !this.isLoaded(field.member));
|
| 100 |
+
if (notLoaded) {
|
| 101 |
+
throw new CheckException([{
|
| 102 |
+
ruleId: "invalid_type",
|
| 103 |
+
location: ObjectLocation.property(notLoaded.canonical),
|
| 104 |
+
message: "Mutation requires a fully loaded entity",
|
| 105 |
+
}]);
|
| 106 |
+
}
|
| 107 |
+
}
|
| 108 |
+
const request = graph.request({
|
| 109 |
+
entity: "OrderItem", action,
|
| 110 |
+
payload: action === "Update"
|
| 111 |
+
? (this as any)._root.change(this.teaqlEntityKey())
|
| 112 |
+
: this.teaqlMutationPayload(),
|
| 113 |
+
id: (this as any).id, version: (this as any).version,
|
| 114 |
+
comment: (this as any)._comment,
|
| 115 |
+
ledgerKey: this.teaqlEntityKey(), ledgerRoot: (this as any)._root,
|
| 116 |
+
}, parent, (this as any)._comment).withLoadedSnapshot(LoadedScalarSnapshot.forEntity(this) ?? new LoadedScalarSnapshot());
|
| 117 |
+
if (pending) service.preflightMutation(request);
|
| 118 |
+
const scope = request.scopeFor(this.teaqlEntityKey());
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
/** @internal Used by generated relation cascades inside the root graph transaction. */
|
| 122 |
+
async teaqlSaveWithinGraph(context: UserContext, service: TeaQLDataService, graph: GraphMutationSession, parent?: MutationTraceScope): Promise<OrderItem> {
|
| 123 |
+
if (!parent) new MutationIntent((this as any)._comment);
|
| 124 |
+
const action = (this as any)._action;
|
| 125 |
+
const ledgerPayload = (this as any)._root.change(this.teaqlEntityKey());
|
| 126 |
+
const mutation = {
|
| 127 |
+
entity: "OrderItem",
|
| 128 |
+
action: (this as any)._action,
|
| 129 |
+
payload: action === "Update" ? ledgerPayload : this.teaqlMutationPayload(),
|
| 130 |
+
id: (this as any).id,
|
| 131 |
+
version: (this as any).version,
|
| 132 |
+
comment: (this as any)._comment
|
| 133 |
+
,ledgerKey: this.teaqlEntityKey()
|
| 134 |
+
,ledgerRoot: (this as any)._root
|
| 135 |
+
};
|
| 136 |
+
const request = graph.request(mutation, parent, (this as any)._comment)
|
| 137 |
+
.withLoadedSnapshot(LoadedScalarSnapshot.forEntity(this) ?? new LoadedScalarSnapshot());
|
| 138 |
+
if (action === "Update" && !(this as any)._root.hasPending(this.teaqlEntityKey())) {
|
| 139 |
+
const scope = request.scopeFor(this.teaqlEntityKey());
|
| 140 |
+
return this;
|
| 141 |
+
}
|
| 142 |
+
const result = await service.executeMutation(request);
|
| 143 |
+
for (const [field, value] of Object.entries(mutation.payload as Record<string, unknown>)) {
|
| 144 |
+
if (field !== "id" && field !== "version") (this as any)._root.set(this.teaqlEntityKey(), field, value);
|
| 145 |
+
}
|
| 146 |
+
if (!result.persistedRecord) {
|
| 147 |
+
throw new Error("Mutation did not return the authoritative persisted record");
|
| 148 |
+
}
|
| 149 |
+
const rollbackState = {
|
| 150 |
+
payload: this.teaqlMutationPayload(),
|
| 151 |
+
ledgerId: (this as any)._ledgerId,
|
| 152 |
+
action: (this as any)._action,
|
| 153 |
+
loadedFields: new Set((this as any)._loadedFields),
|
| 154 |
+
fullyLoaded: (this as any)._fullyLoaded,
|
| 155 |
+
loadedSnapshot: LoadedScalarSnapshot.forEntity(this),
|
| 156 |
+
};
|
| 157 |
+
const oldKey = this.teaqlEntityKey();
|
| 158 |
+
Object.assign(this, result.persistedRecord);
|
| 159 |
+
LoadedScalarSnapshot.captureFor(this, this.teaqlMutationPayload());
|
| 160 |
+
(this as any)._ledgerId = (this as any).id ?? (this as any)._ledgerId;
|
| 161 |
+
const newKey = this.teaqlEntityKey();
|
| 162 |
+
(this as any)._root.rekey(oldKey, newKey);
|
| 163 |
+
service.afterGraphRollback(() => {
|
| 164 |
+
Object.assign(this, rollbackState.payload);
|
| 165 |
+
(this as any)._ledgerId = rollbackState.ledgerId;
|
| 166 |
+
(this as any)._action = rollbackState.action;
|
| 167 |
+
(this as any)._loadedFields = rollbackState.loadedFields;
|
| 168 |
+
(this as any)._fullyLoaded = rollbackState.fullyLoaded;
|
| 169 |
+
LoadedScalarSnapshot.restoreFor(this, rollbackState.loadedSnapshot);
|
| 170 |
+
(this as any)._root.rekey(newKey, oldKey);
|
| 171 |
+
});
|
| 172 |
+
(this as any)._loadedFields = new Set(Object.keys(result.persistedRecord));
|
| 173 |
+
(this as any)._fullyLoaded = false;
|
| 174 |
+
if (mutation.action !== "Delete") (this as any)._action = "Update";
|
| 175 |
+
const scope = request.scopeFor(newKey);
|
| 176 |
+
service.afterGraphCommit(() => {
|
| 177 |
+
(this as any)._root.clearEntity(newKey);
|
| 178 |
+
if ((this as any).version !== undefined) (this as any)._root.acceptCommittedVersion(newKey, Number((this as any).version));
|
| 179 |
+
});
|
| 180 |
+
return this;
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
private teaqlMutationPayload(): Record<string, unknown> {
|
| 184 |
+
return {
|
| 185 |
+
"id": this.id,
|
| 186 |
+
"customer_order": this.customerOrder,
|
| 187 |
+
"name": this.name,
|
| 188 |
+
"version": this.version
|
| 189 |
+
};
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
updateId(value: string): this {
|
| 193 |
+
this.id = value;
|
| 194 |
+
this.markLoaded("id");
|
| 195 |
+
(this as any)._root.set(this.teaqlEntityKey(), "id", value);
|
| 196 |
+
return this;
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
updateName(value: string): this {
|
| 200 |
+
this.name = value;
|
| 201 |
+
this.markLoaded("name");
|
| 202 |
+
(this as any)._root.set(this.teaqlEntityKey(), "name", value);
|
| 203 |
+
return this;
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
updateVersion(value: number): this {
|
| 207 |
+
this.version = value;
|
| 208 |
+
this.markLoaded("version");
|
| 209 |
+
(this as any)._root.set(this.teaqlEntityKey(), "version", value);
|
| 210 |
+
return this;
|
| 211 |
+
}
|
| 212 |
+
updateCustomerOrder(value: any): this {
|
| 213 |
+
this.customerOrder = value?.id ?? value;
|
| 214 |
+
this.markLoaded("customerOrder");
|
| 215 |
+
(this as any)._root.set(this.teaqlEntityKey(), "customer_order", this.customerOrder);
|
| 216 |
+
return this;
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
}
|
source/teaql-ts/examples/trace-chain/lib/src/generated/models/Payment.ts
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { CheckException, EntityKey, EntityRoot, GraphMutationSession, LoadedScalarSnapshot, MutationIntent, MutationTraceScope, ObjectLocation, SmartList, TeaQLDataService, UserContext } from '../../teaql-ts';
|
| 2 |
+
import { CustomerOrder } from './CustomerOrder';
|
| 3 |
+
import { PaymentAttempt } from './PaymentAttempt';
|
| 4 |
+
|
| 5 |
+
export class Payment {
|
| 6 |
+
private static teaqlTemporaryId = 0;
|
| 7 |
+
id?: string;
|
| 8 |
+
customerOrder?: CustomerOrder | string;
|
| 9 |
+
referenceCode?: string;
|
| 10 |
+
version?: number;
|
| 11 |
+
|
| 12 |
+
constructor(init?: Partial<Payment>) {
|
| 13 |
+
Object.defineProperty(this, "_action", { value: init && init.id ? "Update" : "Create", writable: true, enumerable: false });
|
| 14 |
+
Object.defineProperty(this, "_comment", { value: undefined, writable: true, enumerable: false });
|
| 15 |
+
Object.defineProperty(this, "_fullyLoaded", { value: !init || !init.id, writable: true, enumerable: false });
|
| 16 |
+
Object.defineProperty(this, "_loadedFields", { value: new Set(Object.keys(init || {})), writable: true, enumerable: false });
|
| 17 |
+
Object.defineProperty(this, "_root", { value: new EntityRoot(), writable: true, enumerable: false });
|
| 18 |
+
Object.defineProperty(this, "_ledgerId", { value: init?.id ?? --Payment.teaqlTemporaryId, writable: true, enumerable: false });
|
| 19 |
+
Object.defineProperty(this, "_paymentAttemptList", { value: init?.id ? SmartList.empty() : new SmartList(), writable: true, enumerable: false });
|
| 20 |
+
if (init) {
|
| 21 |
+
const fields: Record<string, unknown> = { ...(init as Record<string, unknown>) };
|
| 22 |
+
delete fields["paymentAttemptList"];
|
| 23 |
+
Object.assign(this, fields);
|
| 24 |
+
if ((init as any).customerOrder && typeof (init as any).customerOrder === "object") {
|
| 25 |
+
this.customerOrder = (init as any).customerOrder instanceof CustomerOrder
|
| 26 |
+
? (init as any).customerOrder
|
| 27 |
+
: CustomerOrder.fromRecord((init as any).customerOrder);
|
| 28 |
+
this.markLoaded("customerOrder");
|
| 29 |
+
}
|
| 30 |
+
if (Array.isArray((init as any).paymentAttemptList)) {
|
| 31 |
+
const selected = (init as any).paymentAttemptList;
|
| 32 |
+
(this as any)._paymentAttemptList = new SmartList(selected.map(
|
| 33 |
+
(child: unknown) => child instanceof PaymentAttempt
|
| 34 |
+
? child
|
| 35 |
+
: PaymentAttempt.fromRecord(child as Record<string, unknown>),
|
| 36 |
+
), { totalCount: selected.totalCount, aggregations: selected.aggregations,
|
| 37 |
+
summary: selected.summary, facets: selected.facets, isLoaded: selected.isLoaded ?? true });
|
| 38 |
+
this.markLoaded("paymentAttemptList");
|
| 39 |
+
}
|
| 40 |
+
}
|
| 41 |
+
const key = this.teaqlEntityKey();
|
| 42 |
+
if ((this as any)._action === "Create") (this as any)._root.markAsNew(key);
|
| 43 |
+
else if ((this as any).version !== undefined) (this as any)._root.setOriginalVersion(key, Number((this as any).version));
|
| 44 |
+
LoadedScalarSnapshot.captureFor(this, this.teaqlMutationPayload());
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
private teaqlEntityKey(): EntityKey { return { entity: "Payment", id: (this as any)._ledgerId }; }
|
| 48 |
+
private teaqlAttachRoot(root: EntityRoot): this {
|
| 49 |
+
if ((this as any)._root !== root) {
|
| 50 |
+
root.mergeEntityFrom((this as any)._root, this.teaqlEntityKey());
|
| 51 |
+
(this as any)._root = root;
|
| 52 |
+
}
|
| 53 |
+
for (const child of (this as any)._paymentAttemptList) child.teaqlAttachRoot(root);
|
| 54 |
+
return this;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
static fromRecord(record: Record<string, unknown>, root?: EntityRoot): Payment {
|
| 58 |
+
const entity = new Payment(record as Partial<Payment>);
|
| 59 |
+
return root ? entity.teaqlAttachRoot(root) : entity;
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
isLoaded(field: string): boolean {
|
| 63 |
+
return (this as any)._fullyLoaded || (this as any)._loadedFields.has(field);
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
markLoaded(...fields: string[]): this {
|
| 67 |
+
for (const field of fields) (this as any)._loadedFields.add(field);
|
| 68 |
+
return this;
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
markLoadedOnly(...fields: string[]): this {
|
| 72 |
+
(this as any)._fullyLoaded = false;
|
| 73 |
+
(this as any)._loadedFields = new Set(fields);
|
| 74 |
+
return this;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
static refer(id: string | number): Payment {
|
| 78 |
+
return new Payment({ id: String(id) } as Partial<Payment>);
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
/** @internal Generated Runtime Module fixed-ID construction capability. */
|
| 82 |
+
static teaqlBootstrapNew(id: string | number): Payment {
|
| 83 |
+
return new Payment().updateId(String(id));
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
markForDeletion(): this {
|
| 87 |
+
(this as any)._action = "Delete";
|
| 88 |
+
(this as any)._root.markAsDeleted(this.teaqlEntityKey());
|
| 89 |
+
return this;
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
auditAs(comment: string): this {
|
| 93 |
+
new MutationIntent(comment);
|
| 94 |
+
(this as any)._comment = comment;
|
| 95 |
+
return this;
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
async save(context: UserContext): Promise<Payment> {
|
| 99 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 100 |
+
return service.executeGraphSave(new MutationIntent((this as any)._comment), async (graph) => {
|
| 101 |
+
this.teaqlPreflightGraph(context, service, graph);
|
| 102 |
+
return this.teaqlSaveWithinGraph(context, service, graph);
|
| 103 |
+
});
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
/** @internal Validates and fixes the complete graph before its first mutation. */
|
| 107 |
+
teaqlPreflightGraph(context: UserContext, service: TeaQLDataService, graph: GraphMutationSession, parent?: MutationTraceScope): void {
|
| 108 |
+
if (!parent) new MutationIntent((this as any)._comment);
|
| 109 |
+
const action = (this as any)._action;
|
| 110 |
+
const pending = action !== "Update" || (this as any)._root.hasPending(this.teaqlEntityKey());
|
| 111 |
+
if (action === "Update" && pending) {
|
| 112 |
+
const notLoaded = [{ member: "id", canonical: "id" }, { member: "customerOrder", canonical: "customer_order" }, { member: "referenceCode", canonical: "reference_code" }, { member: "version", canonical: "version" }]
|
| 113 |
+
.find(field => !this.isLoaded(field.member));
|
| 114 |
+
if (notLoaded) {
|
| 115 |
+
throw new CheckException([{
|
| 116 |
+
ruleId: "invalid_type",
|
| 117 |
+
location: ObjectLocation.property(notLoaded.canonical),
|
| 118 |
+
message: "Mutation requires a fully loaded entity",
|
| 119 |
+
}]);
|
| 120 |
+
}
|
| 121 |
+
}
|
| 122 |
+
const request = graph.request({
|
| 123 |
+
entity: "Payment", action,
|
| 124 |
+
payload: action === "Update"
|
| 125 |
+
? (this as any)._root.change(this.teaqlEntityKey())
|
| 126 |
+
: this.teaqlMutationPayload(),
|
| 127 |
+
id: (this as any).id, version: (this as any).version,
|
| 128 |
+
comment: (this as any)._comment,
|
| 129 |
+
ledgerKey: this.teaqlEntityKey(), ledgerRoot: (this as any)._root,
|
| 130 |
+
}, parent, (this as any)._comment).withLoadedSnapshot(LoadedScalarSnapshot.forEntity(this) ?? new LoadedScalarSnapshot());
|
| 131 |
+
if (pending) service.preflightMutation(request);
|
| 132 |
+
const scope = request.scopeFor(this.teaqlEntityKey());
|
| 133 |
+
for (const [index, child] of (this as any)._paymentAttemptList.entries()) {
|
| 134 |
+
child.teaqlAttachRoot((this as any)._root);
|
| 135 |
+
const currentParent = child.payment;
|
| 136 |
+
if (this.id === undefined || !child.isLoaded("payment") || (typeof currentParent === "object" && currentParent !== null
|
| 137 |
+
? currentParent.id : currentParent) !== this.id) child.updatePayment(this);
|
| 138 |
+
try { child.teaqlPreflightGraph(context, service, graph, scope); }
|
| 139 |
+
catch (error) {
|
| 140 |
+
if (!(error instanceof CheckException)) throw error;
|
| 141 |
+
const prefix = ObjectLocation.property("payment_attempt_list").index(index);
|
| 142 |
+
throw new CheckException(error.violations.map(violation => ({
|
| 143 |
+
...violation, location: violation.location.prefixedBy(prefix),
|
| 144 |
+
})));
|
| 145 |
+
}
|
| 146 |
+
}
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
/** @internal Used by generated relation cascades inside the root graph transaction. */
|
| 150 |
+
async teaqlSaveWithinGraph(context: UserContext, service: TeaQLDataService, graph: GraphMutationSession, parent?: MutationTraceScope): Promise<Payment> {
|
| 151 |
+
if (!parent) new MutationIntent((this as any)._comment);
|
| 152 |
+
const action = (this as any)._action;
|
| 153 |
+
const ledgerPayload = (this as any)._root.change(this.teaqlEntityKey());
|
| 154 |
+
const mutation = {
|
| 155 |
+
entity: "Payment",
|
| 156 |
+
action: (this as any)._action,
|
| 157 |
+
payload: action === "Update" ? ledgerPayload : this.teaqlMutationPayload(),
|
| 158 |
+
id: (this as any).id,
|
| 159 |
+
version: (this as any).version,
|
| 160 |
+
comment: (this as any)._comment
|
| 161 |
+
,ledgerKey: this.teaqlEntityKey()
|
| 162 |
+
,ledgerRoot: (this as any)._root
|
| 163 |
+
};
|
| 164 |
+
const request = graph.request(mutation, parent, (this as any)._comment)
|
| 165 |
+
.withLoadedSnapshot(LoadedScalarSnapshot.forEntity(this) ?? new LoadedScalarSnapshot());
|
| 166 |
+
if (action === "Update" && !(this as any)._root.hasPending(this.teaqlEntityKey())) {
|
| 167 |
+
const scope = request.scopeFor(this.teaqlEntityKey());
|
| 168 |
+
for (const [index, child] of (this as any)._paymentAttemptList.entries()) {
|
| 169 |
+
child.teaqlAttachRoot((this as any)._root);
|
| 170 |
+
const currentParent = child.payment;
|
| 171 |
+
if (this.id === undefined || !child.isLoaded("payment") || (typeof currentParent === "object" && currentParent !== null
|
| 172 |
+
? currentParent.id : currentParent) !== this.id) child.updatePayment(this);
|
| 173 |
+
try { await child.teaqlSaveWithinGraph(context, service, graph, scope); }
|
| 174 |
+
catch (error) {
|
| 175 |
+
if (!(error instanceof CheckException)) throw error;
|
| 176 |
+
const prefix = ObjectLocation.property("payment_attempt_list").index(index);
|
| 177 |
+
throw new CheckException(error.violations.map(violation => ({
|
| 178 |
+
...violation, location: violation.location.prefixedBy(prefix),
|
| 179 |
+
})));
|
| 180 |
+
}
|
| 181 |
+
}
|
| 182 |
+
return this;
|
| 183 |
+
}
|
| 184 |
+
const result = await service.executeMutation(request);
|
| 185 |
+
for (const [field, value] of Object.entries(mutation.payload as Record<string, unknown>)) {
|
| 186 |
+
if (field !== "id" && field !== "version") (this as any)._root.set(this.teaqlEntityKey(), field, value);
|
| 187 |
+
}
|
| 188 |
+
if (!result.persistedRecord) {
|
| 189 |
+
throw new Error("Mutation did not return the authoritative persisted record");
|
| 190 |
+
}
|
| 191 |
+
const rollbackState = {
|
| 192 |
+
payload: this.teaqlMutationPayload(),
|
| 193 |
+
ledgerId: (this as any)._ledgerId,
|
| 194 |
+
action: (this as any)._action,
|
| 195 |
+
loadedFields: new Set((this as any)._loadedFields),
|
| 196 |
+
fullyLoaded: (this as any)._fullyLoaded,
|
| 197 |
+
loadedSnapshot: LoadedScalarSnapshot.forEntity(this),
|
| 198 |
+
};
|
| 199 |
+
const oldKey = this.teaqlEntityKey();
|
| 200 |
+
Object.assign(this, result.persistedRecord);
|
| 201 |
+
LoadedScalarSnapshot.captureFor(this, this.teaqlMutationPayload());
|
| 202 |
+
(this as any)._ledgerId = (this as any).id ?? (this as any)._ledgerId;
|
| 203 |
+
const newKey = this.teaqlEntityKey();
|
| 204 |
+
(this as any)._root.rekey(oldKey, newKey);
|
| 205 |
+
service.afterGraphRollback(() => {
|
| 206 |
+
Object.assign(this, rollbackState.payload);
|
| 207 |
+
(this as any)._ledgerId = rollbackState.ledgerId;
|
| 208 |
+
(this as any)._action = rollbackState.action;
|
| 209 |
+
(this as any)._loadedFields = rollbackState.loadedFields;
|
| 210 |
+
(this as any)._fullyLoaded = rollbackState.fullyLoaded;
|
| 211 |
+
LoadedScalarSnapshot.restoreFor(this, rollbackState.loadedSnapshot);
|
| 212 |
+
(this as any)._root.rekey(newKey, oldKey);
|
| 213 |
+
});
|
| 214 |
+
(this as any)._loadedFields = new Set(Object.keys(result.persistedRecord));
|
| 215 |
+
(this as any)._fullyLoaded = false;
|
| 216 |
+
if (mutation.action !== "Delete") (this as any)._action = "Update";
|
| 217 |
+
const scope = request.scopeFor(newKey);
|
| 218 |
+
for (const [index, child] of (this as any)._paymentAttemptList.entries()) {
|
| 219 |
+
child.teaqlAttachRoot((this as any)._root);
|
| 220 |
+
const currentParent = child.payment;
|
| 221 |
+
if (this.id === undefined || !child.isLoaded("payment") || (typeof currentParent === "object" && currentParent !== null
|
| 222 |
+
? currentParent.id : currentParent) !== this.id) child.updatePayment(this);
|
| 223 |
+
try { await child.teaqlSaveWithinGraph(context, service, graph, scope); }
|
| 224 |
+
catch (error) {
|
| 225 |
+
if (!(error instanceof CheckException)) throw error;
|
| 226 |
+
const prefix = ObjectLocation.property("payment_attempt_list").index(index);
|
| 227 |
+
throw new CheckException(error.violations.map(violation => ({
|
| 228 |
+
...violation, location: violation.location.prefixedBy(prefix),
|
| 229 |
+
})));
|
| 230 |
+
}
|
| 231 |
+
}
|
| 232 |
+
service.afterGraphCommit(() => {
|
| 233 |
+
(this as any)._root.clearEntity(newKey);
|
| 234 |
+
if ((this as any).version !== undefined) (this as any)._root.acceptCommittedVersion(newKey, Number((this as any).version));
|
| 235 |
+
});
|
| 236 |
+
return this;
|
| 237 |
+
}
|
| 238 |
+
|
| 239 |
+
private teaqlMutationPayload(): Record<string, unknown> {
|
| 240 |
+
return {
|
| 241 |
+
"id": this.id,
|
| 242 |
+
"customer_order": this.customerOrder,
|
| 243 |
+
"reference_code": this.referenceCode,
|
| 244 |
+
"version": this.version
|
| 245 |
+
};
|
| 246 |
+
}
|
| 247 |
+
|
| 248 |
+
updateId(value: string): this {
|
| 249 |
+
this.id = value;
|
| 250 |
+
this.markLoaded("id");
|
| 251 |
+
(this as any)._root.set(this.teaqlEntityKey(), "id", value);
|
| 252 |
+
return this;
|
| 253 |
+
}
|
| 254 |
+
|
| 255 |
+
updateReferenceCode(value: string): this {
|
| 256 |
+
this.referenceCode = value;
|
| 257 |
+
this.markLoaded("referenceCode");
|
| 258 |
+
(this as any)._root.set(this.teaqlEntityKey(), "reference_code", value);
|
| 259 |
+
return this;
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
updateVersion(value: number): this {
|
| 263 |
+
this.version = value;
|
| 264 |
+
this.markLoaded("version");
|
| 265 |
+
(this as any)._root.set(this.teaqlEntityKey(), "version", value);
|
| 266 |
+
return this;
|
| 267 |
+
}
|
| 268 |
+
updateCustomerOrder(value: any): this {
|
| 269 |
+
this.customerOrder = value?.id ?? value;
|
| 270 |
+
this.markLoaded("customerOrder");
|
| 271 |
+
(this as any)._root.set(this.teaqlEntityKey(), "customer_order", this.customerOrder);
|
| 272 |
+
return this;
|
| 273 |
+
}
|
| 274 |
+
|
| 275 |
+
paymentAttemptList(): SmartList<PaymentAttempt> {
|
| 276 |
+
return (this as any)._paymentAttemptList;
|
| 277 |
+
}
|
| 278 |
+
}
|
source/teaql-ts/examples/trace-chain/lib/src/generated/models/PaymentAttempt.ts
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { CheckException, EntityKey, EntityRoot, GraphMutationSession, LoadedScalarSnapshot, MutationIntent, MutationTraceScope, ObjectLocation, SmartList, TeaQLDataService, UserContext } from '../../teaql-ts';
|
| 2 |
+
import { Payment } from './Payment';
|
| 3 |
+
|
| 4 |
+
export class PaymentAttempt {
|
| 5 |
+
private static teaqlTemporaryId = 0;
|
| 6 |
+
id?: string;
|
| 7 |
+
payment?: Payment | string;
|
| 8 |
+
referenceCode?: string;
|
| 9 |
+
version?: number;
|
| 10 |
+
|
| 11 |
+
constructor(init?: Partial<PaymentAttempt>) {
|
| 12 |
+
Object.defineProperty(this, "_action", { value: init && init.id ? "Update" : "Create", writable: true, enumerable: false });
|
| 13 |
+
Object.defineProperty(this, "_comment", { value: undefined, writable: true, enumerable: false });
|
| 14 |
+
Object.defineProperty(this, "_fullyLoaded", { value: !init || !init.id, writable: true, enumerable: false });
|
| 15 |
+
Object.defineProperty(this, "_loadedFields", { value: new Set(Object.keys(init || {})), writable: true, enumerable: false });
|
| 16 |
+
Object.defineProperty(this, "_root", { value: new EntityRoot(), writable: true, enumerable: false });
|
| 17 |
+
Object.defineProperty(this, "_ledgerId", { value: init?.id ?? --PaymentAttempt.teaqlTemporaryId, writable: true, enumerable: false });
|
| 18 |
+
if (init) {
|
| 19 |
+
const fields: Record<string, unknown> = { ...(init as Record<string, unknown>) };
|
| 20 |
+
Object.assign(this, fields);
|
| 21 |
+
if ((init as any).payment && typeof (init as any).payment === "object") {
|
| 22 |
+
this.payment = (init as any).payment instanceof Payment
|
| 23 |
+
? (init as any).payment
|
| 24 |
+
: Payment.fromRecord((init as any).payment);
|
| 25 |
+
this.markLoaded("payment");
|
| 26 |
+
}
|
| 27 |
+
}
|
| 28 |
+
const key = this.teaqlEntityKey();
|
| 29 |
+
if ((this as any)._action === "Create") (this as any)._root.markAsNew(key);
|
| 30 |
+
else if ((this as any).version !== undefined) (this as any)._root.setOriginalVersion(key, Number((this as any).version));
|
| 31 |
+
LoadedScalarSnapshot.captureFor(this, this.teaqlMutationPayload());
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
private teaqlEntityKey(): EntityKey { return { entity: "PaymentAttempt", id: (this as any)._ledgerId }; }
|
| 35 |
+
private teaqlAttachRoot(root: EntityRoot): this {
|
| 36 |
+
if ((this as any)._root !== root) {
|
| 37 |
+
root.mergeEntityFrom((this as any)._root, this.teaqlEntityKey());
|
| 38 |
+
(this as any)._root = root;
|
| 39 |
+
}
|
| 40 |
+
return this;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
static fromRecord(record: Record<string, unknown>, root?: EntityRoot): PaymentAttempt {
|
| 44 |
+
const entity = new PaymentAttempt(record as Partial<PaymentAttempt>);
|
| 45 |
+
return root ? entity.teaqlAttachRoot(root) : entity;
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
isLoaded(field: string): boolean {
|
| 49 |
+
return (this as any)._fullyLoaded || (this as any)._loadedFields.has(field);
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
markLoaded(...fields: string[]): this {
|
| 53 |
+
for (const field of fields) (this as any)._loadedFields.add(field);
|
| 54 |
+
return this;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
markLoadedOnly(...fields: string[]): this {
|
| 58 |
+
(this as any)._fullyLoaded = false;
|
| 59 |
+
(this as any)._loadedFields = new Set(fields);
|
| 60 |
+
return this;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
static refer(id: string | number): PaymentAttempt {
|
| 64 |
+
return new PaymentAttempt({ id: String(id) } as Partial<PaymentAttempt>);
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
/** @internal Generated Runtime Module fixed-ID construction capability. */
|
| 68 |
+
static teaqlBootstrapNew(id: string | number): PaymentAttempt {
|
| 69 |
+
return new PaymentAttempt().updateId(String(id));
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
markForDeletion(): this {
|
| 73 |
+
(this as any)._action = "Delete";
|
| 74 |
+
(this as any)._root.markAsDeleted(this.teaqlEntityKey());
|
| 75 |
+
return this;
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
auditAs(comment: string): this {
|
| 79 |
+
new MutationIntent(comment);
|
| 80 |
+
(this as any)._comment = comment;
|
| 81 |
+
return this;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
async save(context: UserContext): Promise<PaymentAttempt> {
|
| 85 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 86 |
+
return service.executeGraphSave(new MutationIntent((this as any)._comment), async (graph) => {
|
| 87 |
+
this.teaqlPreflightGraph(context, service, graph);
|
| 88 |
+
return this.teaqlSaveWithinGraph(context, service, graph);
|
| 89 |
+
});
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
/** @internal Validates and fixes the complete graph before its first mutation. */
|
| 93 |
+
teaqlPreflightGraph(context: UserContext, service: TeaQLDataService, graph: GraphMutationSession, parent?: MutationTraceScope): void {
|
| 94 |
+
if (!parent) new MutationIntent((this as any)._comment);
|
| 95 |
+
const action = (this as any)._action;
|
| 96 |
+
const pending = action !== "Update" || (this as any)._root.hasPending(this.teaqlEntityKey());
|
| 97 |
+
if (action === "Update" && pending) {
|
| 98 |
+
const notLoaded = [{ member: "id", canonical: "id" }, { member: "payment", canonical: "payment" }, { member: "referenceCode", canonical: "reference_code" }, { member: "version", canonical: "version" }]
|
| 99 |
+
.find(field => !this.isLoaded(field.member));
|
| 100 |
+
if (notLoaded) {
|
| 101 |
+
throw new CheckException([{
|
| 102 |
+
ruleId: "invalid_type",
|
| 103 |
+
location: ObjectLocation.property(notLoaded.canonical),
|
| 104 |
+
message: "Mutation requires a fully loaded entity",
|
| 105 |
+
}]);
|
| 106 |
+
}
|
| 107 |
+
}
|
| 108 |
+
const request = graph.request({
|
| 109 |
+
entity: "PaymentAttempt", action,
|
| 110 |
+
payload: action === "Update"
|
| 111 |
+
? (this as any)._root.change(this.teaqlEntityKey())
|
| 112 |
+
: this.teaqlMutationPayload(),
|
| 113 |
+
id: (this as any).id, version: (this as any).version,
|
| 114 |
+
comment: (this as any)._comment,
|
| 115 |
+
ledgerKey: this.teaqlEntityKey(), ledgerRoot: (this as any)._root,
|
| 116 |
+
}, parent, (this as any)._comment).withLoadedSnapshot(LoadedScalarSnapshot.forEntity(this) ?? new LoadedScalarSnapshot());
|
| 117 |
+
if (pending) service.preflightMutation(request);
|
| 118 |
+
const scope = request.scopeFor(this.teaqlEntityKey());
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
/** @internal Used by generated relation cascades inside the root graph transaction. */
|
| 122 |
+
async teaqlSaveWithinGraph(context: UserContext, service: TeaQLDataService, graph: GraphMutationSession, parent?: MutationTraceScope): Promise<PaymentAttempt> {
|
| 123 |
+
if (!parent) new MutationIntent((this as any)._comment);
|
| 124 |
+
const action = (this as any)._action;
|
| 125 |
+
const ledgerPayload = (this as any)._root.change(this.teaqlEntityKey());
|
| 126 |
+
const mutation = {
|
| 127 |
+
entity: "PaymentAttempt",
|
| 128 |
+
action: (this as any)._action,
|
| 129 |
+
payload: action === "Update" ? ledgerPayload : this.teaqlMutationPayload(),
|
| 130 |
+
id: (this as any).id,
|
| 131 |
+
version: (this as any).version,
|
| 132 |
+
comment: (this as any)._comment
|
| 133 |
+
,ledgerKey: this.teaqlEntityKey()
|
| 134 |
+
,ledgerRoot: (this as any)._root
|
| 135 |
+
};
|
| 136 |
+
const request = graph.request(mutation, parent, (this as any)._comment)
|
| 137 |
+
.withLoadedSnapshot(LoadedScalarSnapshot.forEntity(this) ?? new LoadedScalarSnapshot());
|
| 138 |
+
if (action === "Update" && !(this as any)._root.hasPending(this.teaqlEntityKey())) {
|
| 139 |
+
const scope = request.scopeFor(this.teaqlEntityKey());
|
| 140 |
+
return this;
|
| 141 |
+
}
|
| 142 |
+
const result = await service.executeMutation(request);
|
| 143 |
+
for (const [field, value] of Object.entries(mutation.payload as Record<string, unknown>)) {
|
| 144 |
+
if (field !== "id" && field !== "version") (this as any)._root.set(this.teaqlEntityKey(), field, value);
|
| 145 |
+
}
|
| 146 |
+
if (!result.persistedRecord) {
|
| 147 |
+
throw new Error("Mutation did not return the authoritative persisted record");
|
| 148 |
+
}
|
| 149 |
+
const rollbackState = {
|
| 150 |
+
payload: this.teaqlMutationPayload(),
|
| 151 |
+
ledgerId: (this as any)._ledgerId,
|
| 152 |
+
action: (this as any)._action,
|
| 153 |
+
loadedFields: new Set((this as any)._loadedFields),
|
| 154 |
+
fullyLoaded: (this as any)._fullyLoaded,
|
| 155 |
+
loadedSnapshot: LoadedScalarSnapshot.forEntity(this),
|
| 156 |
+
};
|
| 157 |
+
const oldKey = this.teaqlEntityKey();
|
| 158 |
+
Object.assign(this, result.persistedRecord);
|
| 159 |
+
LoadedScalarSnapshot.captureFor(this, this.teaqlMutationPayload());
|
| 160 |
+
(this as any)._ledgerId = (this as any).id ?? (this as any)._ledgerId;
|
| 161 |
+
const newKey = this.teaqlEntityKey();
|
| 162 |
+
(this as any)._root.rekey(oldKey, newKey);
|
| 163 |
+
service.afterGraphRollback(() => {
|
| 164 |
+
Object.assign(this, rollbackState.payload);
|
| 165 |
+
(this as any)._ledgerId = rollbackState.ledgerId;
|
| 166 |
+
(this as any)._action = rollbackState.action;
|
| 167 |
+
(this as any)._loadedFields = rollbackState.loadedFields;
|
| 168 |
+
(this as any)._fullyLoaded = rollbackState.fullyLoaded;
|
| 169 |
+
LoadedScalarSnapshot.restoreFor(this, rollbackState.loadedSnapshot);
|
| 170 |
+
(this as any)._root.rekey(newKey, oldKey);
|
| 171 |
+
});
|
| 172 |
+
(this as any)._loadedFields = new Set(Object.keys(result.persistedRecord));
|
| 173 |
+
(this as any)._fullyLoaded = false;
|
| 174 |
+
if (mutation.action !== "Delete") (this as any)._action = "Update";
|
| 175 |
+
const scope = request.scopeFor(newKey);
|
| 176 |
+
service.afterGraphCommit(() => {
|
| 177 |
+
(this as any)._root.clearEntity(newKey);
|
| 178 |
+
if ((this as any).version !== undefined) (this as any)._root.acceptCommittedVersion(newKey, Number((this as any).version));
|
| 179 |
+
});
|
| 180 |
+
return this;
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
private teaqlMutationPayload(): Record<string, unknown> {
|
| 184 |
+
return {
|
| 185 |
+
"id": this.id,
|
| 186 |
+
"payment": this.payment,
|
| 187 |
+
"reference_code": this.referenceCode,
|
| 188 |
+
"version": this.version
|
| 189 |
+
};
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
updateId(value: string): this {
|
| 193 |
+
this.id = value;
|
| 194 |
+
this.markLoaded("id");
|
| 195 |
+
(this as any)._root.set(this.teaqlEntityKey(), "id", value);
|
| 196 |
+
return this;
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
updateReferenceCode(value: string): this {
|
| 200 |
+
this.referenceCode = value;
|
| 201 |
+
this.markLoaded("referenceCode");
|
| 202 |
+
(this as any)._root.set(this.teaqlEntityKey(), "reference_code", value);
|
| 203 |
+
return this;
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
updateVersion(value: number): this {
|
| 207 |
+
this.version = value;
|
| 208 |
+
this.markLoaded("version");
|
| 209 |
+
(this as any)._root.set(this.teaqlEntityKey(), "version", value);
|
| 210 |
+
return this;
|
| 211 |
+
}
|
| 212 |
+
updatePayment(value: any): this {
|
| 213 |
+
this.payment = value?.id ?? value;
|
| 214 |
+
this.markLoaded("payment");
|
| 215 |
+
(this as any)._root.set(this.teaqlEntityKey(), "payment", this.payment);
|
| 216 |
+
return this;
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
}
|
source/teaql-ts/examples/trace-chain/lib/src/generated/models/Platform.ts
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { CheckException, EntityKey, EntityRoot, GraphMutationSession, LoadedScalarSnapshot, MutationIntent, MutationTraceScope, ObjectLocation, SmartList, TeaQLDataService, UserContext } from '../../teaql-ts';
|
| 2 |
+
import { CustomerOrder } from './CustomerOrder';
|
| 3 |
+
|
| 4 |
+
export class Platform {
|
| 5 |
+
private static teaqlTemporaryId = 0;
|
| 6 |
+
id?: string;
|
| 7 |
+
name?: string;
|
| 8 |
+
version?: number;
|
| 9 |
+
|
| 10 |
+
constructor(init?: Partial<Platform>) {
|
| 11 |
+
Object.defineProperty(this, "_action", { value: init && init.id ? "Update" : "Create", writable: true, enumerable: false });
|
| 12 |
+
Object.defineProperty(this, "_comment", { value: undefined, writable: true, enumerable: false });
|
| 13 |
+
Object.defineProperty(this, "_fullyLoaded", { value: !init || !init.id, writable: true, enumerable: false });
|
| 14 |
+
Object.defineProperty(this, "_loadedFields", { value: new Set(Object.keys(init || {})), writable: true, enumerable: false });
|
| 15 |
+
Object.defineProperty(this, "_root", { value: new EntityRoot(), writable: true, enumerable: false });
|
| 16 |
+
Object.defineProperty(this, "_ledgerId", { value: init?.id ?? --Platform.teaqlTemporaryId, writable: true, enumerable: false });
|
| 17 |
+
Object.defineProperty(this, "_customerOrderList", { value: init?.id ? SmartList.empty() : new SmartList(), writable: true, enumerable: false });
|
| 18 |
+
if (init) {
|
| 19 |
+
const fields: Record<string, unknown> = { ...(init as Record<string, unknown>) };
|
| 20 |
+
delete fields["customerOrderList"];
|
| 21 |
+
Object.assign(this, fields);
|
| 22 |
+
if (Array.isArray((init as any).customerOrderList)) {
|
| 23 |
+
const selected = (init as any).customerOrderList;
|
| 24 |
+
(this as any)._customerOrderList = new SmartList(selected.map(
|
| 25 |
+
(child: unknown) => child instanceof CustomerOrder
|
| 26 |
+
? child
|
| 27 |
+
: CustomerOrder.fromRecord(child as Record<string, unknown>),
|
| 28 |
+
), { totalCount: selected.totalCount, aggregations: selected.aggregations,
|
| 29 |
+
summary: selected.summary, facets: selected.facets, isLoaded: selected.isLoaded ?? true });
|
| 30 |
+
this.markLoaded("customerOrderList");
|
| 31 |
+
}
|
| 32 |
+
}
|
| 33 |
+
const key = this.teaqlEntityKey();
|
| 34 |
+
if ((this as any)._action === "Create") (this as any)._root.markAsNew(key);
|
| 35 |
+
else if ((this as any).version !== undefined) (this as any)._root.setOriginalVersion(key, Number((this as any).version));
|
| 36 |
+
LoadedScalarSnapshot.captureFor(this, this.teaqlMutationPayload());
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
private teaqlEntityKey(): EntityKey { return { entity: "Platform", id: (this as any)._ledgerId }; }
|
| 40 |
+
private teaqlAttachRoot(root: EntityRoot): this {
|
| 41 |
+
if ((this as any)._root !== root) {
|
| 42 |
+
root.mergeEntityFrom((this as any)._root, this.teaqlEntityKey());
|
| 43 |
+
(this as any)._root = root;
|
| 44 |
+
}
|
| 45 |
+
for (const child of (this as any)._customerOrderList) child.teaqlAttachRoot(root);
|
| 46 |
+
return this;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
static fromRecord(record: Record<string, unknown>, root?: EntityRoot): Platform {
|
| 50 |
+
const entity = new Platform(record as Partial<Platform>);
|
| 51 |
+
return root ? entity.teaqlAttachRoot(root) : entity;
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
isLoaded(field: string): boolean {
|
| 55 |
+
return (this as any)._fullyLoaded || (this as any)._loadedFields.has(field);
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
markLoaded(...fields: string[]): this {
|
| 59 |
+
for (const field of fields) (this as any)._loadedFields.add(field);
|
| 60 |
+
return this;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
markLoadedOnly(...fields: string[]): this {
|
| 64 |
+
(this as any)._fullyLoaded = false;
|
| 65 |
+
(this as any)._loadedFields = new Set(fields);
|
| 66 |
+
return this;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
static refer(id: string | number): Platform {
|
| 70 |
+
return new Platform({ id: String(id) } as Partial<Platform>);
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
/** @internal Generated Runtime Module fixed-ID construction capability. */
|
| 74 |
+
static teaqlBootstrapNew(id: string | number): Platform {
|
| 75 |
+
return new Platform().updateId(String(id));
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
markForDeletion(): this {
|
| 79 |
+
(this as any)._action = "Delete";
|
| 80 |
+
(this as any)._root.markAsDeleted(this.teaqlEntityKey());
|
| 81 |
+
return this;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
auditAs(comment: string): this {
|
| 85 |
+
new MutationIntent(comment);
|
| 86 |
+
(this as any)._comment = comment;
|
| 87 |
+
return this;
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
async save(context: UserContext): Promise<Platform> {
|
| 91 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 92 |
+
return service.executeGraphSave(new MutationIntent((this as any)._comment), async (graph) => {
|
| 93 |
+
this.teaqlPreflightGraph(context, service, graph);
|
| 94 |
+
return this.teaqlSaveWithinGraph(context, service, graph);
|
| 95 |
+
});
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
/** @internal Validates and fixes the complete graph before its first mutation. */
|
| 99 |
+
teaqlPreflightGraph(context: UserContext, service: TeaQLDataService, graph: GraphMutationSession, parent?: MutationTraceScope): void {
|
| 100 |
+
if (!parent) new MutationIntent((this as any)._comment);
|
| 101 |
+
const action = (this as any)._action;
|
| 102 |
+
const pending = action !== "Update" || (this as any)._root.hasPending(this.teaqlEntityKey());
|
| 103 |
+
if (action === "Update" && pending) {
|
| 104 |
+
const notLoaded = [{ member: "id", canonical: "id" }, { member: "name", canonical: "name" }, { member: "version", canonical: "version" }]
|
| 105 |
+
.find(field => !this.isLoaded(field.member));
|
| 106 |
+
if (notLoaded) {
|
| 107 |
+
throw new CheckException([{
|
| 108 |
+
ruleId: "invalid_type",
|
| 109 |
+
location: ObjectLocation.property(notLoaded.canonical),
|
| 110 |
+
message: "Mutation requires a fully loaded entity",
|
| 111 |
+
}]);
|
| 112 |
+
}
|
| 113 |
+
}
|
| 114 |
+
const request = graph.request({
|
| 115 |
+
entity: "Platform", action,
|
| 116 |
+
payload: action === "Update"
|
| 117 |
+
? (this as any)._root.change(this.teaqlEntityKey())
|
| 118 |
+
: this.teaqlMutationPayload(),
|
| 119 |
+
id: (this as any).id, version: (this as any).version,
|
| 120 |
+
comment: (this as any)._comment,
|
| 121 |
+
ledgerKey: this.teaqlEntityKey(), ledgerRoot: (this as any)._root,
|
| 122 |
+
}, parent, (this as any)._comment).withLoadedSnapshot(LoadedScalarSnapshot.forEntity(this) ?? new LoadedScalarSnapshot());
|
| 123 |
+
if (pending) service.preflightMutation(request);
|
| 124 |
+
const scope = request.scopeFor(this.teaqlEntityKey());
|
| 125 |
+
for (const [index, child] of (this as any)._customerOrderList.entries()) {
|
| 126 |
+
child.teaqlAttachRoot((this as any)._root);
|
| 127 |
+
const currentParent = child.platform;
|
| 128 |
+
if (this.id === undefined || !child.isLoaded("platform") || (typeof currentParent === "object" && currentParent !== null
|
| 129 |
+
? currentParent.id : currentParent) !== this.id) child.updatePlatform(this);
|
| 130 |
+
try { child.teaqlPreflightGraph(context, service, graph, scope); }
|
| 131 |
+
catch (error) {
|
| 132 |
+
if (!(error instanceof CheckException)) throw error;
|
| 133 |
+
const prefix = ObjectLocation.property("customer_order_list").index(index);
|
| 134 |
+
throw new CheckException(error.violations.map(violation => ({
|
| 135 |
+
...violation, location: violation.location.prefixedBy(prefix),
|
| 136 |
+
})));
|
| 137 |
+
}
|
| 138 |
+
}
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
/** @internal Used by generated relation cascades inside the root graph transaction. */
|
| 142 |
+
async teaqlSaveWithinGraph(context: UserContext, service: TeaQLDataService, graph: GraphMutationSession, parent?: MutationTraceScope): Promise<Platform> {
|
| 143 |
+
if (!parent) new MutationIntent((this as any)._comment);
|
| 144 |
+
const action = (this as any)._action;
|
| 145 |
+
const ledgerPayload = (this as any)._root.change(this.teaqlEntityKey());
|
| 146 |
+
const mutation = {
|
| 147 |
+
entity: "Platform",
|
| 148 |
+
action: (this as any)._action,
|
| 149 |
+
payload: action === "Update" ? ledgerPayload : this.teaqlMutationPayload(),
|
| 150 |
+
id: (this as any).id,
|
| 151 |
+
version: (this as any).version,
|
| 152 |
+
comment: (this as any)._comment
|
| 153 |
+
,ledgerKey: this.teaqlEntityKey()
|
| 154 |
+
,ledgerRoot: (this as any)._root
|
| 155 |
+
};
|
| 156 |
+
const request = graph.request(mutation, parent, (this as any)._comment)
|
| 157 |
+
.withLoadedSnapshot(LoadedScalarSnapshot.forEntity(this) ?? new LoadedScalarSnapshot());
|
| 158 |
+
if (action === "Update" && !(this as any)._root.hasPending(this.teaqlEntityKey())) {
|
| 159 |
+
const scope = request.scopeFor(this.teaqlEntityKey());
|
| 160 |
+
for (const [index, child] of (this as any)._customerOrderList.entries()) {
|
| 161 |
+
child.teaqlAttachRoot((this as any)._root);
|
| 162 |
+
const currentParent = child.platform;
|
| 163 |
+
if (this.id === undefined || !child.isLoaded("platform") || (typeof currentParent === "object" && currentParent !== null
|
| 164 |
+
? currentParent.id : currentParent) !== this.id) child.updatePlatform(this);
|
| 165 |
+
try { await child.teaqlSaveWithinGraph(context, service, graph, scope); }
|
| 166 |
+
catch (error) {
|
| 167 |
+
if (!(error instanceof CheckException)) throw error;
|
| 168 |
+
const prefix = ObjectLocation.property("customer_order_list").index(index);
|
| 169 |
+
throw new CheckException(error.violations.map(violation => ({
|
| 170 |
+
...violation, location: violation.location.prefixedBy(prefix),
|
| 171 |
+
})));
|
| 172 |
+
}
|
| 173 |
+
}
|
| 174 |
+
return this;
|
| 175 |
+
}
|
| 176 |
+
const result = await service.executeMutation(request);
|
| 177 |
+
for (const [field, value] of Object.entries(mutation.payload as Record<string, unknown>)) {
|
| 178 |
+
if (field !== "id" && field !== "version") (this as any)._root.set(this.teaqlEntityKey(), field, value);
|
| 179 |
+
}
|
| 180 |
+
if (!result.persistedRecord) {
|
| 181 |
+
throw new Error("Mutation did not return the authoritative persisted record");
|
| 182 |
+
}
|
| 183 |
+
const rollbackState = {
|
| 184 |
+
payload: this.teaqlMutationPayload(),
|
| 185 |
+
ledgerId: (this as any)._ledgerId,
|
| 186 |
+
action: (this as any)._action,
|
| 187 |
+
loadedFields: new Set((this as any)._loadedFields),
|
| 188 |
+
fullyLoaded: (this as any)._fullyLoaded,
|
| 189 |
+
loadedSnapshot: LoadedScalarSnapshot.forEntity(this),
|
| 190 |
+
};
|
| 191 |
+
const oldKey = this.teaqlEntityKey();
|
| 192 |
+
Object.assign(this, result.persistedRecord);
|
| 193 |
+
LoadedScalarSnapshot.captureFor(this, this.teaqlMutationPayload());
|
| 194 |
+
(this as any)._ledgerId = (this as any).id ?? (this as any)._ledgerId;
|
| 195 |
+
const newKey = this.teaqlEntityKey();
|
| 196 |
+
(this as any)._root.rekey(oldKey, newKey);
|
| 197 |
+
service.afterGraphRollback(() => {
|
| 198 |
+
Object.assign(this, rollbackState.payload);
|
| 199 |
+
(this as any)._ledgerId = rollbackState.ledgerId;
|
| 200 |
+
(this as any)._action = rollbackState.action;
|
| 201 |
+
(this as any)._loadedFields = rollbackState.loadedFields;
|
| 202 |
+
(this as any)._fullyLoaded = rollbackState.fullyLoaded;
|
| 203 |
+
LoadedScalarSnapshot.restoreFor(this, rollbackState.loadedSnapshot);
|
| 204 |
+
(this as any)._root.rekey(newKey, oldKey);
|
| 205 |
+
});
|
| 206 |
+
(this as any)._loadedFields = new Set(Object.keys(result.persistedRecord));
|
| 207 |
+
(this as any)._fullyLoaded = false;
|
| 208 |
+
if (mutation.action !== "Delete") (this as any)._action = "Update";
|
| 209 |
+
const scope = request.scopeFor(newKey);
|
| 210 |
+
for (const [index, child] of (this as any)._customerOrderList.entries()) {
|
| 211 |
+
child.teaqlAttachRoot((this as any)._root);
|
| 212 |
+
const currentParent = child.platform;
|
| 213 |
+
if (this.id === undefined || !child.isLoaded("platform") || (typeof currentParent === "object" && currentParent !== null
|
| 214 |
+
? currentParent.id : currentParent) !== this.id) child.updatePlatform(this);
|
| 215 |
+
try { await child.teaqlSaveWithinGraph(context, service, graph, scope); }
|
| 216 |
+
catch (error) {
|
| 217 |
+
if (!(error instanceof CheckException)) throw error;
|
| 218 |
+
const prefix = ObjectLocation.property("customer_order_list").index(index);
|
| 219 |
+
throw new CheckException(error.violations.map(violation => ({
|
| 220 |
+
...violation, location: violation.location.prefixedBy(prefix),
|
| 221 |
+
})));
|
| 222 |
+
}
|
| 223 |
+
}
|
| 224 |
+
service.afterGraphCommit(() => {
|
| 225 |
+
(this as any)._root.clearEntity(newKey);
|
| 226 |
+
if ((this as any).version !== undefined) (this as any)._root.acceptCommittedVersion(newKey, Number((this as any).version));
|
| 227 |
+
});
|
| 228 |
+
return this;
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
private teaqlMutationPayload(): Record<string, unknown> {
|
| 232 |
+
return {
|
| 233 |
+
"id": this.id,
|
| 234 |
+
"name": this.name,
|
| 235 |
+
"version": this.version
|
| 236 |
+
};
|
| 237 |
+
}
|
| 238 |
+
|
| 239 |
+
updateId(value: string): this {
|
| 240 |
+
this.id = value;
|
| 241 |
+
this.markLoaded("id");
|
| 242 |
+
(this as any)._root.set(this.teaqlEntityKey(), "id", value);
|
| 243 |
+
return this;
|
| 244 |
+
}
|
| 245 |
+
|
| 246 |
+
updateName(value: string): this {
|
| 247 |
+
this.name = value;
|
| 248 |
+
this.markLoaded("name");
|
| 249 |
+
(this as any)._root.set(this.teaqlEntityKey(), "name", value);
|
| 250 |
+
return this;
|
| 251 |
+
}
|
| 252 |
+
|
| 253 |
+
updateVersion(value: number): this {
|
| 254 |
+
this.version = value;
|
| 255 |
+
this.markLoaded("version");
|
| 256 |
+
(this as any)._root.set(this.teaqlEntityKey(), "version", value);
|
| 257 |
+
return this;
|
| 258 |
+
}
|
| 259 |
+
customerOrderList(): SmartList<CustomerOrder> {
|
| 260 |
+
return (this as any)._customerOrderList;
|
| 261 |
+
}
|
| 262 |
+
}
|
source/teaql-ts/examples/trace-chain/lib/src/generated/models/Shipment.ts
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { CheckException, EntityKey, EntityRoot, GraphMutationSession, LoadedScalarSnapshot, MutationIntent, MutationTraceScope, ObjectLocation, SmartList, TeaQLDataService, UserContext } from '../../teaql-ts';
|
| 2 |
+
import { CustomerOrder } from './CustomerOrder';
|
| 3 |
+
|
| 4 |
+
export class Shipment {
|
| 5 |
+
private static teaqlTemporaryId = 0;
|
| 6 |
+
id?: string;
|
| 7 |
+
customerOrder?: CustomerOrder | string;
|
| 8 |
+
referenceCode?: string;
|
| 9 |
+
version?: number;
|
| 10 |
+
|
| 11 |
+
constructor(init?: Partial<Shipment>) {
|
| 12 |
+
Object.defineProperty(this, "_action", { value: init && init.id ? "Update" : "Create", writable: true, enumerable: false });
|
| 13 |
+
Object.defineProperty(this, "_comment", { value: undefined, writable: true, enumerable: false });
|
| 14 |
+
Object.defineProperty(this, "_fullyLoaded", { value: !init || !init.id, writable: true, enumerable: false });
|
| 15 |
+
Object.defineProperty(this, "_loadedFields", { value: new Set(Object.keys(init || {})), writable: true, enumerable: false });
|
| 16 |
+
Object.defineProperty(this, "_root", { value: new EntityRoot(), writable: true, enumerable: false });
|
| 17 |
+
Object.defineProperty(this, "_ledgerId", { value: init?.id ?? --Shipment.teaqlTemporaryId, writable: true, enumerable: false });
|
| 18 |
+
if (init) {
|
| 19 |
+
const fields: Record<string, unknown> = { ...(init as Record<string, unknown>) };
|
| 20 |
+
Object.assign(this, fields);
|
| 21 |
+
if ((init as any).customerOrder && typeof (init as any).customerOrder === "object") {
|
| 22 |
+
this.customerOrder = (init as any).customerOrder instanceof CustomerOrder
|
| 23 |
+
? (init as any).customerOrder
|
| 24 |
+
: CustomerOrder.fromRecord((init as any).customerOrder);
|
| 25 |
+
this.markLoaded("customerOrder");
|
| 26 |
+
}
|
| 27 |
+
}
|
| 28 |
+
const key = this.teaqlEntityKey();
|
| 29 |
+
if ((this as any)._action === "Create") (this as any)._root.markAsNew(key);
|
| 30 |
+
else if ((this as any).version !== undefined) (this as any)._root.setOriginalVersion(key, Number((this as any).version));
|
| 31 |
+
LoadedScalarSnapshot.captureFor(this, this.teaqlMutationPayload());
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
private teaqlEntityKey(): EntityKey { return { entity: "Shipment", id: (this as any)._ledgerId }; }
|
| 35 |
+
private teaqlAttachRoot(root: EntityRoot): this {
|
| 36 |
+
if ((this as any)._root !== root) {
|
| 37 |
+
root.mergeEntityFrom((this as any)._root, this.teaqlEntityKey());
|
| 38 |
+
(this as any)._root = root;
|
| 39 |
+
}
|
| 40 |
+
return this;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
static fromRecord(record: Record<string, unknown>, root?: EntityRoot): Shipment {
|
| 44 |
+
const entity = new Shipment(record as Partial<Shipment>);
|
| 45 |
+
return root ? entity.teaqlAttachRoot(root) : entity;
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
isLoaded(field: string): boolean {
|
| 49 |
+
return (this as any)._fullyLoaded || (this as any)._loadedFields.has(field);
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
markLoaded(...fields: string[]): this {
|
| 53 |
+
for (const field of fields) (this as any)._loadedFields.add(field);
|
| 54 |
+
return this;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
markLoadedOnly(...fields: string[]): this {
|
| 58 |
+
(this as any)._fullyLoaded = false;
|
| 59 |
+
(this as any)._loadedFields = new Set(fields);
|
| 60 |
+
return this;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
static refer(id: string | number): Shipment {
|
| 64 |
+
return new Shipment({ id: String(id) } as Partial<Shipment>);
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
/** @internal Generated Runtime Module fixed-ID construction capability. */
|
| 68 |
+
static teaqlBootstrapNew(id: string | number): Shipment {
|
| 69 |
+
return new Shipment().updateId(String(id));
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
markForDeletion(): this {
|
| 73 |
+
(this as any)._action = "Delete";
|
| 74 |
+
(this as any)._root.markAsDeleted(this.teaqlEntityKey());
|
| 75 |
+
return this;
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
auditAs(comment: string): this {
|
| 79 |
+
new MutationIntent(comment);
|
| 80 |
+
(this as any)._comment = comment;
|
| 81 |
+
return this;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
async save(context: UserContext): Promise<Shipment> {
|
| 85 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 86 |
+
return service.executeGraphSave(new MutationIntent((this as any)._comment), async (graph) => {
|
| 87 |
+
this.teaqlPreflightGraph(context, service, graph);
|
| 88 |
+
return this.teaqlSaveWithinGraph(context, service, graph);
|
| 89 |
+
});
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
/** @internal Validates and fixes the complete graph before its first mutation. */
|
| 93 |
+
teaqlPreflightGraph(context: UserContext, service: TeaQLDataService, graph: GraphMutationSession, parent?: MutationTraceScope): void {
|
| 94 |
+
if (!parent) new MutationIntent((this as any)._comment);
|
| 95 |
+
const action = (this as any)._action;
|
| 96 |
+
const pending = action !== "Update" || (this as any)._root.hasPending(this.teaqlEntityKey());
|
| 97 |
+
if (action === "Update" && pending) {
|
| 98 |
+
const notLoaded = [{ member: "id", canonical: "id" }, { member: "customerOrder", canonical: "customer_order" }, { member: "referenceCode", canonical: "reference_code" }, { member: "version", canonical: "version" }]
|
| 99 |
+
.find(field => !this.isLoaded(field.member));
|
| 100 |
+
if (notLoaded) {
|
| 101 |
+
throw new CheckException([{
|
| 102 |
+
ruleId: "invalid_type",
|
| 103 |
+
location: ObjectLocation.property(notLoaded.canonical),
|
| 104 |
+
message: "Mutation requires a fully loaded entity",
|
| 105 |
+
}]);
|
| 106 |
+
}
|
| 107 |
+
}
|
| 108 |
+
const request = graph.request({
|
| 109 |
+
entity: "Shipment", action,
|
| 110 |
+
payload: action === "Update"
|
| 111 |
+
? (this as any)._root.change(this.teaqlEntityKey())
|
| 112 |
+
: this.teaqlMutationPayload(),
|
| 113 |
+
id: (this as any).id, version: (this as any).version,
|
| 114 |
+
comment: (this as any)._comment,
|
| 115 |
+
ledgerKey: this.teaqlEntityKey(), ledgerRoot: (this as any)._root,
|
| 116 |
+
}, parent, (this as any)._comment).withLoadedSnapshot(LoadedScalarSnapshot.forEntity(this) ?? new LoadedScalarSnapshot());
|
| 117 |
+
if (pending) service.preflightMutation(request);
|
| 118 |
+
const scope = request.scopeFor(this.teaqlEntityKey());
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
/** @internal Used by generated relation cascades inside the root graph transaction. */
|
| 122 |
+
async teaqlSaveWithinGraph(context: UserContext, service: TeaQLDataService, graph: GraphMutationSession, parent?: MutationTraceScope): Promise<Shipment> {
|
| 123 |
+
if (!parent) new MutationIntent((this as any)._comment);
|
| 124 |
+
const action = (this as any)._action;
|
| 125 |
+
const ledgerPayload = (this as any)._root.change(this.teaqlEntityKey());
|
| 126 |
+
const mutation = {
|
| 127 |
+
entity: "Shipment",
|
| 128 |
+
action: (this as any)._action,
|
| 129 |
+
payload: action === "Update" ? ledgerPayload : this.teaqlMutationPayload(),
|
| 130 |
+
id: (this as any).id,
|
| 131 |
+
version: (this as any).version,
|
| 132 |
+
comment: (this as any)._comment
|
| 133 |
+
,ledgerKey: this.teaqlEntityKey()
|
| 134 |
+
,ledgerRoot: (this as any)._root
|
| 135 |
+
};
|
| 136 |
+
const request = graph.request(mutation, parent, (this as any)._comment)
|
| 137 |
+
.withLoadedSnapshot(LoadedScalarSnapshot.forEntity(this) ?? new LoadedScalarSnapshot());
|
| 138 |
+
if (action === "Update" && !(this as any)._root.hasPending(this.teaqlEntityKey())) {
|
| 139 |
+
const scope = request.scopeFor(this.teaqlEntityKey());
|
| 140 |
+
return this;
|
| 141 |
+
}
|
| 142 |
+
const result = await service.executeMutation(request);
|
| 143 |
+
for (const [field, value] of Object.entries(mutation.payload as Record<string, unknown>)) {
|
| 144 |
+
if (field !== "id" && field !== "version") (this as any)._root.set(this.teaqlEntityKey(), field, value);
|
| 145 |
+
}
|
| 146 |
+
if (!result.persistedRecord) {
|
| 147 |
+
throw new Error("Mutation did not return the authoritative persisted record");
|
| 148 |
+
}
|
| 149 |
+
const rollbackState = {
|
| 150 |
+
payload: this.teaqlMutationPayload(),
|
| 151 |
+
ledgerId: (this as any)._ledgerId,
|
| 152 |
+
action: (this as any)._action,
|
| 153 |
+
loadedFields: new Set((this as any)._loadedFields),
|
| 154 |
+
fullyLoaded: (this as any)._fullyLoaded,
|
| 155 |
+
loadedSnapshot: LoadedScalarSnapshot.forEntity(this),
|
| 156 |
+
};
|
| 157 |
+
const oldKey = this.teaqlEntityKey();
|
| 158 |
+
Object.assign(this, result.persistedRecord);
|
| 159 |
+
LoadedScalarSnapshot.captureFor(this, this.teaqlMutationPayload());
|
| 160 |
+
(this as any)._ledgerId = (this as any).id ?? (this as any)._ledgerId;
|
| 161 |
+
const newKey = this.teaqlEntityKey();
|
| 162 |
+
(this as any)._root.rekey(oldKey, newKey);
|
| 163 |
+
service.afterGraphRollback(() => {
|
| 164 |
+
Object.assign(this, rollbackState.payload);
|
| 165 |
+
(this as any)._ledgerId = rollbackState.ledgerId;
|
| 166 |
+
(this as any)._action = rollbackState.action;
|
| 167 |
+
(this as any)._loadedFields = rollbackState.loadedFields;
|
| 168 |
+
(this as any)._fullyLoaded = rollbackState.fullyLoaded;
|
| 169 |
+
LoadedScalarSnapshot.restoreFor(this, rollbackState.loadedSnapshot);
|
| 170 |
+
(this as any)._root.rekey(newKey, oldKey);
|
| 171 |
+
});
|
| 172 |
+
(this as any)._loadedFields = new Set(Object.keys(result.persistedRecord));
|
| 173 |
+
(this as any)._fullyLoaded = false;
|
| 174 |
+
if (mutation.action !== "Delete") (this as any)._action = "Update";
|
| 175 |
+
const scope = request.scopeFor(newKey);
|
| 176 |
+
service.afterGraphCommit(() => {
|
| 177 |
+
(this as any)._root.clearEntity(newKey);
|
| 178 |
+
if ((this as any).version !== undefined) (this as any)._root.acceptCommittedVersion(newKey, Number((this as any).version));
|
| 179 |
+
});
|
| 180 |
+
return this;
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
private teaqlMutationPayload(): Record<string, unknown> {
|
| 184 |
+
return {
|
| 185 |
+
"id": this.id,
|
| 186 |
+
"customer_order": this.customerOrder,
|
| 187 |
+
"reference_code": this.referenceCode,
|
| 188 |
+
"version": this.version
|
| 189 |
+
};
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
updateId(value: string): this {
|
| 193 |
+
this.id = value;
|
| 194 |
+
this.markLoaded("id");
|
| 195 |
+
(this as any)._root.set(this.teaqlEntityKey(), "id", value);
|
| 196 |
+
return this;
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
updateReferenceCode(value: string): this {
|
| 200 |
+
this.referenceCode = value;
|
| 201 |
+
this.markLoaded("referenceCode");
|
| 202 |
+
(this as any)._root.set(this.teaqlEntityKey(), "reference_code", value);
|
| 203 |
+
return this;
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
updateVersion(value: number): this {
|
| 207 |
+
this.version = value;
|
| 208 |
+
this.markLoaded("version");
|
| 209 |
+
(this as any)._root.set(this.teaqlEntityKey(), "version", value);
|
| 210 |
+
return this;
|
| 211 |
+
}
|
| 212 |
+
updateCustomerOrder(value: any): this {
|
| 213 |
+
this.customerOrder = value?.id ?? value;
|
| 214 |
+
this.markLoaded("customerOrder");
|
| 215 |
+
(this as any)._root.set(this.teaqlEntityKey(), "customer_order", this.customerOrder);
|
| 216 |
+
return this;
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
}
|
source/teaql-ts/examples/trace-chain/lib/src/generated/requests/CustomerOrderRequest.ts
ADDED
|
@@ -0,0 +1,907 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { EntityRoot, SelectQuery, SmartList, TeaQLDataService, UserContext, executeRelationFacets } from '../../teaql-ts';
|
| 2 |
+
import { CustomerOrder } from '../models/CustomerOrder';
|
| 3 |
+
import { mergeGeneratedScalarSearch, DynamicSearchWarning, QueryIntent } from 'teaql-ts';
|
| 4 |
+
import { GENERATED_SEARCH_MODELS } from '../../generated-search-models';
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
export class CustomerOrderRequest {
|
| 9 |
+
private query: SelectQuery;
|
| 10 |
+
private filters: any[] = [];
|
| 11 |
+
private _purpose: string | undefined;
|
| 12 |
+
private _comment: string | undefined;
|
| 13 |
+
private _pageCountAlias: string | undefined;
|
| 14 |
+
private _pageCountMethod: "count" | "countAs" | undefined;
|
| 15 |
+
private _dynamicSearchWarnings: DynamicSearchWarning[] = [];
|
| 16 |
+
|
| 17 |
+
constructor(minimal = false) {
|
| 18 |
+
this.query = new SelectQuery("CustomerOrder");
|
| 19 |
+
this.filters.push({ version: { "$gte": 1 } });
|
| 20 |
+
if (minimal) {
|
| 21 |
+
this.selectId();
|
| 22 |
+
this.selectVersion();
|
| 23 |
+
}
|
| 24 |
+
else this.selectSelfFields();
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
comment(c: string): this {
|
| 28 |
+
this.query.comment(c);
|
| 29 |
+
this._comment = c;
|
| 30 |
+
return this;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
filterByJson(source: unknown, warn?: (warning: DynamicSearchWarning) => void): this {
|
| 34 |
+
const base = this.query.clone();
|
| 35 |
+
if (this.filters.length > 0) base.filter({ "$and": this.filters });
|
| 36 |
+
const merged = mergeGeneratedScalarSearch(base, source, GENERATED_SEARCH_MODELS, warn);
|
| 37 |
+
this.query = merged.query as SelectQuery;
|
| 38 |
+
this.filters = this.query.filterCondition ? [this.query.filterCondition] : [];
|
| 39 |
+
this._dynamicSearchWarnings.push(...merged.warnings);
|
| 40 |
+
return this;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
get dynamicSearchWarnings(): readonly DynamicSearchWarning[] {
|
| 44 |
+
return this._dynamicSearchWarnings.map(warning => ({ ...warning }));
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
purpose(p: string): ExecutableCustomerOrderRequest {
|
| 48 |
+
this.query.purpose(p);
|
| 49 |
+
this._purpose = p;
|
| 50 |
+
return new ExecutableCustomerOrderRequest(
|
| 51 |
+
(context) => context.withQueryRequest(this.query, () => this.executeForListInternal(context)),
|
| 52 |
+
(context) => context.withQueryRequest(this.query, () => this.executeForRowsInternal(context)),
|
| 53 |
+
(context, chunkSize) => this.executeForStreamInternal(context, chunkSize),
|
| 54 |
+
() => this.limit(1),
|
| 55 |
+
(c) => this.comment(c),
|
| 56 |
+
() => this.ensureIntent());
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
optimizeForContinuousPageFetch(): this {
|
| 60 |
+
this.query.optimizeForContinuousPageFetch();
|
| 61 |
+
return this;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
optimizeForContinuousPageFetchWith(namespace: string, ttlSeconds: number): this {
|
| 65 |
+
this.query.optimizeForContinuousPageFetchWith(namespace, ttlSeconds);
|
| 66 |
+
return this;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
optimizePaginationWithIdSet(): this {
|
| 70 |
+
this.query.optimizePaginationWithIdSet();
|
| 71 |
+
return this;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
optimizePaginationWithIdSetConfig(namespace: string, ttlSeconds: number, maxIds: number): this {
|
| 75 |
+
this.query.optimizePaginationWithIdSetConfig(namespace, ttlSeconds, maxIds);
|
| 76 |
+
return this;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
topNProbeParentThreshold(threshold: number): this {
|
| 80 |
+
this.query.topNProbeParentThreshold(threshold);
|
| 81 |
+
return this;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
limit(n: number): this {
|
| 85 |
+
this.query.limit(n);
|
| 86 |
+
return this;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
offset(n: number): this {
|
| 90 |
+
this.query.offset(n);
|
| 91 |
+
return this;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
toQuery(): SelectQuery {
|
| 95 |
+
if (this.filters.length > 0) {
|
| 96 |
+
this.query.filter({ "$and": this.filters });
|
| 97 |
+
}
|
| 98 |
+
return this.query;
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
withDeletedRows(): this {
|
| 102 |
+
this.filters = this.filters.filter(filter => !("version" in filter));
|
| 103 |
+
return this;
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
deletedRowsOnly(): this {
|
| 107 |
+
this.withDeletedRows();
|
| 108 |
+
this.filters.push({ version: { "$lte": -1 } });
|
| 109 |
+
return this;
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
selectSelfFields(): this {
|
| 113 |
+
this.query.select(["id", "platform", "orderNumber", "description", "version"]);
|
| 114 |
+
return this;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
selectId(): this {
|
| 118 |
+
this.query.select(["id"]);
|
| 119 |
+
return this;
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
selectOrderNumber(): this {
|
| 124 |
+
this.query.select(["orderNumber"]);
|
| 125 |
+
return this;
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
selectDescription(): this {
|
| 129 |
+
this.query.select(["description"]);
|
| 130 |
+
return this;
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
selectVersion(): this {
|
| 134 |
+
this.query.select(["version"]);
|
| 135 |
+
return this;
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
|
| 139 |
+
selectPlatformWith(request: { toQuery(): SelectQuery }): this {
|
| 140 |
+
this.query.select(["platform"]);
|
| 141 |
+
this.query.relationQuery(
|
| 142 |
+
"platform", request.toQuery(), "platform", "id", false,
|
| 143 |
+
{ kind: "relation-select", method: "selectPlatformWith", relation: "platform" });
|
| 144 |
+
return this;
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
withPlatformMatching(request: { toQuery(): SelectQuery }): this {
|
| 148 |
+
this.filters.push({
|
| 149 |
+
"platform": {
|
| 150 |
+
"$inSubquery": { query: request.toQuery(), field: "id" },
|
| 151 |
+
},
|
| 152 |
+
});
|
| 153 |
+
return this;
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
withoutPlatformMatching(request: { toQuery(): SelectQuery }): this {
|
| 157 |
+
this.filters.push({
|
| 158 |
+
"platform": {
|
| 159 |
+
"$notInSubquery": { query: request.toQuery(), field: "id" },
|
| 160 |
+
},
|
| 161 |
+
});
|
| 162 |
+
return this;
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
selectOrderItemListWith(request: { toQuery(): SelectQuery }): this {
|
| 166 |
+
this.query.relationQuery(
|
| 167 |
+
"orderItemList", request.toQuery(), "id", "customerOrder", true,
|
| 168 |
+
{ kind: "relation-select", method: "selectOrderItemListWith", relation: "orderItemList" });
|
| 169 |
+
return this;
|
| 170 |
+
}
|
| 171 |
+
selectPaymentListWith(request: { toQuery(): SelectQuery }): this {
|
| 172 |
+
this.query.relationQuery(
|
| 173 |
+
"paymentList", request.toQuery(), "id", "customerOrder", true,
|
| 174 |
+
{ kind: "relation-select", method: "selectPaymentListWith", relation: "paymentList" });
|
| 175 |
+
return this;
|
| 176 |
+
}
|
| 177 |
+
selectShipmentListWith(request: { toQuery(): SelectQuery }): this {
|
| 178 |
+
this.query.relationQuery(
|
| 179 |
+
"shipmentList", request.toQuery(), "id", "customerOrder", true,
|
| 180 |
+
{ kind: "relation-select", method: "selectShipmentListWith", relation: "shipmentList" });
|
| 181 |
+
return this;
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
haveOrderItems(): this {
|
| 185 |
+
return this.withOrderItemListMatching({
|
| 186 |
+
toQuery: () => new SelectQuery("OrderItem"),
|
| 187 |
+
});
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
haveNoOrderItems(): this {
|
| 191 |
+
return this.withoutOrderItemListMatching({
|
| 192 |
+
toQuery: () => new SelectQuery("OrderItem"),
|
| 193 |
+
});
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
withOrderItemListMatching(request: { toQuery(): SelectQuery }): this {
|
| 197 |
+
this.filters.push({
|
| 198 |
+
"id": {
|
| 199 |
+
"$inSubquery": {
|
| 200 |
+
query: request.toQuery(), field: "customerOrder",
|
| 201 |
+
},
|
| 202 |
+
},
|
| 203 |
+
});
|
| 204 |
+
return this;
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
withoutOrderItemListMatching(request: { toQuery(): SelectQuery }): this {
|
| 208 |
+
this.filters.push({
|
| 209 |
+
"id": {
|
| 210 |
+
"$notInSubquery": {
|
| 211 |
+
query: request.toQuery(), field: "customerOrder",
|
| 212 |
+
},
|
| 213 |
+
},
|
| 214 |
+
});
|
| 215 |
+
return this;
|
| 216 |
+
}
|
| 217 |
+
havePayments(): this {
|
| 218 |
+
return this.withPaymentListMatching({
|
| 219 |
+
toQuery: () => new SelectQuery("Payment"),
|
| 220 |
+
});
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
haveNoPayments(): this {
|
| 224 |
+
return this.withoutPaymentListMatching({
|
| 225 |
+
toQuery: () => new SelectQuery("Payment"),
|
| 226 |
+
});
|
| 227 |
+
}
|
| 228 |
+
|
| 229 |
+
withPaymentListMatching(request: { toQuery(): SelectQuery }): this {
|
| 230 |
+
this.filters.push({
|
| 231 |
+
"id": {
|
| 232 |
+
"$inSubquery": {
|
| 233 |
+
query: request.toQuery(), field: "customerOrder",
|
| 234 |
+
},
|
| 235 |
+
},
|
| 236 |
+
});
|
| 237 |
+
return this;
|
| 238 |
+
}
|
| 239 |
+
|
| 240 |
+
withoutPaymentListMatching(request: { toQuery(): SelectQuery }): this {
|
| 241 |
+
this.filters.push({
|
| 242 |
+
"id": {
|
| 243 |
+
"$notInSubquery": {
|
| 244 |
+
query: request.toQuery(), field: "customerOrder",
|
| 245 |
+
},
|
| 246 |
+
},
|
| 247 |
+
});
|
| 248 |
+
return this;
|
| 249 |
+
}
|
| 250 |
+
haveShipments(): this {
|
| 251 |
+
return this.withShipmentListMatching({
|
| 252 |
+
toQuery: () => new SelectQuery("Shipment"),
|
| 253 |
+
});
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
haveNoShipments(): this {
|
| 257 |
+
return this.withoutShipmentListMatching({
|
| 258 |
+
toQuery: () => new SelectQuery("Shipment"),
|
| 259 |
+
});
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
withShipmentListMatching(request: { toQuery(): SelectQuery }): this {
|
| 263 |
+
this.filters.push({
|
| 264 |
+
"id": {
|
| 265 |
+
"$inSubquery": {
|
| 266 |
+
query: request.toQuery(), field: "customerOrder",
|
| 267 |
+
},
|
| 268 |
+
},
|
| 269 |
+
});
|
| 270 |
+
return this;
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
withoutShipmentListMatching(request: { toQuery(): SelectQuery }): this {
|
| 274 |
+
this.filters.push({
|
| 275 |
+
"id": {
|
| 276 |
+
"$notInSubquery": {
|
| 277 |
+
query: request.toQuery(), field: "customerOrder",
|
| 278 |
+
},
|
| 279 |
+
},
|
| 280 |
+
});
|
| 281 |
+
return this;
|
| 282 |
+
}
|
| 283 |
+
|
| 284 |
+
countOrderItems(): this {
|
| 285 |
+
return this.countOrderItemsAs("countOrderItems");
|
| 286 |
+
}
|
| 287 |
+
|
| 288 |
+
countOrderItemsAs(alias: string): this {
|
| 289 |
+
const query = new SelectQuery("OrderItem").filter({ version: { "$gte": 1 } });
|
| 290 |
+
this.countOrderItemsWith(alias, { toQuery: () => query });
|
| 291 |
+
this.query.relationAggregates[this.query.relationAggregates.length - 1].operation = {
|
| 292 |
+
kind: "relation-count", method: "countOrderItemsAs", relation: "orderItemList", alias };
|
| 293 |
+
return this;
|
| 294 |
+
}
|
| 295 |
+
|
| 296 |
+
countOrderItemsWith(alias: string, child: { toQuery(): SelectQuery }): this {
|
| 297 |
+
const query = child.toQuery().clone();
|
| 298 |
+
query.aggregateItems = [];
|
| 299 |
+
query.aggregate("Count", "id", alias);
|
| 300 |
+
this.query.relationAggregate("orderItemList", alias, query, true,
|
| 301 |
+
{ kind: "relation-count", method: "countOrderItemsWith", relation: "orderItemList", alias });
|
| 302 |
+
return this;
|
| 303 |
+
}
|
| 304 |
+
|
| 305 |
+
|
| 306 |
+
countPayments(): this {
|
| 307 |
+
return this.countPaymentsAs("countPayments");
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
+
countPaymentsAs(alias: string): this {
|
| 311 |
+
const query = new SelectQuery("Payment").filter({ version: { "$gte": 1 } });
|
| 312 |
+
this.countPaymentsWith(alias, { toQuery: () => query });
|
| 313 |
+
this.query.relationAggregates[this.query.relationAggregates.length - 1].operation = {
|
| 314 |
+
kind: "relation-count", method: "countPaymentsAs", relation: "paymentList", alias };
|
| 315 |
+
return this;
|
| 316 |
+
}
|
| 317 |
+
|
| 318 |
+
countPaymentsWith(alias: string, child: { toQuery(): SelectQuery }): this {
|
| 319 |
+
const query = child.toQuery().clone();
|
| 320 |
+
query.aggregateItems = [];
|
| 321 |
+
query.aggregate("Count", "id", alias);
|
| 322 |
+
this.query.relationAggregate("paymentList", alias, query, true,
|
| 323 |
+
{ kind: "relation-count", method: "countPaymentsWith", relation: "paymentList", alias });
|
| 324 |
+
return this;
|
| 325 |
+
}
|
| 326 |
+
|
| 327 |
+
|
| 328 |
+
countShipments(): this {
|
| 329 |
+
return this.countShipmentsAs("countShipments");
|
| 330 |
+
}
|
| 331 |
+
|
| 332 |
+
countShipmentsAs(alias: string): this {
|
| 333 |
+
const query = new SelectQuery("Shipment").filter({ version: { "$gte": 1 } });
|
| 334 |
+
this.countShipmentsWith(alias, { toQuery: () => query });
|
| 335 |
+
this.query.relationAggregates[this.query.relationAggregates.length - 1].operation = {
|
| 336 |
+
kind: "relation-count", method: "countShipmentsAs", relation: "shipmentList", alias };
|
| 337 |
+
return this;
|
| 338 |
+
}
|
| 339 |
+
|
| 340 |
+
countShipmentsWith(alias: string, child: { toQuery(): SelectQuery }): this {
|
| 341 |
+
const query = child.toQuery().clone();
|
| 342 |
+
query.aggregateItems = [];
|
| 343 |
+
query.aggregate("Count", "id", alias);
|
| 344 |
+
this.query.relationAggregate("shipmentList", alias, query, true,
|
| 345 |
+
{ kind: "relation-count", method: "countShipmentsWith", relation: "shipmentList", alias });
|
| 346 |
+
return this;
|
| 347 |
+
}
|
| 348 |
+
|
| 349 |
+
|
| 350 |
+
|
| 351 |
+
withIdIs(val: any): this {
|
| 352 |
+
this.filters.push({ "id": { "$eq": val } });
|
| 353 |
+
return this;
|
| 354 |
+
}
|
| 355 |
+
|
| 356 |
+
withIdIsNot(val: any): this {
|
| 357 |
+
this.filters.push({ "id": { "$ne": val } });
|
| 358 |
+
return this;
|
| 359 |
+
}
|
| 360 |
+
|
| 361 |
+
withIdIn(...vals: any[]): this {
|
| 362 |
+
this.filters.push({ "id": { "$in": vals } });
|
| 363 |
+
return this;
|
| 364 |
+
}
|
| 365 |
+
|
| 366 |
+
withIdNotIn(...vals: any[]): this {
|
| 367 |
+
this.filters.push({ "id": { "$notIn": vals } });
|
| 368 |
+
return this;
|
| 369 |
+
}
|
| 370 |
+
|
| 371 |
+
withIdGreaterThan(val: any): this {
|
| 372 |
+
this.filters.push({ "id": { "$gt": val } });
|
| 373 |
+
return this;
|
| 374 |
+
}
|
| 375 |
+
|
| 376 |
+
withIdGreaterThanOrEqualTo(val: any): this {
|
| 377 |
+
this.filters.push({ "id": { "$gte": val } });
|
| 378 |
+
return this;
|
| 379 |
+
}
|
| 380 |
+
|
| 381 |
+
withIdLessThan(val: any): this {
|
| 382 |
+
this.filters.push({ "id": { "$lt": val } });
|
| 383 |
+
return this;
|
| 384 |
+
}
|
| 385 |
+
|
| 386 |
+
withIdLessThanOrEqualTo(val: any): this {
|
| 387 |
+
this.filters.push({ "id": { "$lte": val } });
|
| 388 |
+
return this;
|
| 389 |
+
}
|
| 390 |
+
|
| 391 |
+
withIdBetween(lower: any, upper: any): this {
|
| 392 |
+
this.filters.push({ "id": { "$between": [lower, upper] } });
|
| 393 |
+
return this;
|
| 394 |
+
}
|
| 395 |
+
|
| 396 |
+
withIdIsKnown(): this {
|
| 397 |
+
this.filters.push({ "id": { "$isNull": false } });
|
| 398 |
+
return this;
|
| 399 |
+
}
|
| 400 |
+
|
| 401 |
+
withIdIsUnknown(): this {
|
| 402 |
+
this.filters.push({ "id": { "$isNull": true } });
|
| 403 |
+
return this;
|
| 404 |
+
}
|
| 405 |
+
|
| 406 |
+
filterByPlatform(val: any): this {
|
| 407 |
+
this.filters.push({ "platform": { "$eq": val } });
|
| 408 |
+
return this;
|
| 409 |
+
}
|
| 410 |
+
|
| 411 |
+
filterByPlatformIn(...vals: any[]): this {
|
| 412 |
+
this.filters.push({ "platform": { "$in": vals } });
|
| 413 |
+
return this;
|
| 414 |
+
}
|
| 415 |
+
|
| 416 |
+
withPlatformIsKnown(): this {
|
| 417 |
+
this.filters.push({ "platform": { "$isNull": false } });
|
| 418 |
+
return this;
|
| 419 |
+
}
|
| 420 |
+
|
| 421 |
+
withPlatformIsUnknown(): this {
|
| 422 |
+
this.filters.push({ "platform": { "$isNull": true } });
|
| 423 |
+
return this;
|
| 424 |
+
}
|
| 425 |
+
|
| 426 |
+
withOrderNumberContaining(val: string): this {
|
| 427 |
+
this.filters.push({ "orderNumber": { "$contains": val } });
|
| 428 |
+
return this;
|
| 429 |
+
}
|
| 430 |
+
|
| 431 |
+
withOrderNumberIs(val: string): this {
|
| 432 |
+
this.filters.push({ "orderNumber": { "$eq": val } });
|
| 433 |
+
return this;
|
| 434 |
+
}
|
| 435 |
+
|
| 436 |
+
withOrderNumberIsNot(val: any): this {
|
| 437 |
+
this.filters.push({ "orderNumber": { "$ne": val } });
|
| 438 |
+
return this;
|
| 439 |
+
}
|
| 440 |
+
|
| 441 |
+
withOrderNumberIn(...vals: any[]): this {
|
| 442 |
+
this.filters.push({ "orderNumber": { "$in": vals } });
|
| 443 |
+
return this;
|
| 444 |
+
}
|
| 445 |
+
|
| 446 |
+
withOrderNumberNotIn(...vals: any[]): this {
|
| 447 |
+
this.filters.push({ "orderNumber": { "$notIn": vals } });
|
| 448 |
+
return this;
|
| 449 |
+
}
|
| 450 |
+
|
| 451 |
+
withOrderNumberGreaterThan(val: any): this {
|
| 452 |
+
this.filters.push({ "orderNumber": { "$gt": val } });
|
| 453 |
+
return this;
|
| 454 |
+
}
|
| 455 |
+
|
| 456 |
+
withOrderNumberGreaterThanOrEqualTo(val: any): this {
|
| 457 |
+
this.filters.push({ "orderNumber": { "$gte": val } });
|
| 458 |
+
return this;
|
| 459 |
+
}
|
| 460 |
+
|
| 461 |
+
withOrderNumberLessThan(val: any): this {
|
| 462 |
+
this.filters.push({ "orderNumber": { "$lt": val } });
|
| 463 |
+
return this;
|
| 464 |
+
}
|
| 465 |
+
|
| 466 |
+
withOrderNumberLessThanOrEqualTo(val: any): this {
|
| 467 |
+
this.filters.push({ "orderNumber": { "$lte": val } });
|
| 468 |
+
return this;
|
| 469 |
+
}
|
| 470 |
+
|
| 471 |
+
withOrderNumberBetween(lower: any, upper: any): this {
|
| 472 |
+
this.filters.push({ "orderNumber": { "$between": [lower, upper] } });
|
| 473 |
+
return this;
|
| 474 |
+
}
|
| 475 |
+
|
| 476 |
+
withOrderNumberIsKnown(): this {
|
| 477 |
+
this.filters.push({ "orderNumber": { "$isNull": false } });
|
| 478 |
+
return this;
|
| 479 |
+
}
|
| 480 |
+
|
| 481 |
+
withOrderNumberIsUnknown(): this {
|
| 482 |
+
this.filters.push({ "orderNumber": { "$isNull": true } });
|
| 483 |
+
return this;
|
| 484 |
+
}
|
| 485 |
+
withOrderNumberNotContaining(val: string): this {
|
| 486 |
+
this.filters.push({ "orderNumber": { "$notContains": val } });
|
| 487 |
+
return this;
|
| 488 |
+
}
|
| 489 |
+
|
| 490 |
+
withOrderNumberStartingWith(val: string): this {
|
| 491 |
+
this.filters.push({ "orderNumber": { "$startsWith": val } });
|
| 492 |
+
return this;
|
| 493 |
+
}
|
| 494 |
+
|
| 495 |
+
withOrderNumberNotStartingWith(val: string): this {
|
| 496 |
+
this.filters.push({ "orderNumber": { "$notStartsWith": val } });
|
| 497 |
+
return this;
|
| 498 |
+
}
|
| 499 |
+
|
| 500 |
+
withOrderNumberEndingWith(val: string): this {
|
| 501 |
+
this.filters.push({ "orderNumber": { "$endsWith": val } });
|
| 502 |
+
return this;
|
| 503 |
+
}
|
| 504 |
+
|
| 505 |
+
withOrderNumberNotEndingWith(val: string): this {
|
| 506 |
+
this.filters.push({ "orderNumber": { "$notEndsWith": val } });
|
| 507 |
+
return this;
|
| 508 |
+
}
|
| 509 |
+
|
| 510 |
+
withOrderNumberSoundingLike(val: string): this {
|
| 511 |
+
this.filters.push({ "orderNumber": { "$soundLike": val } });
|
| 512 |
+
return this;
|
| 513 |
+
}
|
| 514 |
+
|
| 515 |
+
withDescriptionContaining(val: string): this {
|
| 516 |
+
this.filters.push({ "description": { "$contains": val } });
|
| 517 |
+
return this;
|
| 518 |
+
}
|
| 519 |
+
|
| 520 |
+
withDescriptionIs(val: string): this {
|
| 521 |
+
this.filters.push({ "description": { "$eq": val } });
|
| 522 |
+
return this;
|
| 523 |
+
}
|
| 524 |
+
|
| 525 |
+
withDescriptionIsNot(val: any): this {
|
| 526 |
+
this.filters.push({ "description": { "$ne": val } });
|
| 527 |
+
return this;
|
| 528 |
+
}
|
| 529 |
+
|
| 530 |
+
withDescriptionIn(...vals: any[]): this {
|
| 531 |
+
this.filters.push({ "description": { "$in": vals } });
|
| 532 |
+
return this;
|
| 533 |
+
}
|
| 534 |
+
|
| 535 |
+
withDescriptionNotIn(...vals: any[]): this {
|
| 536 |
+
this.filters.push({ "description": { "$notIn": vals } });
|
| 537 |
+
return this;
|
| 538 |
+
}
|
| 539 |
+
|
| 540 |
+
withDescriptionGreaterThan(val: any): this {
|
| 541 |
+
this.filters.push({ "description": { "$gt": val } });
|
| 542 |
+
return this;
|
| 543 |
+
}
|
| 544 |
+
|
| 545 |
+
withDescriptionGreaterThanOrEqualTo(val: any): this {
|
| 546 |
+
this.filters.push({ "description": { "$gte": val } });
|
| 547 |
+
return this;
|
| 548 |
+
}
|
| 549 |
+
|
| 550 |
+
withDescriptionLessThan(val: any): this {
|
| 551 |
+
this.filters.push({ "description": { "$lt": val } });
|
| 552 |
+
return this;
|
| 553 |
+
}
|
| 554 |
+
|
| 555 |
+
withDescriptionLessThanOrEqualTo(val: any): this {
|
| 556 |
+
this.filters.push({ "description": { "$lte": val } });
|
| 557 |
+
return this;
|
| 558 |
+
}
|
| 559 |
+
|
| 560 |
+
withDescriptionBetween(lower: any, upper: any): this {
|
| 561 |
+
this.filters.push({ "description": { "$between": [lower, upper] } });
|
| 562 |
+
return this;
|
| 563 |
+
}
|
| 564 |
+
|
| 565 |
+
withDescriptionIsKnown(): this {
|
| 566 |
+
this.filters.push({ "description": { "$isNull": false } });
|
| 567 |
+
return this;
|
| 568 |
+
}
|
| 569 |
+
|
| 570 |
+
withDescriptionIsUnknown(): this {
|
| 571 |
+
this.filters.push({ "description": { "$isNull": true } });
|
| 572 |
+
return this;
|
| 573 |
+
}
|
| 574 |
+
withDescriptionNotContaining(val: string): this {
|
| 575 |
+
this.filters.push({ "description": { "$notContains": val } });
|
| 576 |
+
return this;
|
| 577 |
+
}
|
| 578 |
+
|
| 579 |
+
withDescriptionStartingWith(val: string): this {
|
| 580 |
+
this.filters.push({ "description": { "$startsWith": val } });
|
| 581 |
+
return this;
|
| 582 |
+
}
|
| 583 |
+
|
| 584 |
+
withDescriptionNotStartingWith(val: string): this {
|
| 585 |
+
this.filters.push({ "description": { "$notStartsWith": val } });
|
| 586 |
+
return this;
|
| 587 |
+
}
|
| 588 |
+
|
| 589 |
+
withDescriptionEndingWith(val: string): this {
|
| 590 |
+
this.filters.push({ "description": { "$endsWith": val } });
|
| 591 |
+
return this;
|
| 592 |
+
}
|
| 593 |
+
|
| 594 |
+
withDescriptionNotEndingWith(val: string): this {
|
| 595 |
+
this.filters.push({ "description": { "$notEndsWith": val } });
|
| 596 |
+
return this;
|
| 597 |
+
}
|
| 598 |
+
|
| 599 |
+
withDescriptionSoundingLike(val: string): this {
|
| 600 |
+
this.filters.push({ "description": { "$soundLike": val } });
|
| 601 |
+
return this;
|
| 602 |
+
}
|
| 603 |
+
|
| 604 |
+
withVersionIs(val: any): this {
|
| 605 |
+
this.filters.push({ "version": { "$eq": val } });
|
| 606 |
+
return this;
|
| 607 |
+
}
|
| 608 |
+
|
| 609 |
+
withVersionIsNot(val: any): this {
|
| 610 |
+
this.filters.push({ "version": { "$ne": val } });
|
| 611 |
+
return this;
|
| 612 |
+
}
|
| 613 |
+
|
| 614 |
+
withVersionIn(...vals: any[]): this {
|
| 615 |
+
this.filters.push({ "version": { "$in": vals } });
|
| 616 |
+
return this;
|
| 617 |
+
}
|
| 618 |
+
|
| 619 |
+
withVersionNotIn(...vals: any[]): this {
|
| 620 |
+
this.filters.push({ "version": { "$notIn": vals } });
|
| 621 |
+
return this;
|
| 622 |
+
}
|
| 623 |
+
|
| 624 |
+
withVersionGreaterThan(val: any): this {
|
| 625 |
+
this.filters.push({ "version": { "$gt": val } });
|
| 626 |
+
return this;
|
| 627 |
+
}
|
| 628 |
+
|
| 629 |
+
withVersionGreaterThanOrEqualTo(val: any): this {
|
| 630 |
+
this.filters.push({ "version": { "$gte": val } });
|
| 631 |
+
return this;
|
| 632 |
+
}
|
| 633 |
+
|
| 634 |
+
withVersionLessThan(val: any): this {
|
| 635 |
+
this.filters.push({ "version": { "$lt": val } });
|
| 636 |
+
return this;
|
| 637 |
+
}
|
| 638 |
+
|
| 639 |
+
withVersionLessThanOrEqualTo(val: any): this {
|
| 640 |
+
this.filters.push({ "version": { "$lte": val } });
|
| 641 |
+
return this;
|
| 642 |
+
}
|
| 643 |
+
|
| 644 |
+
withVersionBetween(lower: any, upper: any): this {
|
| 645 |
+
this.filters.push({ "version": { "$between": [lower, upper] } });
|
| 646 |
+
return this;
|
| 647 |
+
}
|
| 648 |
+
|
| 649 |
+
withVersionIsKnown(): this {
|
| 650 |
+
this.filters.push({ "version": { "$isNull": false } });
|
| 651 |
+
return this;
|
| 652 |
+
}
|
| 653 |
+
|
| 654 |
+
withVersionIsUnknown(): this {
|
| 655 |
+
this.filters.push({ "version": { "$isNull": true } });
|
| 656 |
+
return this;
|
| 657 |
+
}
|
| 658 |
+
|
| 659 |
+
orderByIdAscending(): this {
|
| 660 |
+
this.query.orderBy("id", "asc");
|
| 661 |
+
return this;
|
| 662 |
+
}
|
| 663 |
+
|
| 664 |
+
orderByIdDescending(): this {
|
| 665 |
+
this.query.orderBy("id", "desc");
|
| 666 |
+
return this;
|
| 667 |
+
}
|
| 668 |
+
|
| 669 |
+
|
| 670 |
+
orderByOrderNumberAscending(): this {
|
| 671 |
+
this.query.orderBy("orderNumber", "asc");
|
| 672 |
+
return this;
|
| 673 |
+
}
|
| 674 |
+
|
| 675 |
+
orderByOrderNumberDescending(): this {
|
| 676 |
+
this.query.orderBy("orderNumber", "desc");
|
| 677 |
+
return this;
|
| 678 |
+
}
|
| 679 |
+
|
| 680 |
+
orderByDescriptionAscending(): this {
|
| 681 |
+
this.query.orderBy("description", "asc");
|
| 682 |
+
return this;
|
| 683 |
+
}
|
| 684 |
+
|
| 685 |
+
orderByDescriptionDescending(): this {
|
| 686 |
+
this.query.orderBy("description", "desc");
|
| 687 |
+
return this;
|
| 688 |
+
}
|
| 689 |
+
|
| 690 |
+
orderByVersionAscending(): this {
|
| 691 |
+
this.query.orderBy("version", "asc");
|
| 692 |
+
return this;
|
| 693 |
+
}
|
| 694 |
+
|
| 695 |
+
orderByVersionDescending(): this {
|
| 696 |
+
this.query.orderBy("version", "desc");
|
| 697 |
+
return this;
|
| 698 |
+
}
|
| 699 |
+
|
| 700 |
+
|
| 701 |
+
// --- Aggregations ---
|
| 702 |
+
count(): this {
|
| 703 |
+
this.query.aggregate("Count", "id", "count");
|
| 704 |
+
this._pageCountAlias = "count";
|
| 705 |
+
this._pageCountMethod = "count";
|
| 706 |
+
return this;
|
| 707 |
+
}
|
| 708 |
+
|
| 709 |
+
countAs(retName: string): this {
|
| 710 |
+
this.query.aggregate("Count", "id", retName);
|
| 711 |
+
this._pageCountAlias = retName;
|
| 712 |
+
this._pageCountMethod = "countAs";
|
| 713 |
+
return this;
|
| 714 |
+
}
|
| 715 |
+
|
| 716 |
+
|
| 717 |
+
// --- Group By ---
|
| 718 |
+
groupById(): this {
|
| 719 |
+
this.query.groupBy("id");
|
| 720 |
+
return this;
|
| 721 |
+
}
|
| 722 |
+
|
| 723 |
+
groupByIdAs(retName: string): this {
|
| 724 |
+
this.query.groupBy("id"); // In TS we don't alias group by yet natively
|
| 725 |
+
return this;
|
| 726 |
+
}
|
| 727 |
+
groupByPlatform(): this {
|
| 728 |
+
this.query.groupBy("platform");
|
| 729 |
+
return this;
|
| 730 |
+
}
|
| 731 |
+
|
| 732 |
+
groupByPlatformAs(retName: string): this {
|
| 733 |
+
this.query.groupBy("platform"); // In TS we don't alias group by yet natively
|
| 734 |
+
return this;
|
| 735 |
+
}
|
| 736 |
+
groupByOrderNumber(): this {
|
| 737 |
+
this.query.groupBy("orderNumber");
|
| 738 |
+
return this;
|
| 739 |
+
}
|
| 740 |
+
|
| 741 |
+
groupByOrderNumberAs(retName: string): this {
|
| 742 |
+
this.query.groupBy("orderNumber"); // In TS we don't alias group by yet natively
|
| 743 |
+
return this;
|
| 744 |
+
}
|
| 745 |
+
groupByDescription(): this {
|
| 746 |
+
this.query.groupBy("description");
|
| 747 |
+
return this;
|
| 748 |
+
}
|
| 749 |
+
|
| 750 |
+
groupByDescriptionAs(retName: string): this {
|
| 751 |
+
this.query.groupBy("description"); // In TS we don't alias group by yet natively
|
| 752 |
+
return this;
|
| 753 |
+
}
|
| 754 |
+
groupByVersion(): this {
|
| 755 |
+
this.query.groupBy("version");
|
| 756 |
+
return this;
|
| 757 |
+
}
|
| 758 |
+
|
| 759 |
+
groupByVersionAs(retName: string): this {
|
| 760 |
+
this.query.groupBy("version"); // In TS we don't alias group by yet natively
|
| 761 |
+
return this;
|
| 762 |
+
}
|
| 763 |
+
|
| 764 |
+
// --- Facets ---
|
| 765 |
+
facetByPlatformAs(
|
| 766 |
+
facetName: string,
|
| 767 |
+
request: { toQuery(): SelectQuery },
|
| 768 |
+
includeAllFacets = true,
|
| 769 |
+
): this {
|
| 770 |
+
this.query.facetBy(facetName, "platform", request, includeAllFacets,
|
| 771 |
+
{ kind: "facet", method: "facetByPlatformAs", relation: "platform", alias: facetName });
|
| 772 |
+
return this;
|
| 773 |
+
}
|
| 774 |
+
|
| 775 |
+
|
| 776 |
+
private async executeForListInternal(context: UserContext): Promise<SmartList<CustomerOrder>> {
|
| 777 |
+
this.ensureIntent();
|
| 778 |
+
if (this._pageCountAlias !== undefined) return this.executeCountedListInternal(context);
|
| 779 |
+
if (this.filters.length > 0) {
|
| 780 |
+
this.query.filter({ "$and": this.filters });
|
| 781 |
+
}
|
| 782 |
+
|
| 783 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 784 |
+
const rows = await service.executeQuery(context.prepareQuery(this.query));
|
| 785 |
+
const aggregateOnly = this.query.aggregateItems.length > 0 && this.query.groupByItems.length === 0;
|
| 786 |
+
const data = aggregateOnly ? [] : rows.map((row: unknown) =>
|
| 787 |
+
row instanceof CustomerOrder
|
| 788 |
+
? row
|
| 789 |
+
: CustomerOrder.fromRecord(row as Record<string, unknown>, new EntityRoot()));
|
| 790 |
+
const result = new SmartList<CustomerOrder>(data);
|
| 791 |
+
if (aggregateOnly && rows[0]) Object.assign(result.aggregations, rows[0]);
|
| 792 |
+
|
| 793 |
+
if (this.query.facets.length > 0) {
|
| 794 |
+
result.facets = await executeRelationFacets(
|
| 795 |
+
service, (query: any) => context.prepareQuery(query), this.query, this.query.facets);
|
| 796 |
+
}
|
| 797 |
+
|
| 798 |
+
return result;
|
| 799 |
+
}
|
| 800 |
+
|
| 801 |
+
private async executeForRowsInternal(context: UserContext): Promise<SmartList<Record<string, unknown>>> {
|
| 802 |
+
this.ensureIntent();
|
| 803 |
+
if (this.filters.length > 0) this.query.filter({ "$and": this.filters });
|
| 804 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 805 |
+
return new SmartList<Record<string, unknown>>(
|
| 806 |
+
await service.executeQuery(context.prepareQuery(this.query)) as Record<string, unknown>[]);
|
| 807 |
+
}
|
| 808 |
+
|
| 809 |
+
private async executeCountedListInternal(
|
| 810 |
+
context: UserContext,
|
| 811 |
+
): Promise<SmartList<CustomerOrder>> {
|
| 812 |
+
this.ensureIntent();
|
| 813 |
+
if (this.filters.length > 0) this.query.filter({ "$and": this.filters });
|
| 814 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 815 |
+
const preparedQuery = context.prepareQuery(this.query);
|
| 816 |
+
const useIdSet = preparedQuery.localIdSetPaginationOptions() !== undefined;
|
| 817 |
+
const countOperation = { kind: "named-count" as const,
|
| 818 |
+
method: this._pageCountMethod ?? "count",
|
| 819 |
+
...(this._pageCountMethod === "countAs" ? { alias: this._pageCountAlias } : {}) };
|
| 820 |
+
const totalCountBeforeRows = useIdSet ? undefined : await service.executeCount(
|
| 821 |
+
preparedQuery, this._pageCountAlias, countOperation);
|
| 822 |
+
const pageQuery = preparedQuery.clone();
|
| 823 |
+
// A page count describes the full filtered set, not an aggregate-only page row.
|
| 824 |
+
pageQuery.aggregateItems = pageQuery.aggregateItems.filter(item =>
|
| 825 |
+
!(String(item.function).toLowerCase() === "count" && item.alias === this._pageCountAlias));
|
| 826 |
+
const rows = await service.executeQuery(pageQuery);
|
| 827 |
+
const totalCount = useIdSet && context.idSetPaginationCountAccuracy === "EXACT"
|
| 828 |
+
? context.idSetPaginationCount!
|
| 829 |
+
: (totalCountBeforeRows ?? await service.executeCount(preparedQuery, this._pageCountAlias, countOperation));
|
| 830 |
+
const data = new SmartList(rows.map((row: unknown) =>
|
| 831 |
+
row instanceof CustomerOrder
|
| 832 |
+
? row
|
| 833 |
+
: CustomerOrder.fromRecord(row as Record<string, unknown>, new EntityRoot())));
|
| 834 |
+
data.totalCount = totalCount;
|
| 835 |
+
if (this._pageCountAlias !== undefined) data.aggregations[this._pageCountAlias] = totalCount;
|
| 836 |
+
if (this.query.facets.length > 0) {
|
| 837 |
+
data.facets = await executeRelationFacets(
|
| 838 |
+
service, (query: any) => context.prepareQuery(query), preparedQuery, preparedQuery.facets);
|
| 839 |
+
}
|
| 840 |
+
return data;
|
| 841 |
+
}
|
| 842 |
+
|
| 843 |
+
private executeForStreamInternal(context: UserContext, chunkSize: number): AsyncIterable<CustomerOrder> {
|
| 844 |
+
this.ensureIntent();
|
| 845 |
+
if (this.filters.length > 0) this.query.filter({ "$and": this.filters });
|
| 846 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 847 |
+
const preparedQuery = context.prepareQuery(this.query);
|
| 848 |
+
// Prepare Context and capture the runtime request before returning a lazy iterator.
|
| 849 |
+
const chunks = service.executeForStream(preparedQuery, chunkSize);
|
| 850 |
+
return (async function* () {
|
| 851 |
+
for await (const chunk of chunks) {
|
| 852 |
+
for (const entity of chunk) {
|
| 853 |
+
yield entity instanceof CustomerOrder
|
| 854 |
+
? entity
|
| 855 |
+
: CustomerOrder.fromRecord(entity as Record<string, unknown>, new EntityRoot());
|
| 856 |
+
}
|
| 857 |
+
}
|
| 858 |
+
})();
|
| 859 |
+
}
|
| 860 |
+
|
| 861 |
+
private ensureIntent(): void {
|
| 862 |
+
// Runtime owns validation, Unicode whitespace rules and typed diagnostics.
|
| 863 |
+
new QueryIntent(this._comment, this._purpose);
|
| 864 |
+
}
|
| 865 |
+
|
| 866 |
+
}
|
| 867 |
+
|
| 868 |
+
export class ExecutableCustomerOrderRequest {
|
| 869 |
+
constructor(
|
| 870 |
+
private readonly execute: (context: UserContext) => Promise<SmartList<CustomerOrder>>,
|
| 871 |
+
private readonly executeRows: (context: UserContext) => Promise<SmartList<Record<string, unknown>>>,
|
| 872 |
+
private readonly stream: (context: UserContext, chunkSize: number) => AsyncIterable<CustomerOrder>,
|
| 873 |
+
private readonly limitOne: () => void,
|
| 874 |
+
private readonly addComment: (comment: string) => void,
|
| 875 |
+
private readonly ensureIntent: () => void,
|
| 876 |
+
) {}
|
| 877 |
+
|
| 878 |
+
comment(c: string): this {
|
| 879 |
+
this.addComment(c);
|
| 880 |
+
return this;
|
| 881 |
+
}
|
| 882 |
+
|
| 883 |
+
newEntity(context: UserContext): CustomerOrder {
|
| 884 |
+
this.ensureIntent();
|
| 885 |
+
return new CustomerOrder();
|
| 886 |
+
}
|
| 887 |
+
|
| 888 |
+
executeForList(context: UserContext): Promise<SmartList<CustomerOrder>> {
|
| 889 |
+
this.ensureIntent();
|
| 890 |
+
return this.execute(context);
|
| 891 |
+
}
|
| 892 |
+
|
| 893 |
+
executeForRows(context: UserContext): Promise<SmartList<Record<string, unknown>>> {
|
| 894 |
+
this.ensureIntent();
|
| 895 |
+
return this.executeRows(context);
|
| 896 |
+
}
|
| 897 |
+
|
| 898 |
+
executeForStream(context: UserContext, chunkSize = 1000): AsyncIterable<CustomerOrder> {
|
| 899 |
+
this.ensureIntent();
|
| 900 |
+
return this.stream(context, chunkSize);
|
| 901 |
+
}
|
| 902 |
+
|
| 903 |
+
async executeForOne(context: UserContext): Promise<CustomerOrder | undefined> {
|
| 904 |
+
this.limitOne();
|
| 905 |
+
return (await this.executeForList(context))[0];
|
| 906 |
+
}
|
| 907 |
+
}
|
source/teaql-ts/examples/trace-chain/lib/src/generated/requests/OrderItemRequest.ts
ADDED
|
@@ -0,0 +1,611 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { EntityRoot, SelectQuery, SmartList, TeaQLDataService, UserContext, executeRelationFacets } from '../../teaql-ts';
|
| 2 |
+
import { OrderItem } from '../models/OrderItem';
|
| 3 |
+
import { mergeGeneratedScalarSearch, DynamicSearchWarning, QueryIntent } from 'teaql-ts';
|
| 4 |
+
import { GENERATED_SEARCH_MODELS } from '../../generated-search-models';
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
export class OrderItemRequest {
|
| 9 |
+
private query: SelectQuery;
|
| 10 |
+
private filters: any[] = [];
|
| 11 |
+
private _purpose: string | undefined;
|
| 12 |
+
private _comment: string | undefined;
|
| 13 |
+
private _pageCountAlias: string | undefined;
|
| 14 |
+
private _pageCountMethod: "count" | "countAs" | undefined;
|
| 15 |
+
private _dynamicSearchWarnings: DynamicSearchWarning[] = [];
|
| 16 |
+
|
| 17 |
+
constructor(minimal = false) {
|
| 18 |
+
this.query = new SelectQuery("OrderItem");
|
| 19 |
+
this.filters.push({ version: { "$gte": 1 } });
|
| 20 |
+
if (minimal) {
|
| 21 |
+
this.selectId();
|
| 22 |
+
this.selectVersion();
|
| 23 |
+
}
|
| 24 |
+
else this.selectSelfFields();
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
comment(c: string): this {
|
| 28 |
+
this.query.comment(c);
|
| 29 |
+
this._comment = c;
|
| 30 |
+
return this;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
filterByJson(source: unknown, warn?: (warning: DynamicSearchWarning) => void): this {
|
| 34 |
+
const base = this.query.clone();
|
| 35 |
+
if (this.filters.length > 0) base.filter({ "$and": this.filters });
|
| 36 |
+
const merged = mergeGeneratedScalarSearch(base, source, GENERATED_SEARCH_MODELS, warn);
|
| 37 |
+
this.query = merged.query as SelectQuery;
|
| 38 |
+
this.filters = this.query.filterCondition ? [this.query.filterCondition] : [];
|
| 39 |
+
this._dynamicSearchWarnings.push(...merged.warnings);
|
| 40 |
+
return this;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
get dynamicSearchWarnings(): readonly DynamicSearchWarning[] {
|
| 44 |
+
return this._dynamicSearchWarnings.map(warning => ({ ...warning }));
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
purpose(p: string): ExecutableOrderItemRequest {
|
| 48 |
+
this.query.purpose(p);
|
| 49 |
+
this._purpose = p;
|
| 50 |
+
return new ExecutableOrderItemRequest(
|
| 51 |
+
(context) => context.withQueryRequest(this.query, () => this.executeForListInternal(context)),
|
| 52 |
+
(context) => context.withQueryRequest(this.query, () => this.executeForRowsInternal(context)),
|
| 53 |
+
(context, chunkSize) => this.executeForStreamInternal(context, chunkSize),
|
| 54 |
+
() => this.limit(1),
|
| 55 |
+
(c) => this.comment(c),
|
| 56 |
+
() => this.ensureIntent());
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
optimizeForContinuousPageFetch(): this {
|
| 60 |
+
this.query.optimizeForContinuousPageFetch();
|
| 61 |
+
return this;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
optimizeForContinuousPageFetchWith(namespace: string, ttlSeconds: number): this {
|
| 65 |
+
this.query.optimizeForContinuousPageFetchWith(namespace, ttlSeconds);
|
| 66 |
+
return this;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
optimizePaginationWithIdSet(): this {
|
| 70 |
+
this.query.optimizePaginationWithIdSet();
|
| 71 |
+
return this;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
optimizePaginationWithIdSetConfig(namespace: string, ttlSeconds: number, maxIds: number): this {
|
| 75 |
+
this.query.optimizePaginationWithIdSetConfig(namespace, ttlSeconds, maxIds);
|
| 76 |
+
return this;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
topNProbeParentThreshold(threshold: number): this {
|
| 80 |
+
this.query.topNProbeParentThreshold(threshold);
|
| 81 |
+
return this;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
limit(n: number): this {
|
| 85 |
+
this.query.limit(n);
|
| 86 |
+
return this;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
offset(n: number): this {
|
| 90 |
+
this.query.offset(n);
|
| 91 |
+
return this;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
toQuery(): SelectQuery {
|
| 95 |
+
if (this.filters.length > 0) {
|
| 96 |
+
this.query.filter({ "$and": this.filters });
|
| 97 |
+
}
|
| 98 |
+
return this.query;
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
withDeletedRows(): this {
|
| 102 |
+
this.filters = this.filters.filter(filter => !("version" in filter));
|
| 103 |
+
return this;
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
deletedRowsOnly(): this {
|
| 107 |
+
this.withDeletedRows();
|
| 108 |
+
this.filters.push({ version: { "$lte": -1 } });
|
| 109 |
+
return this;
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
selectSelfFields(): this {
|
| 113 |
+
this.query.select(["id", "customerOrder", "name", "version"]);
|
| 114 |
+
return this;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
selectId(): this {
|
| 118 |
+
this.query.select(["id"]);
|
| 119 |
+
return this;
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
selectName(): this {
|
| 124 |
+
this.query.select(["name"]);
|
| 125 |
+
return this;
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
selectVersion(): this {
|
| 129 |
+
this.query.select(["version"]);
|
| 130 |
+
return this;
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
selectCustomerOrderWith(request: { toQuery(): SelectQuery }): this {
|
| 135 |
+
this.query.select(["customerOrder"]);
|
| 136 |
+
this.query.relationQuery(
|
| 137 |
+
"customerOrder", request.toQuery(), "customerOrder", "id", false,
|
| 138 |
+
{ kind: "relation-select", method: "selectCustomerOrderWith", relation: "customerOrder" });
|
| 139 |
+
return this;
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
withCustomerOrderMatching(request: { toQuery(): SelectQuery }): this {
|
| 143 |
+
this.filters.push({
|
| 144 |
+
"customerOrder": {
|
| 145 |
+
"$inSubquery": { query: request.toQuery(), field: "id" },
|
| 146 |
+
},
|
| 147 |
+
});
|
| 148 |
+
return this;
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
withoutCustomerOrderMatching(request: { toQuery(): SelectQuery }): this {
|
| 152 |
+
this.filters.push({
|
| 153 |
+
"customerOrder": {
|
| 154 |
+
"$notInSubquery": { query: request.toQuery(), field: "id" },
|
| 155 |
+
},
|
| 156 |
+
});
|
| 157 |
+
return this;
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
withIdIs(val: any): this {
|
| 164 |
+
this.filters.push({ "id": { "$eq": val } });
|
| 165 |
+
return this;
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
withIdIsNot(val: any): this {
|
| 169 |
+
this.filters.push({ "id": { "$ne": val } });
|
| 170 |
+
return this;
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
withIdIn(...vals: any[]): this {
|
| 174 |
+
this.filters.push({ "id": { "$in": vals } });
|
| 175 |
+
return this;
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
withIdNotIn(...vals: any[]): this {
|
| 179 |
+
this.filters.push({ "id": { "$notIn": vals } });
|
| 180 |
+
return this;
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
withIdGreaterThan(val: any): this {
|
| 184 |
+
this.filters.push({ "id": { "$gt": val } });
|
| 185 |
+
return this;
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
withIdGreaterThanOrEqualTo(val: any): this {
|
| 189 |
+
this.filters.push({ "id": { "$gte": val } });
|
| 190 |
+
return this;
|
| 191 |
+
}
|
| 192 |
+
|
| 193 |
+
withIdLessThan(val: any): this {
|
| 194 |
+
this.filters.push({ "id": { "$lt": val } });
|
| 195 |
+
return this;
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
withIdLessThanOrEqualTo(val: any): this {
|
| 199 |
+
this.filters.push({ "id": { "$lte": val } });
|
| 200 |
+
return this;
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
withIdBetween(lower: any, upper: any): this {
|
| 204 |
+
this.filters.push({ "id": { "$between": [lower, upper] } });
|
| 205 |
+
return this;
|
| 206 |
+
}
|
| 207 |
+
|
| 208 |
+
withIdIsKnown(): this {
|
| 209 |
+
this.filters.push({ "id": { "$isNull": false } });
|
| 210 |
+
return this;
|
| 211 |
+
}
|
| 212 |
+
|
| 213 |
+
withIdIsUnknown(): this {
|
| 214 |
+
this.filters.push({ "id": { "$isNull": true } });
|
| 215 |
+
return this;
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
filterByCustomerOrder(val: any): this {
|
| 219 |
+
this.filters.push({ "customerOrder": { "$eq": val } });
|
| 220 |
+
return this;
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
filterByCustomerOrderIn(...vals: any[]): this {
|
| 224 |
+
this.filters.push({ "customerOrder": { "$in": vals } });
|
| 225 |
+
return this;
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
+
withCustomerOrderIsKnown(): this {
|
| 229 |
+
this.filters.push({ "customerOrder": { "$isNull": false } });
|
| 230 |
+
return this;
|
| 231 |
+
}
|
| 232 |
+
|
| 233 |
+
withCustomerOrderIsUnknown(): this {
|
| 234 |
+
this.filters.push({ "customerOrder": { "$isNull": true } });
|
| 235 |
+
return this;
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
withNameContaining(val: string): this {
|
| 239 |
+
this.filters.push({ "name": { "$contains": val } });
|
| 240 |
+
return this;
|
| 241 |
+
}
|
| 242 |
+
|
| 243 |
+
withNameIs(val: string): this {
|
| 244 |
+
this.filters.push({ "name": { "$eq": val } });
|
| 245 |
+
return this;
|
| 246 |
+
}
|
| 247 |
+
|
| 248 |
+
withNameIsNot(val: any): this {
|
| 249 |
+
this.filters.push({ "name": { "$ne": val } });
|
| 250 |
+
return this;
|
| 251 |
+
}
|
| 252 |
+
|
| 253 |
+
withNameIn(...vals: any[]): this {
|
| 254 |
+
this.filters.push({ "name": { "$in": vals } });
|
| 255 |
+
return this;
|
| 256 |
+
}
|
| 257 |
+
|
| 258 |
+
withNameNotIn(...vals: any[]): this {
|
| 259 |
+
this.filters.push({ "name": { "$notIn": vals } });
|
| 260 |
+
return this;
|
| 261 |
+
}
|
| 262 |
+
|
| 263 |
+
withNameGreaterThan(val: any): this {
|
| 264 |
+
this.filters.push({ "name": { "$gt": val } });
|
| 265 |
+
return this;
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
withNameGreaterThanOrEqualTo(val: any): this {
|
| 269 |
+
this.filters.push({ "name": { "$gte": val } });
|
| 270 |
+
return this;
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
withNameLessThan(val: any): this {
|
| 274 |
+
this.filters.push({ "name": { "$lt": val } });
|
| 275 |
+
return this;
|
| 276 |
+
}
|
| 277 |
+
|
| 278 |
+
withNameLessThanOrEqualTo(val: any): this {
|
| 279 |
+
this.filters.push({ "name": { "$lte": val } });
|
| 280 |
+
return this;
|
| 281 |
+
}
|
| 282 |
+
|
| 283 |
+
withNameBetween(lower: any, upper: any): this {
|
| 284 |
+
this.filters.push({ "name": { "$between": [lower, upper] } });
|
| 285 |
+
return this;
|
| 286 |
+
}
|
| 287 |
+
|
| 288 |
+
withNameIsKnown(): this {
|
| 289 |
+
this.filters.push({ "name": { "$isNull": false } });
|
| 290 |
+
return this;
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
withNameIsUnknown(): this {
|
| 294 |
+
this.filters.push({ "name": { "$isNull": true } });
|
| 295 |
+
return this;
|
| 296 |
+
}
|
| 297 |
+
withNameNotContaining(val: string): this {
|
| 298 |
+
this.filters.push({ "name": { "$notContains": val } });
|
| 299 |
+
return this;
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
withNameStartingWith(val: string): this {
|
| 303 |
+
this.filters.push({ "name": { "$startsWith": val } });
|
| 304 |
+
return this;
|
| 305 |
+
}
|
| 306 |
+
|
| 307 |
+
withNameNotStartingWith(val: string): this {
|
| 308 |
+
this.filters.push({ "name": { "$notStartsWith": val } });
|
| 309 |
+
return this;
|
| 310 |
+
}
|
| 311 |
+
|
| 312 |
+
withNameEndingWith(val: string): this {
|
| 313 |
+
this.filters.push({ "name": { "$endsWith": val } });
|
| 314 |
+
return this;
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
withNameNotEndingWith(val: string): this {
|
| 318 |
+
this.filters.push({ "name": { "$notEndsWith": val } });
|
| 319 |
+
return this;
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
withNameSoundingLike(val: string): this {
|
| 323 |
+
this.filters.push({ "name": { "$soundLike": val } });
|
| 324 |
+
return this;
|
| 325 |
+
}
|
| 326 |
+
|
| 327 |
+
withVersionIs(val: any): this {
|
| 328 |
+
this.filters.push({ "version": { "$eq": val } });
|
| 329 |
+
return this;
|
| 330 |
+
}
|
| 331 |
+
|
| 332 |
+
withVersionIsNot(val: any): this {
|
| 333 |
+
this.filters.push({ "version": { "$ne": val } });
|
| 334 |
+
return this;
|
| 335 |
+
}
|
| 336 |
+
|
| 337 |
+
withVersionIn(...vals: any[]): this {
|
| 338 |
+
this.filters.push({ "version": { "$in": vals } });
|
| 339 |
+
return this;
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
withVersionNotIn(...vals: any[]): this {
|
| 343 |
+
this.filters.push({ "version": { "$notIn": vals } });
|
| 344 |
+
return this;
|
| 345 |
+
}
|
| 346 |
+
|
| 347 |
+
withVersionGreaterThan(val: any): this {
|
| 348 |
+
this.filters.push({ "version": { "$gt": val } });
|
| 349 |
+
return this;
|
| 350 |
+
}
|
| 351 |
+
|
| 352 |
+
withVersionGreaterThanOrEqualTo(val: any): this {
|
| 353 |
+
this.filters.push({ "version": { "$gte": val } });
|
| 354 |
+
return this;
|
| 355 |
+
}
|
| 356 |
+
|
| 357 |
+
withVersionLessThan(val: any): this {
|
| 358 |
+
this.filters.push({ "version": { "$lt": val } });
|
| 359 |
+
return this;
|
| 360 |
+
}
|
| 361 |
+
|
| 362 |
+
withVersionLessThanOrEqualTo(val: any): this {
|
| 363 |
+
this.filters.push({ "version": { "$lte": val } });
|
| 364 |
+
return this;
|
| 365 |
+
}
|
| 366 |
+
|
| 367 |
+
withVersionBetween(lower: any, upper: any): this {
|
| 368 |
+
this.filters.push({ "version": { "$between": [lower, upper] } });
|
| 369 |
+
return this;
|
| 370 |
+
}
|
| 371 |
+
|
| 372 |
+
withVersionIsKnown(): this {
|
| 373 |
+
this.filters.push({ "version": { "$isNull": false } });
|
| 374 |
+
return this;
|
| 375 |
+
}
|
| 376 |
+
|
| 377 |
+
withVersionIsUnknown(): this {
|
| 378 |
+
this.filters.push({ "version": { "$isNull": true } });
|
| 379 |
+
return this;
|
| 380 |
+
}
|
| 381 |
+
|
| 382 |
+
orderByIdAscending(): this {
|
| 383 |
+
this.query.orderBy("id", "asc");
|
| 384 |
+
return this;
|
| 385 |
+
}
|
| 386 |
+
|
| 387 |
+
orderByIdDescending(): this {
|
| 388 |
+
this.query.orderBy("id", "desc");
|
| 389 |
+
return this;
|
| 390 |
+
}
|
| 391 |
+
|
| 392 |
+
|
| 393 |
+
orderByNameAscending(): this {
|
| 394 |
+
this.query.orderBy("name", "asc");
|
| 395 |
+
return this;
|
| 396 |
+
}
|
| 397 |
+
|
| 398 |
+
orderByNameDescending(): this {
|
| 399 |
+
this.query.orderBy("name", "desc");
|
| 400 |
+
return this;
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
orderByVersionAscending(): this {
|
| 404 |
+
this.query.orderBy("version", "asc");
|
| 405 |
+
return this;
|
| 406 |
+
}
|
| 407 |
+
|
| 408 |
+
orderByVersionDescending(): this {
|
| 409 |
+
this.query.orderBy("version", "desc");
|
| 410 |
+
return this;
|
| 411 |
+
}
|
| 412 |
+
|
| 413 |
+
|
| 414 |
+
// --- Aggregations ---
|
| 415 |
+
count(): this {
|
| 416 |
+
this.query.aggregate("Count", "id", "count");
|
| 417 |
+
this._pageCountAlias = "count";
|
| 418 |
+
this._pageCountMethod = "count";
|
| 419 |
+
return this;
|
| 420 |
+
}
|
| 421 |
+
|
| 422 |
+
countAs(retName: string): this {
|
| 423 |
+
this.query.aggregate("Count", "id", retName);
|
| 424 |
+
this._pageCountAlias = retName;
|
| 425 |
+
this._pageCountMethod = "countAs";
|
| 426 |
+
return this;
|
| 427 |
+
}
|
| 428 |
+
|
| 429 |
+
|
| 430 |
+
// --- Group By ---
|
| 431 |
+
groupById(): this {
|
| 432 |
+
this.query.groupBy("id");
|
| 433 |
+
return this;
|
| 434 |
+
}
|
| 435 |
+
|
| 436 |
+
groupByIdAs(retName: string): this {
|
| 437 |
+
this.query.groupBy("id"); // In TS we don't alias group by yet natively
|
| 438 |
+
return this;
|
| 439 |
+
}
|
| 440 |
+
groupByCustomerOrder(): this {
|
| 441 |
+
this.query.groupBy("customerOrder");
|
| 442 |
+
return this;
|
| 443 |
+
}
|
| 444 |
+
|
| 445 |
+
groupByCustomerOrderAs(retName: string): this {
|
| 446 |
+
this.query.groupBy("customerOrder"); // In TS we don't alias group by yet natively
|
| 447 |
+
return this;
|
| 448 |
+
}
|
| 449 |
+
groupByName(): this {
|
| 450 |
+
this.query.groupBy("name");
|
| 451 |
+
return this;
|
| 452 |
+
}
|
| 453 |
+
|
| 454 |
+
groupByNameAs(retName: string): this {
|
| 455 |
+
this.query.groupBy("name"); // In TS we don't alias group by yet natively
|
| 456 |
+
return this;
|
| 457 |
+
}
|
| 458 |
+
groupByVersion(): this {
|
| 459 |
+
this.query.groupBy("version");
|
| 460 |
+
return this;
|
| 461 |
+
}
|
| 462 |
+
|
| 463 |
+
groupByVersionAs(retName: string): this {
|
| 464 |
+
this.query.groupBy("version"); // In TS we don't alias group by yet natively
|
| 465 |
+
return this;
|
| 466 |
+
}
|
| 467 |
+
|
| 468 |
+
// --- Facets ---
|
| 469 |
+
facetByCustomerOrderAs(
|
| 470 |
+
facetName: string,
|
| 471 |
+
request: { toQuery(): SelectQuery },
|
| 472 |
+
includeAllFacets = true,
|
| 473 |
+
): this {
|
| 474 |
+
this.query.facetBy(facetName, "customerOrder", request, includeAllFacets,
|
| 475 |
+
{ kind: "facet", method: "facetByCustomerOrderAs", relation: "customerOrder", alias: facetName });
|
| 476 |
+
return this;
|
| 477 |
+
}
|
| 478 |
+
|
| 479 |
+
|
| 480 |
+
private async executeForListInternal(context: UserContext): Promise<SmartList<OrderItem>> {
|
| 481 |
+
this.ensureIntent();
|
| 482 |
+
if (this._pageCountAlias !== undefined) return this.executeCountedListInternal(context);
|
| 483 |
+
if (this.filters.length > 0) {
|
| 484 |
+
this.query.filter({ "$and": this.filters });
|
| 485 |
+
}
|
| 486 |
+
|
| 487 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 488 |
+
const rows = await service.executeQuery(context.prepareQuery(this.query));
|
| 489 |
+
const aggregateOnly = this.query.aggregateItems.length > 0 && this.query.groupByItems.length === 0;
|
| 490 |
+
const data = aggregateOnly ? [] : rows.map((row: unknown) =>
|
| 491 |
+
row instanceof OrderItem
|
| 492 |
+
? row
|
| 493 |
+
: OrderItem.fromRecord(row as Record<string, unknown>, new EntityRoot()));
|
| 494 |
+
const result = new SmartList<OrderItem>(data);
|
| 495 |
+
if (aggregateOnly && rows[0]) Object.assign(result.aggregations, rows[0]);
|
| 496 |
+
|
| 497 |
+
if (this.query.facets.length > 0) {
|
| 498 |
+
result.facets = await executeRelationFacets(
|
| 499 |
+
service, (query: any) => context.prepareQuery(query), this.query, this.query.facets);
|
| 500 |
+
}
|
| 501 |
+
|
| 502 |
+
return result;
|
| 503 |
+
}
|
| 504 |
+
|
| 505 |
+
private async executeForRowsInternal(context: UserContext): Promise<SmartList<Record<string, unknown>>> {
|
| 506 |
+
this.ensureIntent();
|
| 507 |
+
if (this.filters.length > 0) this.query.filter({ "$and": this.filters });
|
| 508 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 509 |
+
return new SmartList<Record<string, unknown>>(
|
| 510 |
+
await service.executeQuery(context.prepareQuery(this.query)) as Record<string, unknown>[]);
|
| 511 |
+
}
|
| 512 |
+
|
| 513 |
+
private async executeCountedListInternal(
|
| 514 |
+
context: UserContext,
|
| 515 |
+
): Promise<SmartList<OrderItem>> {
|
| 516 |
+
this.ensureIntent();
|
| 517 |
+
if (this.filters.length > 0) this.query.filter({ "$and": this.filters });
|
| 518 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 519 |
+
const preparedQuery = context.prepareQuery(this.query);
|
| 520 |
+
const useIdSet = preparedQuery.localIdSetPaginationOptions() !== undefined;
|
| 521 |
+
const countOperation = { kind: "named-count" as const,
|
| 522 |
+
method: this._pageCountMethod ?? "count",
|
| 523 |
+
...(this._pageCountMethod === "countAs" ? { alias: this._pageCountAlias } : {}) };
|
| 524 |
+
const totalCountBeforeRows = useIdSet ? undefined : await service.executeCount(
|
| 525 |
+
preparedQuery, this._pageCountAlias, countOperation);
|
| 526 |
+
const pageQuery = preparedQuery.clone();
|
| 527 |
+
// A page count describes the full filtered set, not an aggregate-only page row.
|
| 528 |
+
pageQuery.aggregateItems = pageQuery.aggregateItems.filter(item =>
|
| 529 |
+
!(String(item.function).toLowerCase() === "count" && item.alias === this._pageCountAlias));
|
| 530 |
+
const rows = await service.executeQuery(pageQuery);
|
| 531 |
+
const totalCount = useIdSet && context.idSetPaginationCountAccuracy === "EXACT"
|
| 532 |
+
? context.idSetPaginationCount!
|
| 533 |
+
: (totalCountBeforeRows ?? await service.executeCount(preparedQuery, this._pageCountAlias, countOperation));
|
| 534 |
+
const data = new SmartList(rows.map((row: unknown) =>
|
| 535 |
+
row instanceof OrderItem
|
| 536 |
+
? row
|
| 537 |
+
: OrderItem.fromRecord(row as Record<string, unknown>, new EntityRoot())));
|
| 538 |
+
data.totalCount = totalCount;
|
| 539 |
+
if (this._pageCountAlias !== undefined) data.aggregations[this._pageCountAlias] = totalCount;
|
| 540 |
+
if (this.query.facets.length > 0) {
|
| 541 |
+
data.facets = await executeRelationFacets(
|
| 542 |
+
service, (query: any) => context.prepareQuery(query), preparedQuery, preparedQuery.facets);
|
| 543 |
+
}
|
| 544 |
+
return data;
|
| 545 |
+
}
|
| 546 |
+
|
| 547 |
+
private executeForStreamInternal(context: UserContext, chunkSize: number): AsyncIterable<OrderItem> {
|
| 548 |
+
this.ensureIntent();
|
| 549 |
+
if (this.filters.length > 0) this.query.filter({ "$and": this.filters });
|
| 550 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 551 |
+
const preparedQuery = context.prepareQuery(this.query);
|
| 552 |
+
// Prepare Context and capture the runtime request before returning a lazy iterator.
|
| 553 |
+
const chunks = service.executeForStream(preparedQuery, chunkSize);
|
| 554 |
+
return (async function* () {
|
| 555 |
+
for await (const chunk of chunks) {
|
| 556 |
+
for (const entity of chunk) {
|
| 557 |
+
yield entity instanceof OrderItem
|
| 558 |
+
? entity
|
| 559 |
+
: OrderItem.fromRecord(entity as Record<string, unknown>, new EntityRoot());
|
| 560 |
+
}
|
| 561 |
+
}
|
| 562 |
+
})();
|
| 563 |
+
}
|
| 564 |
+
|
| 565 |
+
private ensureIntent(): void {
|
| 566 |
+
// Runtime owns validation, Unicode whitespace rules and typed diagnostics.
|
| 567 |
+
new QueryIntent(this._comment, this._purpose);
|
| 568 |
+
}
|
| 569 |
+
|
| 570 |
+
}
|
| 571 |
+
|
| 572 |
+
export class ExecutableOrderItemRequest {
|
| 573 |
+
constructor(
|
| 574 |
+
private readonly execute: (context: UserContext) => Promise<SmartList<OrderItem>>,
|
| 575 |
+
private readonly executeRows: (context: UserContext) => Promise<SmartList<Record<string, unknown>>>,
|
| 576 |
+
private readonly stream: (context: UserContext, chunkSize: number) => AsyncIterable<OrderItem>,
|
| 577 |
+
private readonly limitOne: () => void,
|
| 578 |
+
private readonly addComment: (comment: string) => void,
|
| 579 |
+
private readonly ensureIntent: () => void,
|
| 580 |
+
) {}
|
| 581 |
+
|
| 582 |
+
comment(c: string): this {
|
| 583 |
+
this.addComment(c);
|
| 584 |
+
return this;
|
| 585 |
+
}
|
| 586 |
+
|
| 587 |
+
newEntity(context: UserContext): OrderItem {
|
| 588 |
+
this.ensureIntent();
|
| 589 |
+
return new OrderItem();
|
| 590 |
+
}
|
| 591 |
+
|
| 592 |
+
executeForList(context: UserContext): Promise<SmartList<OrderItem>> {
|
| 593 |
+
this.ensureIntent();
|
| 594 |
+
return this.execute(context);
|
| 595 |
+
}
|
| 596 |
+
|
| 597 |
+
executeForRows(context: UserContext): Promise<SmartList<Record<string, unknown>>> {
|
| 598 |
+
this.ensureIntent();
|
| 599 |
+
return this.executeRows(context);
|
| 600 |
+
}
|
| 601 |
+
|
| 602 |
+
executeForStream(context: UserContext, chunkSize = 1000): AsyncIterable<OrderItem> {
|
| 603 |
+
this.ensureIntent();
|
| 604 |
+
return this.stream(context, chunkSize);
|
| 605 |
+
}
|
| 606 |
+
|
| 607 |
+
async executeForOne(context: UserContext): Promise<OrderItem | undefined> {
|
| 608 |
+
this.limitOne();
|
| 609 |
+
return (await this.executeForList(context))[0];
|
| 610 |
+
}
|
| 611 |
+
}
|
source/teaql-ts/examples/trace-chain/lib/src/generated/requests/PaymentAttemptRequest.ts
ADDED
|
@@ -0,0 +1,611 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { EntityRoot, SelectQuery, SmartList, TeaQLDataService, UserContext, executeRelationFacets } from '../../teaql-ts';
|
| 2 |
+
import { PaymentAttempt } from '../models/PaymentAttempt';
|
| 3 |
+
import { mergeGeneratedScalarSearch, DynamicSearchWarning, QueryIntent } from 'teaql-ts';
|
| 4 |
+
import { GENERATED_SEARCH_MODELS } from '../../generated-search-models';
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
export class PaymentAttemptRequest {
|
| 9 |
+
private query: SelectQuery;
|
| 10 |
+
private filters: any[] = [];
|
| 11 |
+
private _purpose: string | undefined;
|
| 12 |
+
private _comment: string | undefined;
|
| 13 |
+
private _pageCountAlias: string | undefined;
|
| 14 |
+
private _pageCountMethod: "count" | "countAs" | undefined;
|
| 15 |
+
private _dynamicSearchWarnings: DynamicSearchWarning[] = [];
|
| 16 |
+
|
| 17 |
+
constructor(minimal = false) {
|
| 18 |
+
this.query = new SelectQuery("PaymentAttempt");
|
| 19 |
+
this.filters.push({ version: { "$gte": 1 } });
|
| 20 |
+
if (minimal) {
|
| 21 |
+
this.selectId();
|
| 22 |
+
this.selectVersion();
|
| 23 |
+
}
|
| 24 |
+
else this.selectSelfFields();
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
comment(c: string): this {
|
| 28 |
+
this.query.comment(c);
|
| 29 |
+
this._comment = c;
|
| 30 |
+
return this;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
filterByJson(source: unknown, warn?: (warning: DynamicSearchWarning) => void): this {
|
| 34 |
+
const base = this.query.clone();
|
| 35 |
+
if (this.filters.length > 0) base.filter({ "$and": this.filters });
|
| 36 |
+
const merged = mergeGeneratedScalarSearch(base, source, GENERATED_SEARCH_MODELS, warn);
|
| 37 |
+
this.query = merged.query as SelectQuery;
|
| 38 |
+
this.filters = this.query.filterCondition ? [this.query.filterCondition] : [];
|
| 39 |
+
this._dynamicSearchWarnings.push(...merged.warnings);
|
| 40 |
+
return this;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
get dynamicSearchWarnings(): readonly DynamicSearchWarning[] {
|
| 44 |
+
return this._dynamicSearchWarnings.map(warning => ({ ...warning }));
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
purpose(p: string): ExecutablePaymentAttemptRequest {
|
| 48 |
+
this.query.purpose(p);
|
| 49 |
+
this._purpose = p;
|
| 50 |
+
return new ExecutablePaymentAttemptRequest(
|
| 51 |
+
(context) => context.withQueryRequest(this.query, () => this.executeForListInternal(context)),
|
| 52 |
+
(context) => context.withQueryRequest(this.query, () => this.executeForRowsInternal(context)),
|
| 53 |
+
(context, chunkSize) => this.executeForStreamInternal(context, chunkSize),
|
| 54 |
+
() => this.limit(1),
|
| 55 |
+
(c) => this.comment(c),
|
| 56 |
+
() => this.ensureIntent());
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
optimizeForContinuousPageFetch(): this {
|
| 60 |
+
this.query.optimizeForContinuousPageFetch();
|
| 61 |
+
return this;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
optimizeForContinuousPageFetchWith(namespace: string, ttlSeconds: number): this {
|
| 65 |
+
this.query.optimizeForContinuousPageFetchWith(namespace, ttlSeconds);
|
| 66 |
+
return this;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
optimizePaginationWithIdSet(): this {
|
| 70 |
+
this.query.optimizePaginationWithIdSet();
|
| 71 |
+
return this;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
optimizePaginationWithIdSetConfig(namespace: string, ttlSeconds: number, maxIds: number): this {
|
| 75 |
+
this.query.optimizePaginationWithIdSetConfig(namespace, ttlSeconds, maxIds);
|
| 76 |
+
return this;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
topNProbeParentThreshold(threshold: number): this {
|
| 80 |
+
this.query.topNProbeParentThreshold(threshold);
|
| 81 |
+
return this;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
limit(n: number): this {
|
| 85 |
+
this.query.limit(n);
|
| 86 |
+
return this;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
offset(n: number): this {
|
| 90 |
+
this.query.offset(n);
|
| 91 |
+
return this;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
toQuery(): SelectQuery {
|
| 95 |
+
if (this.filters.length > 0) {
|
| 96 |
+
this.query.filter({ "$and": this.filters });
|
| 97 |
+
}
|
| 98 |
+
return this.query;
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
withDeletedRows(): this {
|
| 102 |
+
this.filters = this.filters.filter(filter => !("version" in filter));
|
| 103 |
+
return this;
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
deletedRowsOnly(): this {
|
| 107 |
+
this.withDeletedRows();
|
| 108 |
+
this.filters.push({ version: { "$lte": -1 } });
|
| 109 |
+
return this;
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
selectSelfFields(): this {
|
| 113 |
+
this.query.select(["id", "payment", "referenceCode", "version"]);
|
| 114 |
+
return this;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
selectId(): this {
|
| 118 |
+
this.query.select(["id"]);
|
| 119 |
+
return this;
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
selectReferenceCode(): this {
|
| 124 |
+
this.query.select(["referenceCode"]);
|
| 125 |
+
return this;
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
selectVersion(): this {
|
| 129 |
+
this.query.select(["version"]);
|
| 130 |
+
return this;
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
selectPaymentWith(request: { toQuery(): SelectQuery }): this {
|
| 135 |
+
this.query.select(["payment"]);
|
| 136 |
+
this.query.relationQuery(
|
| 137 |
+
"payment", request.toQuery(), "payment", "id", false,
|
| 138 |
+
{ kind: "relation-select", method: "selectPaymentWith", relation: "payment" });
|
| 139 |
+
return this;
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
withPaymentMatching(request: { toQuery(): SelectQuery }): this {
|
| 143 |
+
this.filters.push({
|
| 144 |
+
"payment": {
|
| 145 |
+
"$inSubquery": { query: request.toQuery(), field: "id" },
|
| 146 |
+
},
|
| 147 |
+
});
|
| 148 |
+
return this;
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
withoutPaymentMatching(request: { toQuery(): SelectQuery }): this {
|
| 152 |
+
this.filters.push({
|
| 153 |
+
"payment": {
|
| 154 |
+
"$notInSubquery": { query: request.toQuery(), field: "id" },
|
| 155 |
+
},
|
| 156 |
+
});
|
| 157 |
+
return this;
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
withIdIs(val: any): this {
|
| 164 |
+
this.filters.push({ "id": { "$eq": val } });
|
| 165 |
+
return this;
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
withIdIsNot(val: any): this {
|
| 169 |
+
this.filters.push({ "id": { "$ne": val } });
|
| 170 |
+
return this;
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
withIdIn(...vals: any[]): this {
|
| 174 |
+
this.filters.push({ "id": { "$in": vals } });
|
| 175 |
+
return this;
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
withIdNotIn(...vals: any[]): this {
|
| 179 |
+
this.filters.push({ "id": { "$notIn": vals } });
|
| 180 |
+
return this;
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
withIdGreaterThan(val: any): this {
|
| 184 |
+
this.filters.push({ "id": { "$gt": val } });
|
| 185 |
+
return this;
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
withIdGreaterThanOrEqualTo(val: any): this {
|
| 189 |
+
this.filters.push({ "id": { "$gte": val } });
|
| 190 |
+
return this;
|
| 191 |
+
}
|
| 192 |
+
|
| 193 |
+
withIdLessThan(val: any): this {
|
| 194 |
+
this.filters.push({ "id": { "$lt": val } });
|
| 195 |
+
return this;
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
withIdLessThanOrEqualTo(val: any): this {
|
| 199 |
+
this.filters.push({ "id": { "$lte": val } });
|
| 200 |
+
return this;
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
withIdBetween(lower: any, upper: any): this {
|
| 204 |
+
this.filters.push({ "id": { "$between": [lower, upper] } });
|
| 205 |
+
return this;
|
| 206 |
+
}
|
| 207 |
+
|
| 208 |
+
withIdIsKnown(): this {
|
| 209 |
+
this.filters.push({ "id": { "$isNull": false } });
|
| 210 |
+
return this;
|
| 211 |
+
}
|
| 212 |
+
|
| 213 |
+
withIdIsUnknown(): this {
|
| 214 |
+
this.filters.push({ "id": { "$isNull": true } });
|
| 215 |
+
return this;
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
filterByPayment(val: any): this {
|
| 219 |
+
this.filters.push({ "payment": { "$eq": val } });
|
| 220 |
+
return this;
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
filterByPaymentIn(...vals: any[]): this {
|
| 224 |
+
this.filters.push({ "payment": { "$in": vals } });
|
| 225 |
+
return this;
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
+
withPaymentIsKnown(): this {
|
| 229 |
+
this.filters.push({ "payment": { "$isNull": false } });
|
| 230 |
+
return this;
|
| 231 |
+
}
|
| 232 |
+
|
| 233 |
+
withPaymentIsUnknown(): this {
|
| 234 |
+
this.filters.push({ "payment": { "$isNull": true } });
|
| 235 |
+
return this;
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
withReferenceCodeContaining(val: string): this {
|
| 239 |
+
this.filters.push({ "referenceCode": { "$contains": val } });
|
| 240 |
+
return this;
|
| 241 |
+
}
|
| 242 |
+
|
| 243 |
+
withReferenceCodeIs(val: string): this {
|
| 244 |
+
this.filters.push({ "referenceCode": { "$eq": val } });
|
| 245 |
+
return this;
|
| 246 |
+
}
|
| 247 |
+
|
| 248 |
+
withReferenceCodeIsNot(val: any): this {
|
| 249 |
+
this.filters.push({ "referenceCode": { "$ne": val } });
|
| 250 |
+
return this;
|
| 251 |
+
}
|
| 252 |
+
|
| 253 |
+
withReferenceCodeIn(...vals: any[]): this {
|
| 254 |
+
this.filters.push({ "referenceCode": { "$in": vals } });
|
| 255 |
+
return this;
|
| 256 |
+
}
|
| 257 |
+
|
| 258 |
+
withReferenceCodeNotIn(...vals: any[]): this {
|
| 259 |
+
this.filters.push({ "referenceCode": { "$notIn": vals } });
|
| 260 |
+
return this;
|
| 261 |
+
}
|
| 262 |
+
|
| 263 |
+
withReferenceCodeGreaterThan(val: any): this {
|
| 264 |
+
this.filters.push({ "referenceCode": { "$gt": val } });
|
| 265 |
+
return this;
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
withReferenceCodeGreaterThanOrEqualTo(val: any): this {
|
| 269 |
+
this.filters.push({ "referenceCode": { "$gte": val } });
|
| 270 |
+
return this;
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
withReferenceCodeLessThan(val: any): this {
|
| 274 |
+
this.filters.push({ "referenceCode": { "$lt": val } });
|
| 275 |
+
return this;
|
| 276 |
+
}
|
| 277 |
+
|
| 278 |
+
withReferenceCodeLessThanOrEqualTo(val: any): this {
|
| 279 |
+
this.filters.push({ "referenceCode": { "$lte": val } });
|
| 280 |
+
return this;
|
| 281 |
+
}
|
| 282 |
+
|
| 283 |
+
withReferenceCodeBetween(lower: any, upper: any): this {
|
| 284 |
+
this.filters.push({ "referenceCode": { "$between": [lower, upper] } });
|
| 285 |
+
return this;
|
| 286 |
+
}
|
| 287 |
+
|
| 288 |
+
withReferenceCodeIsKnown(): this {
|
| 289 |
+
this.filters.push({ "referenceCode": { "$isNull": false } });
|
| 290 |
+
return this;
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
withReferenceCodeIsUnknown(): this {
|
| 294 |
+
this.filters.push({ "referenceCode": { "$isNull": true } });
|
| 295 |
+
return this;
|
| 296 |
+
}
|
| 297 |
+
withReferenceCodeNotContaining(val: string): this {
|
| 298 |
+
this.filters.push({ "referenceCode": { "$notContains": val } });
|
| 299 |
+
return this;
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
withReferenceCodeStartingWith(val: string): this {
|
| 303 |
+
this.filters.push({ "referenceCode": { "$startsWith": val } });
|
| 304 |
+
return this;
|
| 305 |
+
}
|
| 306 |
+
|
| 307 |
+
withReferenceCodeNotStartingWith(val: string): this {
|
| 308 |
+
this.filters.push({ "referenceCode": { "$notStartsWith": val } });
|
| 309 |
+
return this;
|
| 310 |
+
}
|
| 311 |
+
|
| 312 |
+
withReferenceCodeEndingWith(val: string): this {
|
| 313 |
+
this.filters.push({ "referenceCode": { "$endsWith": val } });
|
| 314 |
+
return this;
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
withReferenceCodeNotEndingWith(val: string): this {
|
| 318 |
+
this.filters.push({ "referenceCode": { "$notEndsWith": val } });
|
| 319 |
+
return this;
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
withReferenceCodeSoundingLike(val: string): this {
|
| 323 |
+
this.filters.push({ "referenceCode": { "$soundLike": val } });
|
| 324 |
+
return this;
|
| 325 |
+
}
|
| 326 |
+
|
| 327 |
+
withVersionIs(val: any): this {
|
| 328 |
+
this.filters.push({ "version": { "$eq": val } });
|
| 329 |
+
return this;
|
| 330 |
+
}
|
| 331 |
+
|
| 332 |
+
withVersionIsNot(val: any): this {
|
| 333 |
+
this.filters.push({ "version": { "$ne": val } });
|
| 334 |
+
return this;
|
| 335 |
+
}
|
| 336 |
+
|
| 337 |
+
withVersionIn(...vals: any[]): this {
|
| 338 |
+
this.filters.push({ "version": { "$in": vals } });
|
| 339 |
+
return this;
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
withVersionNotIn(...vals: any[]): this {
|
| 343 |
+
this.filters.push({ "version": { "$notIn": vals } });
|
| 344 |
+
return this;
|
| 345 |
+
}
|
| 346 |
+
|
| 347 |
+
withVersionGreaterThan(val: any): this {
|
| 348 |
+
this.filters.push({ "version": { "$gt": val } });
|
| 349 |
+
return this;
|
| 350 |
+
}
|
| 351 |
+
|
| 352 |
+
withVersionGreaterThanOrEqualTo(val: any): this {
|
| 353 |
+
this.filters.push({ "version": { "$gte": val } });
|
| 354 |
+
return this;
|
| 355 |
+
}
|
| 356 |
+
|
| 357 |
+
withVersionLessThan(val: any): this {
|
| 358 |
+
this.filters.push({ "version": { "$lt": val } });
|
| 359 |
+
return this;
|
| 360 |
+
}
|
| 361 |
+
|
| 362 |
+
withVersionLessThanOrEqualTo(val: any): this {
|
| 363 |
+
this.filters.push({ "version": { "$lte": val } });
|
| 364 |
+
return this;
|
| 365 |
+
}
|
| 366 |
+
|
| 367 |
+
withVersionBetween(lower: any, upper: any): this {
|
| 368 |
+
this.filters.push({ "version": { "$between": [lower, upper] } });
|
| 369 |
+
return this;
|
| 370 |
+
}
|
| 371 |
+
|
| 372 |
+
withVersionIsKnown(): this {
|
| 373 |
+
this.filters.push({ "version": { "$isNull": false } });
|
| 374 |
+
return this;
|
| 375 |
+
}
|
| 376 |
+
|
| 377 |
+
withVersionIsUnknown(): this {
|
| 378 |
+
this.filters.push({ "version": { "$isNull": true } });
|
| 379 |
+
return this;
|
| 380 |
+
}
|
| 381 |
+
|
| 382 |
+
orderByIdAscending(): this {
|
| 383 |
+
this.query.orderBy("id", "asc");
|
| 384 |
+
return this;
|
| 385 |
+
}
|
| 386 |
+
|
| 387 |
+
orderByIdDescending(): this {
|
| 388 |
+
this.query.orderBy("id", "desc");
|
| 389 |
+
return this;
|
| 390 |
+
}
|
| 391 |
+
|
| 392 |
+
|
| 393 |
+
orderByReferenceCodeAscending(): this {
|
| 394 |
+
this.query.orderBy("referenceCode", "asc");
|
| 395 |
+
return this;
|
| 396 |
+
}
|
| 397 |
+
|
| 398 |
+
orderByReferenceCodeDescending(): this {
|
| 399 |
+
this.query.orderBy("referenceCode", "desc");
|
| 400 |
+
return this;
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
orderByVersionAscending(): this {
|
| 404 |
+
this.query.orderBy("version", "asc");
|
| 405 |
+
return this;
|
| 406 |
+
}
|
| 407 |
+
|
| 408 |
+
orderByVersionDescending(): this {
|
| 409 |
+
this.query.orderBy("version", "desc");
|
| 410 |
+
return this;
|
| 411 |
+
}
|
| 412 |
+
|
| 413 |
+
|
| 414 |
+
// --- Aggregations ---
|
| 415 |
+
count(): this {
|
| 416 |
+
this.query.aggregate("Count", "id", "count");
|
| 417 |
+
this._pageCountAlias = "count";
|
| 418 |
+
this._pageCountMethod = "count";
|
| 419 |
+
return this;
|
| 420 |
+
}
|
| 421 |
+
|
| 422 |
+
countAs(retName: string): this {
|
| 423 |
+
this.query.aggregate("Count", "id", retName);
|
| 424 |
+
this._pageCountAlias = retName;
|
| 425 |
+
this._pageCountMethod = "countAs";
|
| 426 |
+
return this;
|
| 427 |
+
}
|
| 428 |
+
|
| 429 |
+
|
| 430 |
+
// --- Group By ---
|
| 431 |
+
groupById(): this {
|
| 432 |
+
this.query.groupBy("id");
|
| 433 |
+
return this;
|
| 434 |
+
}
|
| 435 |
+
|
| 436 |
+
groupByIdAs(retName: string): this {
|
| 437 |
+
this.query.groupBy("id"); // In TS we don't alias group by yet natively
|
| 438 |
+
return this;
|
| 439 |
+
}
|
| 440 |
+
groupByPayment(): this {
|
| 441 |
+
this.query.groupBy("payment");
|
| 442 |
+
return this;
|
| 443 |
+
}
|
| 444 |
+
|
| 445 |
+
groupByPaymentAs(retName: string): this {
|
| 446 |
+
this.query.groupBy("payment"); // In TS we don't alias group by yet natively
|
| 447 |
+
return this;
|
| 448 |
+
}
|
| 449 |
+
groupByReferenceCode(): this {
|
| 450 |
+
this.query.groupBy("referenceCode");
|
| 451 |
+
return this;
|
| 452 |
+
}
|
| 453 |
+
|
| 454 |
+
groupByReferenceCodeAs(retName: string): this {
|
| 455 |
+
this.query.groupBy("referenceCode"); // In TS we don't alias group by yet natively
|
| 456 |
+
return this;
|
| 457 |
+
}
|
| 458 |
+
groupByVersion(): this {
|
| 459 |
+
this.query.groupBy("version");
|
| 460 |
+
return this;
|
| 461 |
+
}
|
| 462 |
+
|
| 463 |
+
groupByVersionAs(retName: string): this {
|
| 464 |
+
this.query.groupBy("version"); // In TS we don't alias group by yet natively
|
| 465 |
+
return this;
|
| 466 |
+
}
|
| 467 |
+
|
| 468 |
+
// --- Facets ---
|
| 469 |
+
facetByPaymentAs(
|
| 470 |
+
facetName: string,
|
| 471 |
+
request: { toQuery(): SelectQuery },
|
| 472 |
+
includeAllFacets = true,
|
| 473 |
+
): this {
|
| 474 |
+
this.query.facetBy(facetName, "payment", request, includeAllFacets,
|
| 475 |
+
{ kind: "facet", method: "facetByPaymentAs", relation: "payment", alias: facetName });
|
| 476 |
+
return this;
|
| 477 |
+
}
|
| 478 |
+
|
| 479 |
+
|
| 480 |
+
private async executeForListInternal(context: UserContext): Promise<SmartList<PaymentAttempt>> {
|
| 481 |
+
this.ensureIntent();
|
| 482 |
+
if (this._pageCountAlias !== undefined) return this.executeCountedListInternal(context);
|
| 483 |
+
if (this.filters.length > 0) {
|
| 484 |
+
this.query.filter({ "$and": this.filters });
|
| 485 |
+
}
|
| 486 |
+
|
| 487 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 488 |
+
const rows = await service.executeQuery(context.prepareQuery(this.query));
|
| 489 |
+
const aggregateOnly = this.query.aggregateItems.length > 0 && this.query.groupByItems.length === 0;
|
| 490 |
+
const data = aggregateOnly ? [] : rows.map((row: unknown) =>
|
| 491 |
+
row instanceof PaymentAttempt
|
| 492 |
+
? row
|
| 493 |
+
: PaymentAttempt.fromRecord(row as Record<string, unknown>, new EntityRoot()));
|
| 494 |
+
const result = new SmartList<PaymentAttempt>(data);
|
| 495 |
+
if (aggregateOnly && rows[0]) Object.assign(result.aggregations, rows[0]);
|
| 496 |
+
|
| 497 |
+
if (this.query.facets.length > 0) {
|
| 498 |
+
result.facets = await executeRelationFacets(
|
| 499 |
+
service, (query: any) => context.prepareQuery(query), this.query, this.query.facets);
|
| 500 |
+
}
|
| 501 |
+
|
| 502 |
+
return result;
|
| 503 |
+
}
|
| 504 |
+
|
| 505 |
+
private async executeForRowsInternal(context: UserContext): Promise<SmartList<Record<string, unknown>>> {
|
| 506 |
+
this.ensureIntent();
|
| 507 |
+
if (this.filters.length > 0) this.query.filter({ "$and": this.filters });
|
| 508 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 509 |
+
return new SmartList<Record<string, unknown>>(
|
| 510 |
+
await service.executeQuery(context.prepareQuery(this.query)) as Record<string, unknown>[]);
|
| 511 |
+
}
|
| 512 |
+
|
| 513 |
+
private async executeCountedListInternal(
|
| 514 |
+
context: UserContext,
|
| 515 |
+
): Promise<SmartList<PaymentAttempt>> {
|
| 516 |
+
this.ensureIntent();
|
| 517 |
+
if (this.filters.length > 0) this.query.filter({ "$and": this.filters });
|
| 518 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 519 |
+
const preparedQuery = context.prepareQuery(this.query);
|
| 520 |
+
const useIdSet = preparedQuery.localIdSetPaginationOptions() !== undefined;
|
| 521 |
+
const countOperation = { kind: "named-count" as const,
|
| 522 |
+
method: this._pageCountMethod ?? "count",
|
| 523 |
+
...(this._pageCountMethod === "countAs" ? { alias: this._pageCountAlias } : {}) };
|
| 524 |
+
const totalCountBeforeRows = useIdSet ? undefined : await service.executeCount(
|
| 525 |
+
preparedQuery, this._pageCountAlias, countOperation);
|
| 526 |
+
const pageQuery = preparedQuery.clone();
|
| 527 |
+
// A page count describes the full filtered set, not an aggregate-only page row.
|
| 528 |
+
pageQuery.aggregateItems = pageQuery.aggregateItems.filter(item =>
|
| 529 |
+
!(String(item.function).toLowerCase() === "count" && item.alias === this._pageCountAlias));
|
| 530 |
+
const rows = await service.executeQuery(pageQuery);
|
| 531 |
+
const totalCount = useIdSet && context.idSetPaginationCountAccuracy === "EXACT"
|
| 532 |
+
? context.idSetPaginationCount!
|
| 533 |
+
: (totalCountBeforeRows ?? await service.executeCount(preparedQuery, this._pageCountAlias, countOperation));
|
| 534 |
+
const data = new SmartList(rows.map((row: unknown) =>
|
| 535 |
+
row instanceof PaymentAttempt
|
| 536 |
+
? row
|
| 537 |
+
: PaymentAttempt.fromRecord(row as Record<string, unknown>, new EntityRoot())));
|
| 538 |
+
data.totalCount = totalCount;
|
| 539 |
+
if (this._pageCountAlias !== undefined) data.aggregations[this._pageCountAlias] = totalCount;
|
| 540 |
+
if (this.query.facets.length > 0) {
|
| 541 |
+
data.facets = await executeRelationFacets(
|
| 542 |
+
service, (query: any) => context.prepareQuery(query), preparedQuery, preparedQuery.facets);
|
| 543 |
+
}
|
| 544 |
+
return data;
|
| 545 |
+
}
|
| 546 |
+
|
| 547 |
+
private executeForStreamInternal(context: UserContext, chunkSize: number): AsyncIterable<PaymentAttempt> {
|
| 548 |
+
this.ensureIntent();
|
| 549 |
+
if (this.filters.length > 0) this.query.filter({ "$and": this.filters });
|
| 550 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 551 |
+
const preparedQuery = context.prepareQuery(this.query);
|
| 552 |
+
// Prepare Context and capture the runtime request before returning a lazy iterator.
|
| 553 |
+
const chunks = service.executeForStream(preparedQuery, chunkSize);
|
| 554 |
+
return (async function* () {
|
| 555 |
+
for await (const chunk of chunks) {
|
| 556 |
+
for (const entity of chunk) {
|
| 557 |
+
yield entity instanceof PaymentAttempt
|
| 558 |
+
? entity
|
| 559 |
+
: PaymentAttempt.fromRecord(entity as Record<string, unknown>, new EntityRoot());
|
| 560 |
+
}
|
| 561 |
+
}
|
| 562 |
+
})();
|
| 563 |
+
}
|
| 564 |
+
|
| 565 |
+
private ensureIntent(): void {
|
| 566 |
+
// Runtime owns validation, Unicode whitespace rules and typed diagnostics.
|
| 567 |
+
new QueryIntent(this._comment, this._purpose);
|
| 568 |
+
}
|
| 569 |
+
|
| 570 |
+
}
|
| 571 |
+
|
| 572 |
+
export class ExecutablePaymentAttemptRequest {
|
| 573 |
+
constructor(
|
| 574 |
+
private readonly execute: (context: UserContext) => Promise<SmartList<PaymentAttempt>>,
|
| 575 |
+
private readonly executeRows: (context: UserContext) => Promise<SmartList<Record<string, unknown>>>,
|
| 576 |
+
private readonly stream: (context: UserContext, chunkSize: number) => AsyncIterable<PaymentAttempt>,
|
| 577 |
+
private readonly limitOne: () => void,
|
| 578 |
+
private readonly addComment: (comment: string) => void,
|
| 579 |
+
private readonly ensureIntent: () => void,
|
| 580 |
+
) {}
|
| 581 |
+
|
| 582 |
+
comment(c: string): this {
|
| 583 |
+
this.addComment(c);
|
| 584 |
+
return this;
|
| 585 |
+
}
|
| 586 |
+
|
| 587 |
+
newEntity(context: UserContext): PaymentAttempt {
|
| 588 |
+
this.ensureIntent();
|
| 589 |
+
return new PaymentAttempt();
|
| 590 |
+
}
|
| 591 |
+
|
| 592 |
+
executeForList(context: UserContext): Promise<SmartList<PaymentAttempt>> {
|
| 593 |
+
this.ensureIntent();
|
| 594 |
+
return this.execute(context);
|
| 595 |
+
}
|
| 596 |
+
|
| 597 |
+
executeForRows(context: UserContext): Promise<SmartList<Record<string, unknown>>> {
|
| 598 |
+
this.ensureIntent();
|
| 599 |
+
return this.executeRows(context);
|
| 600 |
+
}
|
| 601 |
+
|
| 602 |
+
executeForStream(context: UserContext, chunkSize = 1000): AsyncIterable<PaymentAttempt> {
|
| 603 |
+
this.ensureIntent();
|
| 604 |
+
return this.stream(context, chunkSize);
|
| 605 |
+
}
|
| 606 |
+
|
| 607 |
+
async executeForOne(context: UserContext): Promise<PaymentAttempt | undefined> {
|
| 608 |
+
this.limitOne();
|
| 609 |
+
return (await this.executeForList(context))[0];
|
| 610 |
+
}
|
| 611 |
+
}
|
source/teaql-ts/examples/trace-chain/lib/src/generated/requests/PaymentRequest.ts
ADDED
|
@@ -0,0 +1,672 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { EntityRoot, SelectQuery, SmartList, TeaQLDataService, UserContext, executeRelationFacets } from '../../teaql-ts';
|
| 2 |
+
import { Payment } from '../models/Payment';
|
| 3 |
+
import { mergeGeneratedScalarSearch, DynamicSearchWarning, QueryIntent } from 'teaql-ts';
|
| 4 |
+
import { GENERATED_SEARCH_MODELS } from '../../generated-search-models';
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
export class PaymentRequest {
|
| 9 |
+
private query: SelectQuery;
|
| 10 |
+
private filters: any[] = [];
|
| 11 |
+
private _purpose: string | undefined;
|
| 12 |
+
private _comment: string | undefined;
|
| 13 |
+
private _pageCountAlias: string | undefined;
|
| 14 |
+
private _pageCountMethod: "count" | "countAs" | undefined;
|
| 15 |
+
private _dynamicSearchWarnings: DynamicSearchWarning[] = [];
|
| 16 |
+
|
| 17 |
+
constructor(minimal = false) {
|
| 18 |
+
this.query = new SelectQuery("Payment");
|
| 19 |
+
this.filters.push({ version: { "$gte": 1 } });
|
| 20 |
+
if (minimal) {
|
| 21 |
+
this.selectId();
|
| 22 |
+
this.selectVersion();
|
| 23 |
+
}
|
| 24 |
+
else this.selectSelfFields();
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
comment(c: string): this {
|
| 28 |
+
this.query.comment(c);
|
| 29 |
+
this._comment = c;
|
| 30 |
+
return this;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
filterByJson(source: unknown, warn?: (warning: DynamicSearchWarning) => void): this {
|
| 34 |
+
const base = this.query.clone();
|
| 35 |
+
if (this.filters.length > 0) base.filter({ "$and": this.filters });
|
| 36 |
+
const merged = mergeGeneratedScalarSearch(base, source, GENERATED_SEARCH_MODELS, warn);
|
| 37 |
+
this.query = merged.query as SelectQuery;
|
| 38 |
+
this.filters = this.query.filterCondition ? [this.query.filterCondition] : [];
|
| 39 |
+
this._dynamicSearchWarnings.push(...merged.warnings);
|
| 40 |
+
return this;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
get dynamicSearchWarnings(): readonly DynamicSearchWarning[] {
|
| 44 |
+
return this._dynamicSearchWarnings.map(warning => ({ ...warning }));
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
purpose(p: string): ExecutablePaymentRequest {
|
| 48 |
+
this.query.purpose(p);
|
| 49 |
+
this._purpose = p;
|
| 50 |
+
return new ExecutablePaymentRequest(
|
| 51 |
+
(context) => context.withQueryRequest(this.query, () => this.executeForListInternal(context)),
|
| 52 |
+
(context) => context.withQueryRequest(this.query, () => this.executeForRowsInternal(context)),
|
| 53 |
+
(context, chunkSize) => this.executeForStreamInternal(context, chunkSize),
|
| 54 |
+
() => this.limit(1),
|
| 55 |
+
(c) => this.comment(c),
|
| 56 |
+
() => this.ensureIntent());
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
optimizeForContinuousPageFetch(): this {
|
| 60 |
+
this.query.optimizeForContinuousPageFetch();
|
| 61 |
+
return this;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
optimizeForContinuousPageFetchWith(namespace: string, ttlSeconds: number): this {
|
| 65 |
+
this.query.optimizeForContinuousPageFetchWith(namespace, ttlSeconds);
|
| 66 |
+
return this;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
optimizePaginationWithIdSet(): this {
|
| 70 |
+
this.query.optimizePaginationWithIdSet();
|
| 71 |
+
return this;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
optimizePaginationWithIdSetConfig(namespace: string, ttlSeconds: number, maxIds: number): this {
|
| 75 |
+
this.query.optimizePaginationWithIdSetConfig(namespace, ttlSeconds, maxIds);
|
| 76 |
+
return this;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
topNProbeParentThreshold(threshold: number): this {
|
| 80 |
+
this.query.topNProbeParentThreshold(threshold);
|
| 81 |
+
return this;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
limit(n: number): this {
|
| 85 |
+
this.query.limit(n);
|
| 86 |
+
return this;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
offset(n: number): this {
|
| 90 |
+
this.query.offset(n);
|
| 91 |
+
return this;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
toQuery(): SelectQuery {
|
| 95 |
+
if (this.filters.length > 0) {
|
| 96 |
+
this.query.filter({ "$and": this.filters });
|
| 97 |
+
}
|
| 98 |
+
return this.query;
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
withDeletedRows(): this {
|
| 102 |
+
this.filters = this.filters.filter(filter => !("version" in filter));
|
| 103 |
+
return this;
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
deletedRowsOnly(): this {
|
| 107 |
+
this.withDeletedRows();
|
| 108 |
+
this.filters.push({ version: { "$lte": -1 } });
|
| 109 |
+
return this;
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
selectSelfFields(): this {
|
| 113 |
+
this.query.select(["id", "customerOrder", "referenceCode", "version"]);
|
| 114 |
+
return this;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
selectId(): this {
|
| 118 |
+
this.query.select(["id"]);
|
| 119 |
+
return this;
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
selectReferenceCode(): this {
|
| 124 |
+
this.query.select(["referenceCode"]);
|
| 125 |
+
return this;
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
selectVersion(): this {
|
| 129 |
+
this.query.select(["version"]);
|
| 130 |
+
return this;
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
selectCustomerOrderWith(request: { toQuery(): SelectQuery }): this {
|
| 135 |
+
this.query.select(["customerOrder"]);
|
| 136 |
+
this.query.relationQuery(
|
| 137 |
+
"customerOrder", request.toQuery(), "customerOrder", "id", false,
|
| 138 |
+
{ kind: "relation-select", method: "selectCustomerOrderWith", relation: "customerOrder" });
|
| 139 |
+
return this;
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
withCustomerOrderMatching(request: { toQuery(): SelectQuery }): this {
|
| 143 |
+
this.filters.push({
|
| 144 |
+
"customerOrder": {
|
| 145 |
+
"$inSubquery": { query: request.toQuery(), field: "id" },
|
| 146 |
+
},
|
| 147 |
+
});
|
| 148 |
+
return this;
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
withoutCustomerOrderMatching(request: { toQuery(): SelectQuery }): this {
|
| 152 |
+
this.filters.push({
|
| 153 |
+
"customerOrder": {
|
| 154 |
+
"$notInSubquery": { query: request.toQuery(), field: "id" },
|
| 155 |
+
},
|
| 156 |
+
});
|
| 157 |
+
return this;
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
selectPaymentAttemptListWith(request: { toQuery(): SelectQuery }): this {
|
| 161 |
+
this.query.relationQuery(
|
| 162 |
+
"paymentAttemptList", request.toQuery(), "id", "payment", true,
|
| 163 |
+
{ kind: "relation-select", method: "selectPaymentAttemptListWith", relation: "paymentAttemptList" });
|
| 164 |
+
return this;
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
havePaymentAttempts(): this {
|
| 168 |
+
return this.withPaymentAttemptListMatching({
|
| 169 |
+
toQuery: () => new SelectQuery("PaymentAttempt"),
|
| 170 |
+
});
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
haveNoPaymentAttempts(): this {
|
| 174 |
+
return this.withoutPaymentAttemptListMatching({
|
| 175 |
+
toQuery: () => new SelectQuery("PaymentAttempt"),
|
| 176 |
+
});
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
withPaymentAttemptListMatching(request: { toQuery(): SelectQuery }): this {
|
| 180 |
+
this.filters.push({
|
| 181 |
+
"id": {
|
| 182 |
+
"$inSubquery": {
|
| 183 |
+
query: request.toQuery(), field: "payment",
|
| 184 |
+
},
|
| 185 |
+
},
|
| 186 |
+
});
|
| 187 |
+
return this;
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
withoutPaymentAttemptListMatching(request: { toQuery(): SelectQuery }): this {
|
| 191 |
+
this.filters.push({
|
| 192 |
+
"id": {
|
| 193 |
+
"$notInSubquery": {
|
| 194 |
+
query: request.toQuery(), field: "payment",
|
| 195 |
+
},
|
| 196 |
+
},
|
| 197 |
+
});
|
| 198 |
+
return this;
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
countPaymentAttempts(): this {
|
| 202 |
+
return this.countPaymentAttemptsAs("countPaymentAttempts");
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
countPaymentAttemptsAs(alias: string): this {
|
| 206 |
+
const query = new SelectQuery("PaymentAttempt").filter({ version: { "$gte": 1 } });
|
| 207 |
+
this.countPaymentAttemptsWith(alias, { toQuery: () => query });
|
| 208 |
+
this.query.relationAggregates[this.query.relationAggregates.length - 1].operation = {
|
| 209 |
+
kind: "relation-count", method: "countPaymentAttemptsAs", relation: "paymentAttemptList", alias };
|
| 210 |
+
return this;
|
| 211 |
+
}
|
| 212 |
+
|
| 213 |
+
countPaymentAttemptsWith(alias: string, child: { toQuery(): SelectQuery }): this {
|
| 214 |
+
const query = child.toQuery().clone();
|
| 215 |
+
query.aggregateItems = [];
|
| 216 |
+
query.aggregate("Count", "id", alias);
|
| 217 |
+
this.query.relationAggregate("paymentAttemptList", alias, query, true,
|
| 218 |
+
{ kind: "relation-count", method: "countPaymentAttemptsWith", relation: "paymentAttemptList", alias });
|
| 219 |
+
return this;
|
| 220 |
+
}
|
| 221 |
+
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
withIdIs(val: any): this {
|
| 225 |
+
this.filters.push({ "id": { "$eq": val } });
|
| 226 |
+
return this;
|
| 227 |
+
}
|
| 228 |
+
|
| 229 |
+
withIdIsNot(val: any): this {
|
| 230 |
+
this.filters.push({ "id": { "$ne": val } });
|
| 231 |
+
return this;
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
withIdIn(...vals: any[]): this {
|
| 235 |
+
this.filters.push({ "id": { "$in": vals } });
|
| 236 |
+
return this;
|
| 237 |
+
}
|
| 238 |
+
|
| 239 |
+
withIdNotIn(...vals: any[]): this {
|
| 240 |
+
this.filters.push({ "id": { "$notIn": vals } });
|
| 241 |
+
return this;
|
| 242 |
+
}
|
| 243 |
+
|
| 244 |
+
withIdGreaterThan(val: any): this {
|
| 245 |
+
this.filters.push({ "id": { "$gt": val } });
|
| 246 |
+
return this;
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
withIdGreaterThanOrEqualTo(val: any): this {
|
| 250 |
+
this.filters.push({ "id": { "$gte": val } });
|
| 251 |
+
return this;
|
| 252 |
+
}
|
| 253 |
+
|
| 254 |
+
withIdLessThan(val: any): this {
|
| 255 |
+
this.filters.push({ "id": { "$lt": val } });
|
| 256 |
+
return this;
|
| 257 |
+
}
|
| 258 |
+
|
| 259 |
+
withIdLessThanOrEqualTo(val: any): this {
|
| 260 |
+
this.filters.push({ "id": { "$lte": val } });
|
| 261 |
+
return this;
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
withIdBetween(lower: any, upper: any): this {
|
| 265 |
+
this.filters.push({ "id": { "$between": [lower, upper] } });
|
| 266 |
+
return this;
|
| 267 |
+
}
|
| 268 |
+
|
| 269 |
+
withIdIsKnown(): this {
|
| 270 |
+
this.filters.push({ "id": { "$isNull": false } });
|
| 271 |
+
return this;
|
| 272 |
+
}
|
| 273 |
+
|
| 274 |
+
withIdIsUnknown(): this {
|
| 275 |
+
this.filters.push({ "id": { "$isNull": true } });
|
| 276 |
+
return this;
|
| 277 |
+
}
|
| 278 |
+
|
| 279 |
+
filterByCustomerOrder(val: any): this {
|
| 280 |
+
this.filters.push({ "customerOrder": { "$eq": val } });
|
| 281 |
+
return this;
|
| 282 |
+
}
|
| 283 |
+
|
| 284 |
+
filterByCustomerOrderIn(...vals: any[]): this {
|
| 285 |
+
this.filters.push({ "customerOrder": { "$in": vals } });
|
| 286 |
+
return this;
|
| 287 |
+
}
|
| 288 |
+
|
| 289 |
+
withCustomerOrderIsKnown(): this {
|
| 290 |
+
this.filters.push({ "customerOrder": { "$isNull": false } });
|
| 291 |
+
return this;
|
| 292 |
+
}
|
| 293 |
+
|
| 294 |
+
withCustomerOrderIsUnknown(): this {
|
| 295 |
+
this.filters.push({ "customerOrder": { "$isNull": true } });
|
| 296 |
+
return this;
|
| 297 |
+
}
|
| 298 |
+
|
| 299 |
+
withReferenceCodeContaining(val: string): this {
|
| 300 |
+
this.filters.push({ "referenceCode": { "$contains": val } });
|
| 301 |
+
return this;
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
withReferenceCodeIs(val: string): this {
|
| 305 |
+
this.filters.push({ "referenceCode": { "$eq": val } });
|
| 306 |
+
return this;
|
| 307 |
+
}
|
| 308 |
+
|
| 309 |
+
withReferenceCodeIsNot(val: any): this {
|
| 310 |
+
this.filters.push({ "referenceCode": { "$ne": val } });
|
| 311 |
+
return this;
|
| 312 |
+
}
|
| 313 |
+
|
| 314 |
+
withReferenceCodeIn(...vals: any[]): this {
|
| 315 |
+
this.filters.push({ "referenceCode": { "$in": vals } });
|
| 316 |
+
return this;
|
| 317 |
+
}
|
| 318 |
+
|
| 319 |
+
withReferenceCodeNotIn(...vals: any[]): this {
|
| 320 |
+
this.filters.push({ "referenceCode": { "$notIn": vals } });
|
| 321 |
+
return this;
|
| 322 |
+
}
|
| 323 |
+
|
| 324 |
+
withReferenceCodeGreaterThan(val: any): this {
|
| 325 |
+
this.filters.push({ "referenceCode": { "$gt": val } });
|
| 326 |
+
return this;
|
| 327 |
+
}
|
| 328 |
+
|
| 329 |
+
withReferenceCodeGreaterThanOrEqualTo(val: any): this {
|
| 330 |
+
this.filters.push({ "referenceCode": { "$gte": val } });
|
| 331 |
+
return this;
|
| 332 |
+
}
|
| 333 |
+
|
| 334 |
+
withReferenceCodeLessThan(val: any): this {
|
| 335 |
+
this.filters.push({ "referenceCode": { "$lt": val } });
|
| 336 |
+
return this;
|
| 337 |
+
}
|
| 338 |
+
|
| 339 |
+
withReferenceCodeLessThanOrEqualTo(val: any): this {
|
| 340 |
+
this.filters.push({ "referenceCode": { "$lte": val } });
|
| 341 |
+
return this;
|
| 342 |
+
}
|
| 343 |
+
|
| 344 |
+
withReferenceCodeBetween(lower: any, upper: any): this {
|
| 345 |
+
this.filters.push({ "referenceCode": { "$between": [lower, upper] } });
|
| 346 |
+
return this;
|
| 347 |
+
}
|
| 348 |
+
|
| 349 |
+
withReferenceCodeIsKnown(): this {
|
| 350 |
+
this.filters.push({ "referenceCode": { "$isNull": false } });
|
| 351 |
+
return this;
|
| 352 |
+
}
|
| 353 |
+
|
| 354 |
+
withReferenceCodeIsUnknown(): this {
|
| 355 |
+
this.filters.push({ "referenceCode": { "$isNull": true } });
|
| 356 |
+
return this;
|
| 357 |
+
}
|
| 358 |
+
withReferenceCodeNotContaining(val: string): this {
|
| 359 |
+
this.filters.push({ "referenceCode": { "$notContains": val } });
|
| 360 |
+
return this;
|
| 361 |
+
}
|
| 362 |
+
|
| 363 |
+
withReferenceCodeStartingWith(val: string): this {
|
| 364 |
+
this.filters.push({ "referenceCode": { "$startsWith": val } });
|
| 365 |
+
return this;
|
| 366 |
+
}
|
| 367 |
+
|
| 368 |
+
withReferenceCodeNotStartingWith(val: string): this {
|
| 369 |
+
this.filters.push({ "referenceCode": { "$notStartsWith": val } });
|
| 370 |
+
return this;
|
| 371 |
+
}
|
| 372 |
+
|
| 373 |
+
withReferenceCodeEndingWith(val: string): this {
|
| 374 |
+
this.filters.push({ "referenceCode": { "$endsWith": val } });
|
| 375 |
+
return this;
|
| 376 |
+
}
|
| 377 |
+
|
| 378 |
+
withReferenceCodeNotEndingWith(val: string): this {
|
| 379 |
+
this.filters.push({ "referenceCode": { "$notEndsWith": val } });
|
| 380 |
+
return this;
|
| 381 |
+
}
|
| 382 |
+
|
| 383 |
+
withReferenceCodeSoundingLike(val: string): this {
|
| 384 |
+
this.filters.push({ "referenceCode": { "$soundLike": val } });
|
| 385 |
+
return this;
|
| 386 |
+
}
|
| 387 |
+
|
| 388 |
+
withVersionIs(val: any): this {
|
| 389 |
+
this.filters.push({ "version": { "$eq": val } });
|
| 390 |
+
return this;
|
| 391 |
+
}
|
| 392 |
+
|
| 393 |
+
withVersionIsNot(val: any): this {
|
| 394 |
+
this.filters.push({ "version": { "$ne": val } });
|
| 395 |
+
return this;
|
| 396 |
+
}
|
| 397 |
+
|
| 398 |
+
withVersionIn(...vals: any[]): this {
|
| 399 |
+
this.filters.push({ "version": { "$in": vals } });
|
| 400 |
+
return this;
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
withVersionNotIn(...vals: any[]): this {
|
| 404 |
+
this.filters.push({ "version": { "$notIn": vals } });
|
| 405 |
+
return this;
|
| 406 |
+
}
|
| 407 |
+
|
| 408 |
+
withVersionGreaterThan(val: any): this {
|
| 409 |
+
this.filters.push({ "version": { "$gt": val } });
|
| 410 |
+
return this;
|
| 411 |
+
}
|
| 412 |
+
|
| 413 |
+
withVersionGreaterThanOrEqualTo(val: any): this {
|
| 414 |
+
this.filters.push({ "version": { "$gte": val } });
|
| 415 |
+
return this;
|
| 416 |
+
}
|
| 417 |
+
|
| 418 |
+
withVersionLessThan(val: any): this {
|
| 419 |
+
this.filters.push({ "version": { "$lt": val } });
|
| 420 |
+
return this;
|
| 421 |
+
}
|
| 422 |
+
|
| 423 |
+
withVersionLessThanOrEqualTo(val: any): this {
|
| 424 |
+
this.filters.push({ "version": { "$lte": val } });
|
| 425 |
+
return this;
|
| 426 |
+
}
|
| 427 |
+
|
| 428 |
+
withVersionBetween(lower: any, upper: any): this {
|
| 429 |
+
this.filters.push({ "version": { "$between": [lower, upper] } });
|
| 430 |
+
return this;
|
| 431 |
+
}
|
| 432 |
+
|
| 433 |
+
withVersionIsKnown(): this {
|
| 434 |
+
this.filters.push({ "version": { "$isNull": false } });
|
| 435 |
+
return this;
|
| 436 |
+
}
|
| 437 |
+
|
| 438 |
+
withVersionIsUnknown(): this {
|
| 439 |
+
this.filters.push({ "version": { "$isNull": true } });
|
| 440 |
+
return this;
|
| 441 |
+
}
|
| 442 |
+
|
| 443 |
+
orderByIdAscending(): this {
|
| 444 |
+
this.query.orderBy("id", "asc");
|
| 445 |
+
return this;
|
| 446 |
+
}
|
| 447 |
+
|
| 448 |
+
orderByIdDescending(): this {
|
| 449 |
+
this.query.orderBy("id", "desc");
|
| 450 |
+
return this;
|
| 451 |
+
}
|
| 452 |
+
|
| 453 |
+
|
| 454 |
+
orderByReferenceCodeAscending(): this {
|
| 455 |
+
this.query.orderBy("referenceCode", "asc");
|
| 456 |
+
return this;
|
| 457 |
+
}
|
| 458 |
+
|
| 459 |
+
orderByReferenceCodeDescending(): this {
|
| 460 |
+
this.query.orderBy("referenceCode", "desc");
|
| 461 |
+
return this;
|
| 462 |
+
}
|
| 463 |
+
|
| 464 |
+
orderByVersionAscending(): this {
|
| 465 |
+
this.query.orderBy("version", "asc");
|
| 466 |
+
return this;
|
| 467 |
+
}
|
| 468 |
+
|
| 469 |
+
orderByVersionDescending(): this {
|
| 470 |
+
this.query.orderBy("version", "desc");
|
| 471 |
+
return this;
|
| 472 |
+
}
|
| 473 |
+
|
| 474 |
+
|
| 475 |
+
// --- Aggregations ---
|
| 476 |
+
count(): this {
|
| 477 |
+
this.query.aggregate("Count", "id", "count");
|
| 478 |
+
this._pageCountAlias = "count";
|
| 479 |
+
this._pageCountMethod = "count";
|
| 480 |
+
return this;
|
| 481 |
+
}
|
| 482 |
+
|
| 483 |
+
countAs(retName: string): this {
|
| 484 |
+
this.query.aggregate("Count", "id", retName);
|
| 485 |
+
this._pageCountAlias = retName;
|
| 486 |
+
this._pageCountMethod = "countAs";
|
| 487 |
+
return this;
|
| 488 |
+
}
|
| 489 |
+
|
| 490 |
+
|
| 491 |
+
// --- Group By ---
|
| 492 |
+
groupById(): this {
|
| 493 |
+
this.query.groupBy("id");
|
| 494 |
+
return this;
|
| 495 |
+
}
|
| 496 |
+
|
| 497 |
+
groupByIdAs(retName: string): this {
|
| 498 |
+
this.query.groupBy("id"); // In TS we don't alias group by yet natively
|
| 499 |
+
return this;
|
| 500 |
+
}
|
| 501 |
+
groupByCustomerOrder(): this {
|
| 502 |
+
this.query.groupBy("customerOrder");
|
| 503 |
+
return this;
|
| 504 |
+
}
|
| 505 |
+
|
| 506 |
+
groupByCustomerOrderAs(retName: string): this {
|
| 507 |
+
this.query.groupBy("customerOrder"); // In TS we don't alias group by yet natively
|
| 508 |
+
return this;
|
| 509 |
+
}
|
| 510 |
+
groupByReferenceCode(): this {
|
| 511 |
+
this.query.groupBy("referenceCode");
|
| 512 |
+
return this;
|
| 513 |
+
}
|
| 514 |
+
|
| 515 |
+
groupByReferenceCodeAs(retName: string): this {
|
| 516 |
+
this.query.groupBy("referenceCode"); // In TS we don't alias group by yet natively
|
| 517 |
+
return this;
|
| 518 |
+
}
|
| 519 |
+
groupByVersion(): this {
|
| 520 |
+
this.query.groupBy("version");
|
| 521 |
+
return this;
|
| 522 |
+
}
|
| 523 |
+
|
| 524 |
+
groupByVersionAs(retName: string): this {
|
| 525 |
+
this.query.groupBy("version"); // In TS we don't alias group by yet natively
|
| 526 |
+
return this;
|
| 527 |
+
}
|
| 528 |
+
|
| 529 |
+
// --- Facets ---
|
| 530 |
+
facetByCustomerOrderAs(
|
| 531 |
+
facetName: string,
|
| 532 |
+
request: { toQuery(): SelectQuery },
|
| 533 |
+
includeAllFacets = true,
|
| 534 |
+
): this {
|
| 535 |
+
this.query.facetBy(facetName, "customerOrder", request, includeAllFacets,
|
| 536 |
+
{ kind: "facet", method: "facetByCustomerOrderAs", relation: "customerOrder", alias: facetName });
|
| 537 |
+
return this;
|
| 538 |
+
}
|
| 539 |
+
|
| 540 |
+
|
| 541 |
+
private async executeForListInternal(context: UserContext): Promise<SmartList<Payment>> {
|
| 542 |
+
this.ensureIntent();
|
| 543 |
+
if (this._pageCountAlias !== undefined) return this.executeCountedListInternal(context);
|
| 544 |
+
if (this.filters.length > 0) {
|
| 545 |
+
this.query.filter({ "$and": this.filters });
|
| 546 |
+
}
|
| 547 |
+
|
| 548 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 549 |
+
const rows = await service.executeQuery(context.prepareQuery(this.query));
|
| 550 |
+
const aggregateOnly = this.query.aggregateItems.length > 0 && this.query.groupByItems.length === 0;
|
| 551 |
+
const data = aggregateOnly ? [] : rows.map((row: unknown) =>
|
| 552 |
+
row instanceof Payment
|
| 553 |
+
? row
|
| 554 |
+
: Payment.fromRecord(row as Record<string, unknown>, new EntityRoot()));
|
| 555 |
+
const result = new SmartList<Payment>(data);
|
| 556 |
+
if (aggregateOnly && rows[0]) Object.assign(result.aggregations, rows[0]);
|
| 557 |
+
|
| 558 |
+
if (this.query.facets.length > 0) {
|
| 559 |
+
result.facets = await executeRelationFacets(
|
| 560 |
+
service, (query: any) => context.prepareQuery(query), this.query, this.query.facets);
|
| 561 |
+
}
|
| 562 |
+
|
| 563 |
+
return result;
|
| 564 |
+
}
|
| 565 |
+
|
| 566 |
+
private async executeForRowsInternal(context: UserContext): Promise<SmartList<Record<string, unknown>>> {
|
| 567 |
+
this.ensureIntent();
|
| 568 |
+
if (this.filters.length > 0) this.query.filter({ "$and": this.filters });
|
| 569 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 570 |
+
return new SmartList<Record<string, unknown>>(
|
| 571 |
+
await service.executeQuery(context.prepareQuery(this.query)) as Record<string, unknown>[]);
|
| 572 |
+
}
|
| 573 |
+
|
| 574 |
+
private async executeCountedListInternal(
|
| 575 |
+
context: UserContext,
|
| 576 |
+
): Promise<SmartList<Payment>> {
|
| 577 |
+
this.ensureIntent();
|
| 578 |
+
if (this.filters.length > 0) this.query.filter({ "$and": this.filters });
|
| 579 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 580 |
+
const preparedQuery = context.prepareQuery(this.query);
|
| 581 |
+
const useIdSet = preparedQuery.localIdSetPaginationOptions() !== undefined;
|
| 582 |
+
const countOperation = { kind: "named-count" as const,
|
| 583 |
+
method: this._pageCountMethod ?? "count",
|
| 584 |
+
...(this._pageCountMethod === "countAs" ? { alias: this._pageCountAlias } : {}) };
|
| 585 |
+
const totalCountBeforeRows = useIdSet ? undefined : await service.executeCount(
|
| 586 |
+
preparedQuery, this._pageCountAlias, countOperation);
|
| 587 |
+
const pageQuery = preparedQuery.clone();
|
| 588 |
+
// A page count describes the full filtered set, not an aggregate-only page row.
|
| 589 |
+
pageQuery.aggregateItems = pageQuery.aggregateItems.filter(item =>
|
| 590 |
+
!(String(item.function).toLowerCase() === "count" && item.alias === this._pageCountAlias));
|
| 591 |
+
const rows = await service.executeQuery(pageQuery);
|
| 592 |
+
const totalCount = useIdSet && context.idSetPaginationCountAccuracy === "EXACT"
|
| 593 |
+
? context.idSetPaginationCount!
|
| 594 |
+
: (totalCountBeforeRows ?? await service.executeCount(preparedQuery, this._pageCountAlias, countOperation));
|
| 595 |
+
const data = new SmartList(rows.map((row: unknown) =>
|
| 596 |
+
row instanceof Payment
|
| 597 |
+
? row
|
| 598 |
+
: Payment.fromRecord(row as Record<string, unknown>, new EntityRoot())));
|
| 599 |
+
data.totalCount = totalCount;
|
| 600 |
+
if (this._pageCountAlias !== undefined) data.aggregations[this._pageCountAlias] = totalCount;
|
| 601 |
+
if (this.query.facets.length > 0) {
|
| 602 |
+
data.facets = await executeRelationFacets(
|
| 603 |
+
service, (query: any) => context.prepareQuery(query), preparedQuery, preparedQuery.facets);
|
| 604 |
+
}
|
| 605 |
+
return data;
|
| 606 |
+
}
|
| 607 |
+
|
| 608 |
+
private executeForStreamInternal(context: UserContext, chunkSize: number): AsyncIterable<Payment> {
|
| 609 |
+
this.ensureIntent();
|
| 610 |
+
if (this.filters.length > 0) this.query.filter({ "$and": this.filters });
|
| 611 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 612 |
+
const preparedQuery = context.prepareQuery(this.query);
|
| 613 |
+
// Prepare Context and capture the runtime request before returning a lazy iterator.
|
| 614 |
+
const chunks = service.executeForStream(preparedQuery, chunkSize);
|
| 615 |
+
return (async function* () {
|
| 616 |
+
for await (const chunk of chunks) {
|
| 617 |
+
for (const entity of chunk) {
|
| 618 |
+
yield entity instanceof Payment
|
| 619 |
+
? entity
|
| 620 |
+
: Payment.fromRecord(entity as Record<string, unknown>, new EntityRoot());
|
| 621 |
+
}
|
| 622 |
+
}
|
| 623 |
+
})();
|
| 624 |
+
}
|
| 625 |
+
|
| 626 |
+
private ensureIntent(): void {
|
| 627 |
+
// Runtime owns validation, Unicode whitespace rules and typed diagnostics.
|
| 628 |
+
new QueryIntent(this._comment, this._purpose);
|
| 629 |
+
}
|
| 630 |
+
|
| 631 |
+
}
|
| 632 |
+
|
| 633 |
+
export class ExecutablePaymentRequest {
|
| 634 |
+
constructor(
|
| 635 |
+
private readonly execute: (context: UserContext) => Promise<SmartList<Payment>>,
|
| 636 |
+
private readonly executeRows: (context: UserContext) => Promise<SmartList<Record<string, unknown>>>,
|
| 637 |
+
private readonly stream: (context: UserContext, chunkSize: number) => AsyncIterable<Payment>,
|
| 638 |
+
private readonly limitOne: () => void,
|
| 639 |
+
private readonly addComment: (comment: string) => void,
|
| 640 |
+
private readonly ensureIntent: () => void,
|
| 641 |
+
) {}
|
| 642 |
+
|
| 643 |
+
comment(c: string): this {
|
| 644 |
+
this.addComment(c);
|
| 645 |
+
return this;
|
| 646 |
+
}
|
| 647 |
+
|
| 648 |
+
newEntity(context: UserContext): Payment {
|
| 649 |
+
this.ensureIntent();
|
| 650 |
+
return new Payment();
|
| 651 |
+
}
|
| 652 |
+
|
| 653 |
+
executeForList(context: UserContext): Promise<SmartList<Payment>> {
|
| 654 |
+
this.ensureIntent();
|
| 655 |
+
return this.execute(context);
|
| 656 |
+
}
|
| 657 |
+
|
| 658 |
+
executeForRows(context: UserContext): Promise<SmartList<Record<string, unknown>>> {
|
| 659 |
+
this.ensureIntent();
|
| 660 |
+
return this.executeRows(context);
|
| 661 |
+
}
|
| 662 |
+
|
| 663 |
+
executeForStream(context: UserContext, chunkSize = 1000): AsyncIterable<Payment> {
|
| 664 |
+
this.ensureIntent();
|
| 665 |
+
return this.stream(context, chunkSize);
|
| 666 |
+
}
|
| 667 |
+
|
| 668 |
+
async executeForOne(context: UserContext): Promise<Payment | undefined> {
|
| 669 |
+
this.limitOne();
|
| 670 |
+
return (await this.executeForList(context))[0];
|
| 671 |
+
}
|
| 672 |
+
}
|
source/teaql-ts/examples/trace-chain/lib/src/generated/requests/PlatformRequest.ts
ADDED
|
@@ -0,0 +1,607 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { EntityRoot, SelectQuery, SmartList, TeaQLDataService, UserContext, executeRelationFacets } from '../../teaql-ts';
|
| 2 |
+
import { Platform } from '../models/Platform';
|
| 3 |
+
import { mergeGeneratedScalarSearch, DynamicSearchWarning, QueryIntent } from 'teaql-ts';
|
| 4 |
+
import { GENERATED_SEARCH_MODELS } from '../../generated-search-models';
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
export class PlatformRequest {
|
| 9 |
+
private query: SelectQuery;
|
| 10 |
+
private filters: any[] = [];
|
| 11 |
+
private _purpose: string | undefined;
|
| 12 |
+
private _comment: string | undefined;
|
| 13 |
+
private _pageCountAlias: string | undefined;
|
| 14 |
+
private _pageCountMethod: "count" | "countAs" | undefined;
|
| 15 |
+
private _dynamicSearchWarnings: DynamicSearchWarning[] = [];
|
| 16 |
+
|
| 17 |
+
constructor(minimal = false) {
|
| 18 |
+
this.query = new SelectQuery("Platform");
|
| 19 |
+
this.filters.push({ version: { "$gte": 1 } });
|
| 20 |
+
if (minimal) {
|
| 21 |
+
this.selectId();
|
| 22 |
+
this.selectVersion();
|
| 23 |
+
}
|
| 24 |
+
else this.selectSelfFields();
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
comment(c: string): this {
|
| 28 |
+
this.query.comment(c);
|
| 29 |
+
this._comment = c;
|
| 30 |
+
return this;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
filterByJson(source: unknown, warn?: (warning: DynamicSearchWarning) => void): this {
|
| 34 |
+
const base = this.query.clone();
|
| 35 |
+
if (this.filters.length > 0) base.filter({ "$and": this.filters });
|
| 36 |
+
const merged = mergeGeneratedScalarSearch(base, source, GENERATED_SEARCH_MODELS, warn);
|
| 37 |
+
this.query = merged.query as SelectQuery;
|
| 38 |
+
this.filters = this.query.filterCondition ? [this.query.filterCondition] : [];
|
| 39 |
+
this._dynamicSearchWarnings.push(...merged.warnings);
|
| 40 |
+
return this;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
get dynamicSearchWarnings(): readonly DynamicSearchWarning[] {
|
| 44 |
+
return this._dynamicSearchWarnings.map(warning => ({ ...warning }));
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
purpose(p: string): ExecutablePlatformRequest {
|
| 48 |
+
this.query.purpose(p);
|
| 49 |
+
this._purpose = p;
|
| 50 |
+
return new ExecutablePlatformRequest(
|
| 51 |
+
(context) => context.withQueryRequest(this.query, () => this.executeForListInternal(context)),
|
| 52 |
+
(context) => context.withQueryRequest(this.query, () => this.executeForRowsInternal(context)),
|
| 53 |
+
(context, chunkSize) => this.executeForStreamInternal(context, chunkSize),
|
| 54 |
+
() => this.limit(1),
|
| 55 |
+
(c) => this.comment(c),
|
| 56 |
+
() => this.ensureIntent());
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
optimizeForContinuousPageFetch(): this {
|
| 60 |
+
this.query.optimizeForContinuousPageFetch();
|
| 61 |
+
return this;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
optimizeForContinuousPageFetchWith(namespace: string, ttlSeconds: number): this {
|
| 65 |
+
this.query.optimizeForContinuousPageFetchWith(namespace, ttlSeconds);
|
| 66 |
+
return this;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
optimizePaginationWithIdSet(): this {
|
| 70 |
+
this.query.optimizePaginationWithIdSet();
|
| 71 |
+
return this;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
optimizePaginationWithIdSetConfig(namespace: string, ttlSeconds: number, maxIds: number): this {
|
| 75 |
+
this.query.optimizePaginationWithIdSetConfig(namespace, ttlSeconds, maxIds);
|
| 76 |
+
return this;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
topNProbeParentThreshold(threshold: number): this {
|
| 80 |
+
this.query.topNProbeParentThreshold(threshold);
|
| 81 |
+
return this;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
limit(n: number): this {
|
| 85 |
+
this.query.limit(n);
|
| 86 |
+
return this;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
offset(n: number): this {
|
| 90 |
+
this.query.offset(n);
|
| 91 |
+
return this;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
toQuery(): SelectQuery {
|
| 95 |
+
if (this.filters.length > 0) {
|
| 96 |
+
this.query.filter({ "$and": this.filters });
|
| 97 |
+
}
|
| 98 |
+
return this.query;
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
withDeletedRows(): this {
|
| 102 |
+
this.filters = this.filters.filter(filter => !("version" in filter));
|
| 103 |
+
return this;
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
deletedRowsOnly(): this {
|
| 107 |
+
this.withDeletedRows();
|
| 108 |
+
this.filters.push({ version: { "$lte": -1 } });
|
| 109 |
+
return this;
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
selectSelfFields(): this {
|
| 113 |
+
this.query.select(["id", "name", "version"]);
|
| 114 |
+
return this;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
selectId(): this {
|
| 118 |
+
this.query.select(["id"]);
|
| 119 |
+
return this;
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
selectName(): this {
|
| 123 |
+
this.query.select(["name"]);
|
| 124 |
+
return this;
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
selectVersion(): this {
|
| 128 |
+
this.query.select(["version"]);
|
| 129 |
+
return this;
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
selectCustomerOrderListWith(request: { toQuery(): SelectQuery }): this {
|
| 136 |
+
this.query.relationQuery(
|
| 137 |
+
"customerOrderList", request.toQuery(), "id", "platform", true,
|
| 138 |
+
{ kind: "relation-select", method: "selectCustomerOrderListWith", relation: "customerOrderList" });
|
| 139 |
+
return this;
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
haveCustomerOrders(): this {
|
| 143 |
+
return this.withCustomerOrderListMatching({
|
| 144 |
+
toQuery: () => new SelectQuery("CustomerOrder"),
|
| 145 |
+
});
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
haveNoCustomerOrders(): this {
|
| 149 |
+
return this.withoutCustomerOrderListMatching({
|
| 150 |
+
toQuery: () => new SelectQuery("CustomerOrder"),
|
| 151 |
+
});
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
withCustomerOrderListMatching(request: { toQuery(): SelectQuery }): this {
|
| 155 |
+
this.filters.push({
|
| 156 |
+
"id": {
|
| 157 |
+
"$inSubquery": {
|
| 158 |
+
query: request.toQuery(), field: "platform",
|
| 159 |
+
},
|
| 160 |
+
},
|
| 161 |
+
});
|
| 162 |
+
return this;
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
withoutCustomerOrderListMatching(request: { toQuery(): SelectQuery }): this {
|
| 166 |
+
this.filters.push({
|
| 167 |
+
"id": {
|
| 168 |
+
"$notInSubquery": {
|
| 169 |
+
query: request.toQuery(), field: "platform",
|
| 170 |
+
},
|
| 171 |
+
},
|
| 172 |
+
});
|
| 173 |
+
return this;
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
countCustomerOrders(): this {
|
| 177 |
+
return this.countCustomerOrdersAs("countCustomerOrders");
|
| 178 |
+
}
|
| 179 |
+
|
| 180 |
+
countCustomerOrdersAs(alias: string): this {
|
| 181 |
+
const query = new SelectQuery("CustomerOrder").filter({ version: { "$gte": 1 } });
|
| 182 |
+
this.countCustomerOrdersWith(alias, { toQuery: () => query });
|
| 183 |
+
this.query.relationAggregates[this.query.relationAggregates.length - 1].operation = {
|
| 184 |
+
kind: "relation-count", method: "countCustomerOrdersAs", relation: "customerOrderList", alias };
|
| 185 |
+
return this;
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
countCustomerOrdersWith(alias: string, child: { toQuery(): SelectQuery }): this {
|
| 189 |
+
const query = child.toQuery().clone();
|
| 190 |
+
query.aggregateItems = [];
|
| 191 |
+
query.aggregate("Count", "id", alias);
|
| 192 |
+
this.query.relationAggregate("customerOrderList", alias, query, true,
|
| 193 |
+
{ kind: "relation-count", method: "countCustomerOrdersWith", relation: "customerOrderList", alias });
|
| 194 |
+
return this;
|
| 195 |
+
}
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
|
| 199 |
+
withIdIs(val: any): this {
|
| 200 |
+
this.filters.push({ "id": { "$eq": val } });
|
| 201 |
+
return this;
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
withIdIsNot(val: any): this {
|
| 205 |
+
this.filters.push({ "id": { "$ne": val } });
|
| 206 |
+
return this;
|
| 207 |
+
}
|
| 208 |
+
|
| 209 |
+
withIdIn(...vals: any[]): this {
|
| 210 |
+
this.filters.push({ "id": { "$in": vals } });
|
| 211 |
+
return this;
|
| 212 |
+
}
|
| 213 |
+
|
| 214 |
+
withIdNotIn(...vals: any[]): this {
|
| 215 |
+
this.filters.push({ "id": { "$notIn": vals } });
|
| 216 |
+
return this;
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
withIdGreaterThan(val: any): this {
|
| 220 |
+
this.filters.push({ "id": { "$gt": val } });
|
| 221 |
+
return this;
|
| 222 |
+
}
|
| 223 |
+
|
| 224 |
+
withIdGreaterThanOrEqualTo(val: any): this {
|
| 225 |
+
this.filters.push({ "id": { "$gte": val } });
|
| 226 |
+
return this;
|
| 227 |
+
}
|
| 228 |
+
|
| 229 |
+
withIdLessThan(val: any): this {
|
| 230 |
+
this.filters.push({ "id": { "$lt": val } });
|
| 231 |
+
return this;
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
withIdLessThanOrEqualTo(val: any): this {
|
| 235 |
+
this.filters.push({ "id": { "$lte": val } });
|
| 236 |
+
return this;
|
| 237 |
+
}
|
| 238 |
+
|
| 239 |
+
withIdBetween(lower: any, upper: any): this {
|
| 240 |
+
this.filters.push({ "id": { "$between": [lower, upper] } });
|
| 241 |
+
return this;
|
| 242 |
+
}
|
| 243 |
+
|
| 244 |
+
withIdIsKnown(): this {
|
| 245 |
+
this.filters.push({ "id": { "$isNull": false } });
|
| 246 |
+
return this;
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
withIdIsUnknown(): this {
|
| 250 |
+
this.filters.push({ "id": { "$isNull": true } });
|
| 251 |
+
return this;
|
| 252 |
+
}
|
| 253 |
+
|
| 254 |
+
withNameContaining(val: string): this {
|
| 255 |
+
this.filters.push({ "name": { "$contains": val } });
|
| 256 |
+
return this;
|
| 257 |
+
}
|
| 258 |
+
|
| 259 |
+
withNameIs(val: string): this {
|
| 260 |
+
this.filters.push({ "name": { "$eq": val } });
|
| 261 |
+
return this;
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
withNameIsNot(val: any): this {
|
| 265 |
+
this.filters.push({ "name": { "$ne": val } });
|
| 266 |
+
return this;
|
| 267 |
+
}
|
| 268 |
+
|
| 269 |
+
withNameIn(...vals: any[]): this {
|
| 270 |
+
this.filters.push({ "name": { "$in": vals } });
|
| 271 |
+
return this;
|
| 272 |
+
}
|
| 273 |
+
|
| 274 |
+
withNameNotIn(...vals: any[]): this {
|
| 275 |
+
this.filters.push({ "name": { "$notIn": vals } });
|
| 276 |
+
return this;
|
| 277 |
+
}
|
| 278 |
+
|
| 279 |
+
withNameGreaterThan(val: any): this {
|
| 280 |
+
this.filters.push({ "name": { "$gt": val } });
|
| 281 |
+
return this;
|
| 282 |
+
}
|
| 283 |
+
|
| 284 |
+
withNameGreaterThanOrEqualTo(val: any): this {
|
| 285 |
+
this.filters.push({ "name": { "$gte": val } });
|
| 286 |
+
return this;
|
| 287 |
+
}
|
| 288 |
+
|
| 289 |
+
withNameLessThan(val: any): this {
|
| 290 |
+
this.filters.push({ "name": { "$lt": val } });
|
| 291 |
+
return this;
|
| 292 |
+
}
|
| 293 |
+
|
| 294 |
+
withNameLessThanOrEqualTo(val: any): this {
|
| 295 |
+
this.filters.push({ "name": { "$lte": val } });
|
| 296 |
+
return this;
|
| 297 |
+
}
|
| 298 |
+
|
| 299 |
+
withNameBetween(lower: any, upper: any): this {
|
| 300 |
+
this.filters.push({ "name": { "$between": [lower, upper] } });
|
| 301 |
+
return this;
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
withNameIsKnown(): this {
|
| 305 |
+
this.filters.push({ "name": { "$isNull": false } });
|
| 306 |
+
return this;
|
| 307 |
+
}
|
| 308 |
+
|
| 309 |
+
withNameIsUnknown(): this {
|
| 310 |
+
this.filters.push({ "name": { "$isNull": true } });
|
| 311 |
+
return this;
|
| 312 |
+
}
|
| 313 |
+
withNameNotContaining(val: string): this {
|
| 314 |
+
this.filters.push({ "name": { "$notContains": val } });
|
| 315 |
+
return this;
|
| 316 |
+
}
|
| 317 |
+
|
| 318 |
+
withNameStartingWith(val: string): this {
|
| 319 |
+
this.filters.push({ "name": { "$startsWith": val } });
|
| 320 |
+
return this;
|
| 321 |
+
}
|
| 322 |
+
|
| 323 |
+
withNameNotStartingWith(val: string): this {
|
| 324 |
+
this.filters.push({ "name": { "$notStartsWith": val } });
|
| 325 |
+
return this;
|
| 326 |
+
}
|
| 327 |
+
|
| 328 |
+
withNameEndingWith(val: string): this {
|
| 329 |
+
this.filters.push({ "name": { "$endsWith": val } });
|
| 330 |
+
return this;
|
| 331 |
+
}
|
| 332 |
+
|
| 333 |
+
withNameNotEndingWith(val: string): this {
|
| 334 |
+
this.filters.push({ "name": { "$notEndsWith": val } });
|
| 335 |
+
return this;
|
| 336 |
+
}
|
| 337 |
+
|
| 338 |
+
withNameSoundingLike(val: string): this {
|
| 339 |
+
this.filters.push({ "name": { "$soundLike": val } });
|
| 340 |
+
return this;
|
| 341 |
+
}
|
| 342 |
+
|
| 343 |
+
withVersionIs(val: any): this {
|
| 344 |
+
this.filters.push({ "version": { "$eq": val } });
|
| 345 |
+
return this;
|
| 346 |
+
}
|
| 347 |
+
|
| 348 |
+
withVersionIsNot(val: any): this {
|
| 349 |
+
this.filters.push({ "version": { "$ne": val } });
|
| 350 |
+
return this;
|
| 351 |
+
}
|
| 352 |
+
|
| 353 |
+
withVersionIn(...vals: any[]): this {
|
| 354 |
+
this.filters.push({ "version": { "$in": vals } });
|
| 355 |
+
return this;
|
| 356 |
+
}
|
| 357 |
+
|
| 358 |
+
withVersionNotIn(...vals: any[]): this {
|
| 359 |
+
this.filters.push({ "version": { "$notIn": vals } });
|
| 360 |
+
return this;
|
| 361 |
+
}
|
| 362 |
+
|
| 363 |
+
withVersionGreaterThan(val: any): this {
|
| 364 |
+
this.filters.push({ "version": { "$gt": val } });
|
| 365 |
+
return this;
|
| 366 |
+
}
|
| 367 |
+
|
| 368 |
+
withVersionGreaterThanOrEqualTo(val: any): this {
|
| 369 |
+
this.filters.push({ "version": { "$gte": val } });
|
| 370 |
+
return this;
|
| 371 |
+
}
|
| 372 |
+
|
| 373 |
+
withVersionLessThan(val: any): this {
|
| 374 |
+
this.filters.push({ "version": { "$lt": val } });
|
| 375 |
+
return this;
|
| 376 |
+
}
|
| 377 |
+
|
| 378 |
+
withVersionLessThanOrEqualTo(val: any): this {
|
| 379 |
+
this.filters.push({ "version": { "$lte": val } });
|
| 380 |
+
return this;
|
| 381 |
+
}
|
| 382 |
+
|
| 383 |
+
withVersionBetween(lower: any, upper: any): this {
|
| 384 |
+
this.filters.push({ "version": { "$between": [lower, upper] } });
|
| 385 |
+
return this;
|
| 386 |
+
}
|
| 387 |
+
|
| 388 |
+
withVersionIsKnown(): this {
|
| 389 |
+
this.filters.push({ "version": { "$isNull": false } });
|
| 390 |
+
return this;
|
| 391 |
+
}
|
| 392 |
+
|
| 393 |
+
withVersionIsUnknown(): this {
|
| 394 |
+
this.filters.push({ "version": { "$isNull": true } });
|
| 395 |
+
return this;
|
| 396 |
+
}
|
| 397 |
+
|
| 398 |
+
orderByIdAscending(): this {
|
| 399 |
+
this.query.orderBy("id", "asc");
|
| 400 |
+
return this;
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
orderByIdDescending(): this {
|
| 404 |
+
this.query.orderBy("id", "desc");
|
| 405 |
+
return this;
|
| 406 |
+
}
|
| 407 |
+
|
| 408 |
+
orderByNameAscending(): this {
|
| 409 |
+
this.query.orderBy("name", "asc");
|
| 410 |
+
return this;
|
| 411 |
+
}
|
| 412 |
+
|
| 413 |
+
orderByNameDescending(): this {
|
| 414 |
+
this.query.orderBy("name", "desc");
|
| 415 |
+
return this;
|
| 416 |
+
}
|
| 417 |
+
|
| 418 |
+
orderByVersionAscending(): this {
|
| 419 |
+
this.query.orderBy("version", "asc");
|
| 420 |
+
return this;
|
| 421 |
+
}
|
| 422 |
+
|
| 423 |
+
orderByVersionDescending(): this {
|
| 424 |
+
this.query.orderBy("version", "desc");
|
| 425 |
+
return this;
|
| 426 |
+
}
|
| 427 |
+
|
| 428 |
+
|
| 429 |
+
// --- Aggregations ---
|
| 430 |
+
count(): this {
|
| 431 |
+
this.query.aggregate("Count", "id", "count");
|
| 432 |
+
this._pageCountAlias = "count";
|
| 433 |
+
this._pageCountMethod = "count";
|
| 434 |
+
return this;
|
| 435 |
+
}
|
| 436 |
+
|
| 437 |
+
countAs(retName: string): this {
|
| 438 |
+
this.query.aggregate("Count", "id", retName);
|
| 439 |
+
this._pageCountAlias = retName;
|
| 440 |
+
this._pageCountMethod = "countAs";
|
| 441 |
+
return this;
|
| 442 |
+
}
|
| 443 |
+
|
| 444 |
+
|
| 445 |
+
// --- Group By ---
|
| 446 |
+
groupById(): this {
|
| 447 |
+
this.query.groupBy("id");
|
| 448 |
+
return this;
|
| 449 |
+
}
|
| 450 |
+
|
| 451 |
+
groupByIdAs(retName: string): this {
|
| 452 |
+
this.query.groupBy("id"); // In TS we don't alias group by yet natively
|
| 453 |
+
return this;
|
| 454 |
+
}
|
| 455 |
+
groupByName(): this {
|
| 456 |
+
this.query.groupBy("name");
|
| 457 |
+
return this;
|
| 458 |
+
}
|
| 459 |
+
|
| 460 |
+
groupByNameAs(retName: string): this {
|
| 461 |
+
this.query.groupBy("name"); // In TS we don't alias group by yet natively
|
| 462 |
+
return this;
|
| 463 |
+
}
|
| 464 |
+
groupByVersion(): this {
|
| 465 |
+
this.query.groupBy("version");
|
| 466 |
+
return this;
|
| 467 |
+
}
|
| 468 |
+
|
| 469 |
+
groupByVersionAs(retName: string): this {
|
| 470 |
+
this.query.groupBy("version"); // In TS we don't alias group by yet natively
|
| 471 |
+
return this;
|
| 472 |
+
}
|
| 473 |
+
|
| 474 |
+
// --- Facets ---
|
| 475 |
+
|
| 476 |
+
private async executeForListInternal(context: UserContext): Promise<SmartList<Platform>> {
|
| 477 |
+
this.ensureIntent();
|
| 478 |
+
if (this._pageCountAlias !== undefined) return this.executeCountedListInternal(context);
|
| 479 |
+
if (this.filters.length > 0) {
|
| 480 |
+
this.query.filter({ "$and": this.filters });
|
| 481 |
+
}
|
| 482 |
+
|
| 483 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 484 |
+
const rows = await service.executeQuery(context.prepareQuery(this.query));
|
| 485 |
+
const aggregateOnly = this.query.aggregateItems.length > 0 && this.query.groupByItems.length === 0;
|
| 486 |
+
const data = aggregateOnly ? [] : rows.map((row: unknown) =>
|
| 487 |
+
row instanceof Platform
|
| 488 |
+
? row
|
| 489 |
+
: Platform.fromRecord(row as Record<string, unknown>, new EntityRoot()));
|
| 490 |
+
const result = new SmartList<Platform>(data);
|
| 491 |
+
if (aggregateOnly && rows[0]) Object.assign(result.aggregations, rows[0]);
|
| 492 |
+
|
| 493 |
+
if (this.query.facets.length > 0) {
|
| 494 |
+
result.facets = await executeRelationFacets(
|
| 495 |
+
service, (query: any) => context.prepareQuery(query), this.query, this.query.facets);
|
| 496 |
+
}
|
| 497 |
+
|
| 498 |
+
return result;
|
| 499 |
+
}
|
| 500 |
+
|
| 501 |
+
private async executeForRowsInternal(context: UserContext): Promise<SmartList<Record<string, unknown>>> {
|
| 502 |
+
this.ensureIntent();
|
| 503 |
+
if (this.filters.length > 0) this.query.filter({ "$and": this.filters });
|
| 504 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 505 |
+
return new SmartList<Record<string, unknown>>(
|
| 506 |
+
await service.executeQuery(context.prepareQuery(this.query)) as Record<string, unknown>[]);
|
| 507 |
+
}
|
| 508 |
+
|
| 509 |
+
private async executeCountedListInternal(
|
| 510 |
+
context: UserContext,
|
| 511 |
+
): Promise<SmartList<Platform>> {
|
| 512 |
+
this.ensureIntent();
|
| 513 |
+
if (this.filters.length > 0) this.query.filter({ "$and": this.filters });
|
| 514 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 515 |
+
const preparedQuery = context.prepareQuery(this.query);
|
| 516 |
+
const useIdSet = preparedQuery.localIdSetPaginationOptions() !== undefined;
|
| 517 |
+
const countOperation = { kind: "named-count" as const,
|
| 518 |
+
method: this._pageCountMethod ?? "count",
|
| 519 |
+
...(this._pageCountMethod === "countAs" ? { alias: this._pageCountAlias } : {}) };
|
| 520 |
+
const totalCountBeforeRows = useIdSet ? undefined : await service.executeCount(
|
| 521 |
+
preparedQuery, this._pageCountAlias, countOperation);
|
| 522 |
+
const pageQuery = preparedQuery.clone();
|
| 523 |
+
// A page count describes the full filtered set, not an aggregate-only page row.
|
| 524 |
+
pageQuery.aggregateItems = pageQuery.aggregateItems.filter(item =>
|
| 525 |
+
!(String(item.function).toLowerCase() === "count" && item.alias === this._pageCountAlias));
|
| 526 |
+
const rows = await service.executeQuery(pageQuery);
|
| 527 |
+
const totalCount = useIdSet && context.idSetPaginationCountAccuracy === "EXACT"
|
| 528 |
+
? context.idSetPaginationCount!
|
| 529 |
+
: (totalCountBeforeRows ?? await service.executeCount(preparedQuery, this._pageCountAlias, countOperation));
|
| 530 |
+
const data = new SmartList(rows.map((row: unknown) =>
|
| 531 |
+
row instanceof Platform
|
| 532 |
+
? row
|
| 533 |
+
: Platform.fromRecord(row as Record<string, unknown>, new EntityRoot())));
|
| 534 |
+
data.totalCount = totalCount;
|
| 535 |
+
if (this._pageCountAlias !== undefined) data.aggregations[this._pageCountAlias] = totalCount;
|
| 536 |
+
if (this.query.facets.length > 0) {
|
| 537 |
+
data.facets = await executeRelationFacets(
|
| 538 |
+
service, (query: any) => context.prepareQuery(query), preparedQuery, preparedQuery.facets);
|
| 539 |
+
}
|
| 540 |
+
return data;
|
| 541 |
+
}
|
| 542 |
+
|
| 543 |
+
private executeForStreamInternal(context: UserContext, chunkSize: number): AsyncIterable<Platform> {
|
| 544 |
+
this.ensureIntent();
|
| 545 |
+
if (this.filters.length > 0) this.query.filter({ "$and": this.filters });
|
| 546 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 547 |
+
const preparedQuery = context.prepareQuery(this.query);
|
| 548 |
+
// Prepare Context and capture the runtime request before returning a lazy iterator.
|
| 549 |
+
const chunks = service.executeForStream(preparedQuery, chunkSize);
|
| 550 |
+
return (async function* () {
|
| 551 |
+
for await (const chunk of chunks) {
|
| 552 |
+
for (const entity of chunk) {
|
| 553 |
+
yield entity instanceof Platform
|
| 554 |
+
? entity
|
| 555 |
+
: Platform.fromRecord(entity as Record<string, unknown>, new EntityRoot());
|
| 556 |
+
}
|
| 557 |
+
}
|
| 558 |
+
})();
|
| 559 |
+
}
|
| 560 |
+
|
| 561 |
+
private ensureIntent(): void {
|
| 562 |
+
// Runtime owns validation, Unicode whitespace rules and typed diagnostics.
|
| 563 |
+
new QueryIntent(this._comment, this._purpose);
|
| 564 |
+
}
|
| 565 |
+
|
| 566 |
+
}
|
| 567 |
+
|
| 568 |
+
export class ExecutablePlatformRequest {
|
| 569 |
+
constructor(
|
| 570 |
+
private readonly execute: (context: UserContext) => Promise<SmartList<Platform>>,
|
| 571 |
+
private readonly executeRows: (context: UserContext) => Promise<SmartList<Record<string, unknown>>>,
|
| 572 |
+
private readonly stream: (context: UserContext, chunkSize: number) => AsyncIterable<Platform>,
|
| 573 |
+
private readonly limitOne: () => void,
|
| 574 |
+
private readonly addComment: (comment: string) => void,
|
| 575 |
+
private readonly ensureIntent: () => void,
|
| 576 |
+
) {}
|
| 577 |
+
|
| 578 |
+
comment(c: string): this {
|
| 579 |
+
this.addComment(c);
|
| 580 |
+
return this;
|
| 581 |
+
}
|
| 582 |
+
|
| 583 |
+
newEntity(context: UserContext): Platform {
|
| 584 |
+
this.ensureIntent();
|
| 585 |
+
return new Platform();
|
| 586 |
+
}
|
| 587 |
+
|
| 588 |
+
executeForList(context: UserContext): Promise<SmartList<Platform>> {
|
| 589 |
+
this.ensureIntent();
|
| 590 |
+
return this.execute(context);
|
| 591 |
+
}
|
| 592 |
+
|
| 593 |
+
executeForRows(context: UserContext): Promise<SmartList<Record<string, unknown>>> {
|
| 594 |
+
this.ensureIntent();
|
| 595 |
+
return this.executeRows(context);
|
| 596 |
+
}
|
| 597 |
+
|
| 598 |
+
executeForStream(context: UserContext, chunkSize = 1000): AsyncIterable<Platform> {
|
| 599 |
+
this.ensureIntent();
|
| 600 |
+
return this.stream(context, chunkSize);
|
| 601 |
+
}
|
| 602 |
+
|
| 603 |
+
async executeForOne(context: UserContext): Promise<Platform | undefined> {
|
| 604 |
+
this.limitOne();
|
| 605 |
+
return (await this.executeForList(context))[0];
|
| 606 |
+
}
|
| 607 |
+
}
|
source/teaql-ts/examples/trace-chain/lib/src/generated/requests/ShipmentRequest.ts
ADDED
|
@@ -0,0 +1,611 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { EntityRoot, SelectQuery, SmartList, TeaQLDataService, UserContext, executeRelationFacets } from '../../teaql-ts';
|
| 2 |
+
import { Shipment } from '../models/Shipment';
|
| 3 |
+
import { mergeGeneratedScalarSearch, DynamicSearchWarning, QueryIntent } from 'teaql-ts';
|
| 4 |
+
import { GENERATED_SEARCH_MODELS } from '../../generated-search-models';
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
export class ShipmentRequest {
|
| 9 |
+
private query: SelectQuery;
|
| 10 |
+
private filters: any[] = [];
|
| 11 |
+
private _purpose: string | undefined;
|
| 12 |
+
private _comment: string | undefined;
|
| 13 |
+
private _pageCountAlias: string | undefined;
|
| 14 |
+
private _pageCountMethod: "count" | "countAs" | undefined;
|
| 15 |
+
private _dynamicSearchWarnings: DynamicSearchWarning[] = [];
|
| 16 |
+
|
| 17 |
+
constructor(minimal = false) {
|
| 18 |
+
this.query = new SelectQuery("Shipment");
|
| 19 |
+
this.filters.push({ version: { "$gte": 1 } });
|
| 20 |
+
if (minimal) {
|
| 21 |
+
this.selectId();
|
| 22 |
+
this.selectVersion();
|
| 23 |
+
}
|
| 24 |
+
else this.selectSelfFields();
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
comment(c: string): this {
|
| 28 |
+
this.query.comment(c);
|
| 29 |
+
this._comment = c;
|
| 30 |
+
return this;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
filterByJson(source: unknown, warn?: (warning: DynamicSearchWarning) => void): this {
|
| 34 |
+
const base = this.query.clone();
|
| 35 |
+
if (this.filters.length > 0) base.filter({ "$and": this.filters });
|
| 36 |
+
const merged = mergeGeneratedScalarSearch(base, source, GENERATED_SEARCH_MODELS, warn);
|
| 37 |
+
this.query = merged.query as SelectQuery;
|
| 38 |
+
this.filters = this.query.filterCondition ? [this.query.filterCondition] : [];
|
| 39 |
+
this._dynamicSearchWarnings.push(...merged.warnings);
|
| 40 |
+
return this;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
get dynamicSearchWarnings(): readonly DynamicSearchWarning[] {
|
| 44 |
+
return this._dynamicSearchWarnings.map(warning => ({ ...warning }));
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
purpose(p: string): ExecutableShipmentRequest {
|
| 48 |
+
this.query.purpose(p);
|
| 49 |
+
this._purpose = p;
|
| 50 |
+
return new ExecutableShipmentRequest(
|
| 51 |
+
(context) => context.withQueryRequest(this.query, () => this.executeForListInternal(context)),
|
| 52 |
+
(context) => context.withQueryRequest(this.query, () => this.executeForRowsInternal(context)),
|
| 53 |
+
(context, chunkSize) => this.executeForStreamInternal(context, chunkSize),
|
| 54 |
+
() => this.limit(1),
|
| 55 |
+
(c) => this.comment(c),
|
| 56 |
+
() => this.ensureIntent());
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
optimizeForContinuousPageFetch(): this {
|
| 60 |
+
this.query.optimizeForContinuousPageFetch();
|
| 61 |
+
return this;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
optimizeForContinuousPageFetchWith(namespace: string, ttlSeconds: number): this {
|
| 65 |
+
this.query.optimizeForContinuousPageFetchWith(namespace, ttlSeconds);
|
| 66 |
+
return this;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
optimizePaginationWithIdSet(): this {
|
| 70 |
+
this.query.optimizePaginationWithIdSet();
|
| 71 |
+
return this;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
optimizePaginationWithIdSetConfig(namespace: string, ttlSeconds: number, maxIds: number): this {
|
| 75 |
+
this.query.optimizePaginationWithIdSetConfig(namespace, ttlSeconds, maxIds);
|
| 76 |
+
return this;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
topNProbeParentThreshold(threshold: number): this {
|
| 80 |
+
this.query.topNProbeParentThreshold(threshold);
|
| 81 |
+
return this;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
limit(n: number): this {
|
| 85 |
+
this.query.limit(n);
|
| 86 |
+
return this;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
offset(n: number): this {
|
| 90 |
+
this.query.offset(n);
|
| 91 |
+
return this;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
toQuery(): SelectQuery {
|
| 95 |
+
if (this.filters.length > 0) {
|
| 96 |
+
this.query.filter({ "$and": this.filters });
|
| 97 |
+
}
|
| 98 |
+
return this.query;
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
withDeletedRows(): this {
|
| 102 |
+
this.filters = this.filters.filter(filter => !("version" in filter));
|
| 103 |
+
return this;
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
deletedRowsOnly(): this {
|
| 107 |
+
this.withDeletedRows();
|
| 108 |
+
this.filters.push({ version: { "$lte": -1 } });
|
| 109 |
+
return this;
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
selectSelfFields(): this {
|
| 113 |
+
this.query.select(["id", "customerOrder", "referenceCode", "version"]);
|
| 114 |
+
return this;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
selectId(): this {
|
| 118 |
+
this.query.select(["id"]);
|
| 119 |
+
return this;
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
selectReferenceCode(): this {
|
| 124 |
+
this.query.select(["referenceCode"]);
|
| 125 |
+
return this;
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
selectVersion(): this {
|
| 129 |
+
this.query.select(["version"]);
|
| 130 |
+
return this;
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
selectCustomerOrderWith(request: { toQuery(): SelectQuery }): this {
|
| 135 |
+
this.query.select(["customerOrder"]);
|
| 136 |
+
this.query.relationQuery(
|
| 137 |
+
"customerOrder", request.toQuery(), "customerOrder", "id", false,
|
| 138 |
+
{ kind: "relation-select", method: "selectCustomerOrderWith", relation: "customerOrder" });
|
| 139 |
+
return this;
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
withCustomerOrderMatching(request: { toQuery(): SelectQuery }): this {
|
| 143 |
+
this.filters.push({
|
| 144 |
+
"customerOrder": {
|
| 145 |
+
"$inSubquery": { query: request.toQuery(), field: "id" },
|
| 146 |
+
},
|
| 147 |
+
});
|
| 148 |
+
return this;
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
withoutCustomerOrderMatching(request: { toQuery(): SelectQuery }): this {
|
| 152 |
+
this.filters.push({
|
| 153 |
+
"customerOrder": {
|
| 154 |
+
"$notInSubquery": { query: request.toQuery(), field: "id" },
|
| 155 |
+
},
|
| 156 |
+
});
|
| 157 |
+
return this;
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
withIdIs(val: any): this {
|
| 164 |
+
this.filters.push({ "id": { "$eq": val } });
|
| 165 |
+
return this;
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
withIdIsNot(val: any): this {
|
| 169 |
+
this.filters.push({ "id": { "$ne": val } });
|
| 170 |
+
return this;
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
withIdIn(...vals: any[]): this {
|
| 174 |
+
this.filters.push({ "id": { "$in": vals } });
|
| 175 |
+
return this;
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
withIdNotIn(...vals: any[]): this {
|
| 179 |
+
this.filters.push({ "id": { "$notIn": vals } });
|
| 180 |
+
return this;
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
withIdGreaterThan(val: any): this {
|
| 184 |
+
this.filters.push({ "id": { "$gt": val } });
|
| 185 |
+
return this;
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
withIdGreaterThanOrEqualTo(val: any): this {
|
| 189 |
+
this.filters.push({ "id": { "$gte": val } });
|
| 190 |
+
return this;
|
| 191 |
+
}
|
| 192 |
+
|
| 193 |
+
withIdLessThan(val: any): this {
|
| 194 |
+
this.filters.push({ "id": { "$lt": val } });
|
| 195 |
+
return this;
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
withIdLessThanOrEqualTo(val: any): this {
|
| 199 |
+
this.filters.push({ "id": { "$lte": val } });
|
| 200 |
+
return this;
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
withIdBetween(lower: any, upper: any): this {
|
| 204 |
+
this.filters.push({ "id": { "$between": [lower, upper] } });
|
| 205 |
+
return this;
|
| 206 |
+
}
|
| 207 |
+
|
| 208 |
+
withIdIsKnown(): this {
|
| 209 |
+
this.filters.push({ "id": { "$isNull": false } });
|
| 210 |
+
return this;
|
| 211 |
+
}
|
| 212 |
+
|
| 213 |
+
withIdIsUnknown(): this {
|
| 214 |
+
this.filters.push({ "id": { "$isNull": true } });
|
| 215 |
+
return this;
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
filterByCustomerOrder(val: any): this {
|
| 219 |
+
this.filters.push({ "customerOrder": { "$eq": val } });
|
| 220 |
+
return this;
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
filterByCustomerOrderIn(...vals: any[]): this {
|
| 224 |
+
this.filters.push({ "customerOrder": { "$in": vals } });
|
| 225 |
+
return this;
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
+
withCustomerOrderIsKnown(): this {
|
| 229 |
+
this.filters.push({ "customerOrder": { "$isNull": false } });
|
| 230 |
+
return this;
|
| 231 |
+
}
|
| 232 |
+
|
| 233 |
+
withCustomerOrderIsUnknown(): this {
|
| 234 |
+
this.filters.push({ "customerOrder": { "$isNull": true } });
|
| 235 |
+
return this;
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
withReferenceCodeContaining(val: string): this {
|
| 239 |
+
this.filters.push({ "referenceCode": { "$contains": val } });
|
| 240 |
+
return this;
|
| 241 |
+
}
|
| 242 |
+
|
| 243 |
+
withReferenceCodeIs(val: string): this {
|
| 244 |
+
this.filters.push({ "referenceCode": { "$eq": val } });
|
| 245 |
+
return this;
|
| 246 |
+
}
|
| 247 |
+
|
| 248 |
+
withReferenceCodeIsNot(val: any): this {
|
| 249 |
+
this.filters.push({ "referenceCode": { "$ne": val } });
|
| 250 |
+
return this;
|
| 251 |
+
}
|
| 252 |
+
|
| 253 |
+
withReferenceCodeIn(...vals: any[]): this {
|
| 254 |
+
this.filters.push({ "referenceCode": { "$in": vals } });
|
| 255 |
+
return this;
|
| 256 |
+
}
|
| 257 |
+
|
| 258 |
+
withReferenceCodeNotIn(...vals: any[]): this {
|
| 259 |
+
this.filters.push({ "referenceCode": { "$notIn": vals } });
|
| 260 |
+
return this;
|
| 261 |
+
}
|
| 262 |
+
|
| 263 |
+
withReferenceCodeGreaterThan(val: any): this {
|
| 264 |
+
this.filters.push({ "referenceCode": { "$gt": val } });
|
| 265 |
+
return this;
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
withReferenceCodeGreaterThanOrEqualTo(val: any): this {
|
| 269 |
+
this.filters.push({ "referenceCode": { "$gte": val } });
|
| 270 |
+
return this;
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
withReferenceCodeLessThan(val: any): this {
|
| 274 |
+
this.filters.push({ "referenceCode": { "$lt": val } });
|
| 275 |
+
return this;
|
| 276 |
+
}
|
| 277 |
+
|
| 278 |
+
withReferenceCodeLessThanOrEqualTo(val: any): this {
|
| 279 |
+
this.filters.push({ "referenceCode": { "$lte": val } });
|
| 280 |
+
return this;
|
| 281 |
+
}
|
| 282 |
+
|
| 283 |
+
withReferenceCodeBetween(lower: any, upper: any): this {
|
| 284 |
+
this.filters.push({ "referenceCode": { "$between": [lower, upper] } });
|
| 285 |
+
return this;
|
| 286 |
+
}
|
| 287 |
+
|
| 288 |
+
withReferenceCodeIsKnown(): this {
|
| 289 |
+
this.filters.push({ "referenceCode": { "$isNull": false } });
|
| 290 |
+
return this;
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
withReferenceCodeIsUnknown(): this {
|
| 294 |
+
this.filters.push({ "referenceCode": { "$isNull": true } });
|
| 295 |
+
return this;
|
| 296 |
+
}
|
| 297 |
+
withReferenceCodeNotContaining(val: string): this {
|
| 298 |
+
this.filters.push({ "referenceCode": { "$notContains": val } });
|
| 299 |
+
return this;
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
withReferenceCodeStartingWith(val: string): this {
|
| 303 |
+
this.filters.push({ "referenceCode": { "$startsWith": val } });
|
| 304 |
+
return this;
|
| 305 |
+
}
|
| 306 |
+
|
| 307 |
+
withReferenceCodeNotStartingWith(val: string): this {
|
| 308 |
+
this.filters.push({ "referenceCode": { "$notStartsWith": val } });
|
| 309 |
+
return this;
|
| 310 |
+
}
|
| 311 |
+
|
| 312 |
+
withReferenceCodeEndingWith(val: string): this {
|
| 313 |
+
this.filters.push({ "referenceCode": { "$endsWith": val } });
|
| 314 |
+
return this;
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
withReferenceCodeNotEndingWith(val: string): this {
|
| 318 |
+
this.filters.push({ "referenceCode": { "$notEndsWith": val } });
|
| 319 |
+
return this;
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
withReferenceCodeSoundingLike(val: string): this {
|
| 323 |
+
this.filters.push({ "referenceCode": { "$soundLike": val } });
|
| 324 |
+
return this;
|
| 325 |
+
}
|
| 326 |
+
|
| 327 |
+
withVersionIs(val: any): this {
|
| 328 |
+
this.filters.push({ "version": { "$eq": val } });
|
| 329 |
+
return this;
|
| 330 |
+
}
|
| 331 |
+
|
| 332 |
+
withVersionIsNot(val: any): this {
|
| 333 |
+
this.filters.push({ "version": { "$ne": val } });
|
| 334 |
+
return this;
|
| 335 |
+
}
|
| 336 |
+
|
| 337 |
+
withVersionIn(...vals: any[]): this {
|
| 338 |
+
this.filters.push({ "version": { "$in": vals } });
|
| 339 |
+
return this;
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
withVersionNotIn(...vals: any[]): this {
|
| 343 |
+
this.filters.push({ "version": { "$notIn": vals } });
|
| 344 |
+
return this;
|
| 345 |
+
}
|
| 346 |
+
|
| 347 |
+
withVersionGreaterThan(val: any): this {
|
| 348 |
+
this.filters.push({ "version": { "$gt": val } });
|
| 349 |
+
return this;
|
| 350 |
+
}
|
| 351 |
+
|
| 352 |
+
withVersionGreaterThanOrEqualTo(val: any): this {
|
| 353 |
+
this.filters.push({ "version": { "$gte": val } });
|
| 354 |
+
return this;
|
| 355 |
+
}
|
| 356 |
+
|
| 357 |
+
withVersionLessThan(val: any): this {
|
| 358 |
+
this.filters.push({ "version": { "$lt": val } });
|
| 359 |
+
return this;
|
| 360 |
+
}
|
| 361 |
+
|
| 362 |
+
withVersionLessThanOrEqualTo(val: any): this {
|
| 363 |
+
this.filters.push({ "version": { "$lte": val } });
|
| 364 |
+
return this;
|
| 365 |
+
}
|
| 366 |
+
|
| 367 |
+
withVersionBetween(lower: any, upper: any): this {
|
| 368 |
+
this.filters.push({ "version": { "$between": [lower, upper] } });
|
| 369 |
+
return this;
|
| 370 |
+
}
|
| 371 |
+
|
| 372 |
+
withVersionIsKnown(): this {
|
| 373 |
+
this.filters.push({ "version": { "$isNull": false } });
|
| 374 |
+
return this;
|
| 375 |
+
}
|
| 376 |
+
|
| 377 |
+
withVersionIsUnknown(): this {
|
| 378 |
+
this.filters.push({ "version": { "$isNull": true } });
|
| 379 |
+
return this;
|
| 380 |
+
}
|
| 381 |
+
|
| 382 |
+
orderByIdAscending(): this {
|
| 383 |
+
this.query.orderBy("id", "asc");
|
| 384 |
+
return this;
|
| 385 |
+
}
|
| 386 |
+
|
| 387 |
+
orderByIdDescending(): this {
|
| 388 |
+
this.query.orderBy("id", "desc");
|
| 389 |
+
return this;
|
| 390 |
+
}
|
| 391 |
+
|
| 392 |
+
|
| 393 |
+
orderByReferenceCodeAscending(): this {
|
| 394 |
+
this.query.orderBy("referenceCode", "asc");
|
| 395 |
+
return this;
|
| 396 |
+
}
|
| 397 |
+
|
| 398 |
+
orderByReferenceCodeDescending(): this {
|
| 399 |
+
this.query.orderBy("referenceCode", "desc");
|
| 400 |
+
return this;
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
orderByVersionAscending(): this {
|
| 404 |
+
this.query.orderBy("version", "asc");
|
| 405 |
+
return this;
|
| 406 |
+
}
|
| 407 |
+
|
| 408 |
+
orderByVersionDescending(): this {
|
| 409 |
+
this.query.orderBy("version", "desc");
|
| 410 |
+
return this;
|
| 411 |
+
}
|
| 412 |
+
|
| 413 |
+
|
| 414 |
+
// --- Aggregations ---
|
| 415 |
+
count(): this {
|
| 416 |
+
this.query.aggregate("Count", "id", "count");
|
| 417 |
+
this._pageCountAlias = "count";
|
| 418 |
+
this._pageCountMethod = "count";
|
| 419 |
+
return this;
|
| 420 |
+
}
|
| 421 |
+
|
| 422 |
+
countAs(retName: string): this {
|
| 423 |
+
this.query.aggregate("Count", "id", retName);
|
| 424 |
+
this._pageCountAlias = retName;
|
| 425 |
+
this._pageCountMethod = "countAs";
|
| 426 |
+
return this;
|
| 427 |
+
}
|
| 428 |
+
|
| 429 |
+
|
| 430 |
+
// --- Group By ---
|
| 431 |
+
groupById(): this {
|
| 432 |
+
this.query.groupBy("id");
|
| 433 |
+
return this;
|
| 434 |
+
}
|
| 435 |
+
|
| 436 |
+
groupByIdAs(retName: string): this {
|
| 437 |
+
this.query.groupBy("id"); // In TS we don't alias group by yet natively
|
| 438 |
+
return this;
|
| 439 |
+
}
|
| 440 |
+
groupByCustomerOrder(): this {
|
| 441 |
+
this.query.groupBy("customerOrder");
|
| 442 |
+
return this;
|
| 443 |
+
}
|
| 444 |
+
|
| 445 |
+
groupByCustomerOrderAs(retName: string): this {
|
| 446 |
+
this.query.groupBy("customerOrder"); // In TS we don't alias group by yet natively
|
| 447 |
+
return this;
|
| 448 |
+
}
|
| 449 |
+
groupByReferenceCode(): this {
|
| 450 |
+
this.query.groupBy("referenceCode");
|
| 451 |
+
return this;
|
| 452 |
+
}
|
| 453 |
+
|
| 454 |
+
groupByReferenceCodeAs(retName: string): this {
|
| 455 |
+
this.query.groupBy("referenceCode"); // In TS we don't alias group by yet natively
|
| 456 |
+
return this;
|
| 457 |
+
}
|
| 458 |
+
groupByVersion(): this {
|
| 459 |
+
this.query.groupBy("version");
|
| 460 |
+
return this;
|
| 461 |
+
}
|
| 462 |
+
|
| 463 |
+
groupByVersionAs(retName: string): this {
|
| 464 |
+
this.query.groupBy("version"); // In TS we don't alias group by yet natively
|
| 465 |
+
return this;
|
| 466 |
+
}
|
| 467 |
+
|
| 468 |
+
// --- Facets ---
|
| 469 |
+
facetByCustomerOrderAs(
|
| 470 |
+
facetName: string,
|
| 471 |
+
request: { toQuery(): SelectQuery },
|
| 472 |
+
includeAllFacets = true,
|
| 473 |
+
): this {
|
| 474 |
+
this.query.facetBy(facetName, "customerOrder", request, includeAllFacets,
|
| 475 |
+
{ kind: "facet", method: "facetByCustomerOrderAs", relation: "customerOrder", alias: facetName });
|
| 476 |
+
return this;
|
| 477 |
+
}
|
| 478 |
+
|
| 479 |
+
|
| 480 |
+
private async executeForListInternal(context: UserContext): Promise<SmartList<Shipment>> {
|
| 481 |
+
this.ensureIntent();
|
| 482 |
+
if (this._pageCountAlias !== undefined) return this.executeCountedListInternal(context);
|
| 483 |
+
if (this.filters.length > 0) {
|
| 484 |
+
this.query.filter({ "$and": this.filters });
|
| 485 |
+
}
|
| 486 |
+
|
| 487 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 488 |
+
const rows = await service.executeQuery(context.prepareQuery(this.query));
|
| 489 |
+
const aggregateOnly = this.query.aggregateItems.length > 0 && this.query.groupByItems.length === 0;
|
| 490 |
+
const data = aggregateOnly ? [] : rows.map((row: unknown) =>
|
| 491 |
+
row instanceof Shipment
|
| 492 |
+
? row
|
| 493 |
+
: Shipment.fromRecord(row as Record<string, unknown>, new EntityRoot()));
|
| 494 |
+
const result = new SmartList<Shipment>(data);
|
| 495 |
+
if (aggregateOnly && rows[0]) Object.assign(result.aggregations, rows[0]);
|
| 496 |
+
|
| 497 |
+
if (this.query.facets.length > 0) {
|
| 498 |
+
result.facets = await executeRelationFacets(
|
| 499 |
+
service, (query: any) => context.prepareQuery(query), this.query, this.query.facets);
|
| 500 |
+
}
|
| 501 |
+
|
| 502 |
+
return result;
|
| 503 |
+
}
|
| 504 |
+
|
| 505 |
+
private async executeForRowsInternal(context: UserContext): Promise<SmartList<Record<string, unknown>>> {
|
| 506 |
+
this.ensureIntent();
|
| 507 |
+
if (this.filters.length > 0) this.query.filter({ "$and": this.filters });
|
| 508 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 509 |
+
return new SmartList<Record<string, unknown>>(
|
| 510 |
+
await service.executeQuery(context.prepareQuery(this.query)) as Record<string, unknown>[]);
|
| 511 |
+
}
|
| 512 |
+
|
| 513 |
+
private async executeCountedListInternal(
|
| 514 |
+
context: UserContext,
|
| 515 |
+
): Promise<SmartList<Shipment>> {
|
| 516 |
+
this.ensureIntent();
|
| 517 |
+
if (this.filters.length > 0) this.query.filter({ "$and": this.filters });
|
| 518 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 519 |
+
const preparedQuery = context.prepareQuery(this.query);
|
| 520 |
+
const useIdSet = preparedQuery.localIdSetPaginationOptions() !== undefined;
|
| 521 |
+
const countOperation = { kind: "named-count" as const,
|
| 522 |
+
method: this._pageCountMethod ?? "count",
|
| 523 |
+
...(this._pageCountMethod === "countAs" ? { alias: this._pageCountAlias } : {}) };
|
| 524 |
+
const totalCountBeforeRows = useIdSet ? undefined : await service.executeCount(
|
| 525 |
+
preparedQuery, this._pageCountAlias, countOperation);
|
| 526 |
+
const pageQuery = preparedQuery.clone();
|
| 527 |
+
// A page count describes the full filtered set, not an aggregate-only page row.
|
| 528 |
+
pageQuery.aggregateItems = pageQuery.aggregateItems.filter(item =>
|
| 529 |
+
!(String(item.function).toLowerCase() === "count" && item.alias === this._pageCountAlias));
|
| 530 |
+
const rows = await service.executeQuery(pageQuery);
|
| 531 |
+
const totalCount = useIdSet && context.idSetPaginationCountAccuracy === "EXACT"
|
| 532 |
+
? context.idSetPaginationCount!
|
| 533 |
+
: (totalCountBeforeRows ?? await service.executeCount(preparedQuery, this._pageCountAlias, countOperation));
|
| 534 |
+
const data = new SmartList(rows.map((row: unknown) =>
|
| 535 |
+
row instanceof Shipment
|
| 536 |
+
? row
|
| 537 |
+
: Shipment.fromRecord(row as Record<string, unknown>, new EntityRoot())));
|
| 538 |
+
data.totalCount = totalCount;
|
| 539 |
+
if (this._pageCountAlias !== undefined) data.aggregations[this._pageCountAlias] = totalCount;
|
| 540 |
+
if (this.query.facets.length > 0) {
|
| 541 |
+
data.facets = await executeRelationFacets(
|
| 542 |
+
service, (query: any) => context.prepareQuery(query), preparedQuery, preparedQuery.facets);
|
| 543 |
+
}
|
| 544 |
+
return data;
|
| 545 |
+
}
|
| 546 |
+
|
| 547 |
+
private executeForStreamInternal(context: UserContext, chunkSize: number): AsyncIterable<Shipment> {
|
| 548 |
+
this.ensureIntent();
|
| 549 |
+
if (this.filters.length > 0) this.query.filter({ "$and": this.filters });
|
| 550 |
+
const service = context.requireResource<TeaQLDataService>("dataService");
|
| 551 |
+
const preparedQuery = context.prepareQuery(this.query);
|
| 552 |
+
// Prepare Context and capture the runtime request before returning a lazy iterator.
|
| 553 |
+
const chunks = service.executeForStream(preparedQuery, chunkSize);
|
| 554 |
+
return (async function* () {
|
| 555 |
+
for await (const chunk of chunks) {
|
| 556 |
+
for (const entity of chunk) {
|
| 557 |
+
yield entity instanceof Shipment
|
| 558 |
+
? entity
|
| 559 |
+
: Shipment.fromRecord(entity as Record<string, unknown>, new EntityRoot());
|
| 560 |
+
}
|
| 561 |
+
}
|
| 562 |
+
})();
|
| 563 |
+
}
|
| 564 |
+
|
| 565 |
+
private ensureIntent(): void {
|
| 566 |
+
// Runtime owns validation, Unicode whitespace rules and typed diagnostics.
|
| 567 |
+
new QueryIntent(this._comment, this._purpose);
|
| 568 |
+
}
|
| 569 |
+
|
| 570 |
+
}
|
| 571 |
+
|
| 572 |
+
export class ExecutableShipmentRequest {
|
| 573 |
+
constructor(
|
| 574 |
+
private readonly execute: (context: UserContext) => Promise<SmartList<Shipment>>,
|
| 575 |
+
private readonly executeRows: (context: UserContext) => Promise<SmartList<Record<string, unknown>>>,
|
| 576 |
+
private readonly stream: (context: UserContext, chunkSize: number) => AsyncIterable<Shipment>,
|
| 577 |
+
private readonly limitOne: () => void,
|
| 578 |
+
private readonly addComment: (comment: string) => void,
|
| 579 |
+
private readonly ensureIntent: () => void,
|
| 580 |
+
) {}
|
| 581 |
+
|
| 582 |
+
comment(c: string): this {
|
| 583 |
+
this.addComment(c);
|
| 584 |
+
return this;
|
| 585 |
+
}
|
| 586 |
+
|
| 587 |
+
newEntity(context: UserContext): Shipment {
|
| 588 |
+
this.ensureIntent();
|
| 589 |
+
return new Shipment();
|
| 590 |
+
}
|
| 591 |
+
|
| 592 |
+
executeForList(context: UserContext): Promise<SmartList<Shipment>> {
|
| 593 |
+
this.ensureIntent();
|
| 594 |
+
return this.execute(context);
|
| 595 |
+
}
|
| 596 |
+
|
| 597 |
+
executeForRows(context: UserContext): Promise<SmartList<Record<string, unknown>>> {
|
| 598 |
+
this.ensureIntent();
|
| 599 |
+
return this.executeRows(context);
|
| 600 |
+
}
|
| 601 |
+
|
| 602 |
+
executeForStream(context: UserContext, chunkSize = 1000): AsyncIterable<Shipment> {
|
| 603 |
+
this.ensureIntent();
|
| 604 |
+
return this.stream(context, chunkSize);
|
| 605 |
+
}
|
| 606 |
+
|
| 607 |
+
async executeForOne(context: UserContext): Promise<Shipment | undefined> {
|
| 608 |
+
this.limitOne();
|
| 609 |
+
return (await this.executeForList(context))[0];
|
| 610 |
+
}
|
| 611 |
+
}
|
source/teaql-ts/examples/trace-chain/lib/src/runtime-module.ts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { ObjectLocation, RuntimeModule } from "teaql-ts";
|
| 2 |
+
import { ENTITY_SCHEMAS } from "./teaql-schemas";
|
| 3 |
+
import { ensureGeneratedBootstrap } from "./generated-bootstrap";
|
| 4 |
+
|
| 5 |
+
/** Generated canonical KSML to selected-wire mapping. Never infer this from TS members. */
|
| 6 |
+
export const GENERATED_WIRE_MODEL_METADATA = Object.freeze({
|
| 7 |
+
profile: "camelCase" as const,
|
| 8 |
+
entities: Object.freeze({
|
| 9 |
+
"Platform": Object.freeze({
|
| 10 |
+
entityType: "Platform",
|
| 11 |
+
profile: "camelCase" as const,
|
| 12 |
+
fields: Object.freeze({
|
| 13 |
+
"id": Object.freeze({ canonicalName: "id", wireName: "id", aliases: Object.freeze([] as string[]) }),
|
| 14 |
+
"name": Object.freeze({ canonicalName: "name", wireName: "name", aliases: Object.freeze([] as string[]) }),
|
| 15 |
+
"version": Object.freeze({ canonicalName: "version", wireName: "version", aliases: Object.freeze([] as string[]) })
|
| 16 |
+
}),
|
| 17 |
+
}),
|
| 18 |
+
"CustomerOrder": Object.freeze({
|
| 19 |
+
entityType: "CustomerOrder",
|
| 20 |
+
profile: "camelCase" as const,
|
| 21 |
+
fields: Object.freeze({
|
| 22 |
+
"id": Object.freeze({ canonicalName: "id", wireName: "id", aliases: Object.freeze([] as string[]) }),
|
| 23 |
+
"platform": Object.freeze({ canonicalName: "platform", wireName: "platform", aliases: Object.freeze([] as string[]) }),
|
| 24 |
+
"order_number": Object.freeze({ canonicalName: "order_number", wireName: "orderNumber", aliases: Object.freeze([] as string[]) }),
|
| 25 |
+
"description": Object.freeze({ canonicalName: "description", wireName: "description", aliases: Object.freeze([] as string[]) }),
|
| 26 |
+
"version": Object.freeze({ canonicalName: "version", wireName: "version", aliases: Object.freeze([] as string[]) })
|
| 27 |
+
}),
|
| 28 |
+
}),
|
| 29 |
+
"OrderItem": Object.freeze({
|
| 30 |
+
entityType: "OrderItem",
|
| 31 |
+
profile: "camelCase" as const,
|
| 32 |
+
fields: Object.freeze({
|
| 33 |
+
"id": Object.freeze({ canonicalName: "id", wireName: "id", aliases: Object.freeze([] as string[]) }),
|
| 34 |
+
"customer_order": Object.freeze({ canonicalName: "customer_order", wireName: "customerOrder", aliases: Object.freeze([] as string[]) }),
|
| 35 |
+
"name": Object.freeze({ canonicalName: "name", wireName: "name", aliases: Object.freeze([] as string[]) }),
|
| 36 |
+
"version": Object.freeze({ canonicalName: "version", wireName: "version", aliases: Object.freeze([] as string[]) })
|
| 37 |
+
}),
|
| 38 |
+
}),
|
| 39 |
+
"Payment": Object.freeze({
|
| 40 |
+
entityType: "Payment",
|
| 41 |
+
profile: "camelCase" as const,
|
| 42 |
+
fields: Object.freeze({
|
| 43 |
+
"id": Object.freeze({ canonicalName: "id", wireName: "id", aliases: Object.freeze([] as string[]) }),
|
| 44 |
+
"customer_order": Object.freeze({ canonicalName: "customer_order", wireName: "customerOrder", aliases: Object.freeze([] as string[]) }),
|
| 45 |
+
"reference_code": Object.freeze({ canonicalName: "reference_code", wireName: "referenceCode", aliases: Object.freeze([] as string[]) }),
|
| 46 |
+
"version": Object.freeze({ canonicalName: "version", wireName: "version", aliases: Object.freeze([] as string[]) })
|
| 47 |
+
}),
|
| 48 |
+
}),
|
| 49 |
+
"PaymentAttempt": Object.freeze({
|
| 50 |
+
entityType: "PaymentAttempt",
|
| 51 |
+
profile: "camelCase" as const,
|
| 52 |
+
fields: Object.freeze({
|
| 53 |
+
"id": Object.freeze({ canonicalName: "id", wireName: "id", aliases: Object.freeze([] as string[]) }),
|
| 54 |
+
"payment": Object.freeze({ canonicalName: "payment", wireName: "payment", aliases: Object.freeze([] as string[]) }),
|
| 55 |
+
"reference_code": Object.freeze({ canonicalName: "reference_code", wireName: "referenceCode", aliases: Object.freeze([] as string[]) }),
|
| 56 |
+
"version": Object.freeze({ canonicalName: "version", wireName: "version", aliases: Object.freeze([] as string[]) })
|
| 57 |
+
}),
|
| 58 |
+
}),
|
| 59 |
+
"Shipment": Object.freeze({
|
| 60 |
+
entityType: "Shipment",
|
| 61 |
+
profile: "camelCase" as const,
|
| 62 |
+
fields: Object.freeze({
|
| 63 |
+
"id": Object.freeze({ canonicalName: "id", wireName: "id", aliases: Object.freeze([] as string[]) }),
|
| 64 |
+
"customer_order": Object.freeze({ canonicalName: "customer_order", wireName: "customerOrder", aliases: Object.freeze([] as string[]) }),
|
| 65 |
+
"reference_code": Object.freeze({ canonicalName: "reference_code", wireName: "referenceCode", aliases: Object.freeze([] as string[]) }),
|
| 66 |
+
"version": Object.freeze({ canonicalName: "version", wireName: "version", aliases: Object.freeze([] as string[]) })
|
| 67 |
+
}),
|
| 68 |
+
})
|
| 69 |
+
}),
|
| 70 |
+
});
|
| 71 |
+
|
| 72 |
+
/** Passive generated metadata manifest. It never modifies the database schema. */
|
| 73 |
+
export const GENERATED_RUNTIME_MODULE = new RuntimeModule(ENTITY_SCHEMAS, {
|
| 74 |
+
"Platform": {
|
| 75 |
+
checkAndFix(context, mutation, results) {
|
| 76 |
+
const now = context.getResource("fixTime");
|
| 77 |
+
if ((mutation.action === "Create" && mutation.payload["name"] === undefined) || mutation.payload["name"] === null) results.push({ ruleId: "required", location: ObjectLocation.property("name") });
|
| 78 |
+
if (mutation.payload["name"] != null && [...String(mutation.payload["name"])].length > 100) results.push({ ruleId: "max_length", location: ObjectLocation.property("name"), inputValue: mutation.payload["name"], systemValue: 100 });
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
},
|
| 82 |
+
},
|
| 83 |
+
"CustomerOrder": {
|
| 84 |
+
checkAndFix(context, mutation, results) {
|
| 85 |
+
const now = context.getResource("fixTime");
|
| 86 |
+
if ((mutation.action === "Create" && mutation.payload["platform"] === undefined) || mutation.payload["platform"] === null) results.push({ ruleId: "required", location: ObjectLocation.property("platform") });
|
| 87 |
+
|
| 88 |
+
if ((mutation.action === "Create" && mutation.payload["order_number"] === undefined) || mutation.payload["order_number"] === null) results.push({ ruleId: "required", location: ObjectLocation.property("order_number") });
|
| 89 |
+
if (mutation.payload["order_number"] != null && [...String(mutation.payload["order_number"])].length > 100) results.push({ ruleId: "max_length", location: ObjectLocation.property("order_number"), inputValue: mutation.payload["order_number"], systemValue: 100 });
|
| 90 |
+
|
| 91 |
+
if ((mutation.action === "Create" && mutation.payload["description"] === undefined) || mutation.payload["description"] === null) results.push({ ruleId: "required", location: ObjectLocation.property("description") });
|
| 92 |
+
if (mutation.payload["description"] != null && [...String(mutation.payload["description"])].length > 100) results.push({ ruleId: "max_length", location: ObjectLocation.property("description"), inputValue: mutation.payload["description"], systemValue: 100 });
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
},
|
| 96 |
+
},
|
| 97 |
+
"OrderItem": {
|
| 98 |
+
checkAndFix(context, mutation, results) {
|
| 99 |
+
const now = context.getResource("fixTime");
|
| 100 |
+
if ((mutation.action === "Create" && mutation.payload["customer_order"] === undefined) || mutation.payload["customer_order"] === null) results.push({ ruleId: "required", location: ObjectLocation.property("customer_order") });
|
| 101 |
+
|
| 102 |
+
if ((mutation.action === "Create" && mutation.payload["name"] === undefined) || mutation.payload["name"] === null) results.push({ ruleId: "required", location: ObjectLocation.property("name") });
|
| 103 |
+
if (mutation.payload["name"] != null && [...String(mutation.payload["name"])].length > 100) results.push({ ruleId: "max_length", location: ObjectLocation.property("name"), inputValue: mutation.payload["name"], systemValue: 100 });
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
},
|
| 107 |
+
},
|
| 108 |
+
"Payment": {
|
| 109 |
+
checkAndFix(context, mutation, results) {
|
| 110 |
+
const now = context.getResource("fixTime");
|
| 111 |
+
if ((mutation.action === "Create" && mutation.payload["customer_order"] === undefined) || mutation.payload["customer_order"] === null) results.push({ ruleId: "required", location: ObjectLocation.property("customer_order") });
|
| 112 |
+
|
| 113 |
+
if ((mutation.action === "Create" && mutation.payload["reference_code"] === undefined) || mutation.payload["reference_code"] === null) results.push({ ruleId: "required", location: ObjectLocation.property("reference_code") });
|
| 114 |
+
if (mutation.payload["reference_code"] != null && [...String(mutation.payload["reference_code"])].length > 100) results.push({ ruleId: "max_length", location: ObjectLocation.property("reference_code"), inputValue: mutation.payload["reference_code"], systemValue: 100 });
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
},
|
| 118 |
+
},
|
| 119 |
+
"PaymentAttempt": {
|
| 120 |
+
checkAndFix(context, mutation, results) {
|
| 121 |
+
const now = context.getResource("fixTime");
|
| 122 |
+
if ((mutation.action === "Create" && mutation.payload["payment"] === undefined) || mutation.payload["payment"] === null) results.push({ ruleId: "required", location: ObjectLocation.property("payment") });
|
| 123 |
+
|
| 124 |
+
if ((mutation.action === "Create" && mutation.payload["reference_code"] === undefined) || mutation.payload["reference_code"] === null) results.push({ ruleId: "required", location: ObjectLocation.property("reference_code") });
|
| 125 |
+
if (mutation.payload["reference_code"] != null && [...String(mutation.payload["reference_code"])].length > 100) results.push({ ruleId: "max_length", location: ObjectLocation.property("reference_code"), inputValue: mutation.payload["reference_code"], systemValue: 100 });
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
},
|
| 129 |
+
},
|
| 130 |
+
"Shipment": {
|
| 131 |
+
checkAndFix(context, mutation, results) {
|
| 132 |
+
const now = context.getResource("fixTime");
|
| 133 |
+
if ((mutation.action === "Create" && mutation.payload["customer_order"] === undefined) || mutation.payload["customer_order"] === null) results.push({ ruleId: "required", location: ObjectLocation.property("customer_order") });
|
| 134 |
+
|
| 135 |
+
if ((mutation.action === "Create" && mutation.payload["reference_code"] === undefined) || mutation.payload["reference_code"] === null) results.push({ ruleId: "required", location: ObjectLocation.property("reference_code") });
|
| 136 |
+
if (mutation.payload["reference_code"] != null && [...String(mutation.payload["reference_code"])].length > 100) results.push({ ruleId: "max_length", location: ObjectLocation.property("reference_code"), inputValue: mutation.payload["reference_code"], systemValue: 100 });
|
| 137 |
+
|
| 138 |
+
|
| 139 |
+
},
|
| 140 |
+
}
|
| 141 |
+
}, { ...{
|
| 142 |
+
defaultDomainRoot: { entity: "Platform", id: "1", values: { "name": "Trace Chain Verification" } },
|
| 143 |
+
constants: []
|
| 144 |
+
}, ensure: ensureGeneratedBootstrap });
|
source/teaql-ts/examples/trace-chain/lib/src/teaql-schemas.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { EntitySchema } from "teaql-ts/sql/core";
|
| 2 |
+
|
| 3 |
+
export const ENTITY_SCHEMAS: Record<string, EntitySchema> = {
|
| 4 |
+
"Platform": {
|
| 5 |
+
table: "platform_data",
|
| 6 |
+
auditMaskFields: [],
|
| 7 |
+
columns: {"id": { columnName: "id", modelName: "id", logPolicy: "plain", logicalType: "integer", decode: "string", nullable: false }, "name": { columnName: "name", modelName: "name", logPolicy: "plain", logicalType: "text", decode: "native", nullable: false }, "version": { columnName: "version", modelName: "version", logPolicy: "plain", logicalType: "integer", decode: "number", nullable: false }},
|
| 8 |
+
relations: {"customerOrderList": { targetEntity: "CustomerOrder", localKey: "id", foreignKey: "platform", many: true }}
|
| 9 |
+
},
|
| 10 |
+
"CustomerOrder": {
|
| 11 |
+
table: "customer_order_data",
|
| 12 |
+
auditMaskFields: [],
|
| 13 |
+
columns: {"id": { columnName: "id", modelName: "id", logPolicy: "plain", logicalType: "integer", decode: "string", nullable: false }, "platform": { columnName: "platform", modelName: "platform", logPolicy: "plain", logicalType: "integer", decode: "string", nullable: false }, "orderNumber": { columnName: "order_number", modelName: "order_number", logPolicy: "plain", logicalType: "text", decode: "native", nullable: false }, "description": { columnName: "description", modelName: "description", logPolicy: "plain", logicalType: "text", decode: "native", nullable: false }, "version": { columnName: "version", modelName: "version", logPolicy: "plain", logicalType: "integer", decode: "number", nullable: false }},
|
| 14 |
+
relations: {"platform": { targetEntity: "Platform", localKey: "platform", foreignKey: "id", many: false }, "orderItemList": { targetEntity: "OrderItem", localKey: "id", foreignKey: "customerOrder", many: true }, "paymentList": { targetEntity: "Payment", localKey: "id", foreignKey: "customerOrder", many: true }, "shipmentList": { targetEntity: "Shipment", localKey: "id", foreignKey: "customerOrder", many: true }}
|
| 15 |
+
},
|
| 16 |
+
"OrderItem": {
|
| 17 |
+
table: "order_item_data",
|
| 18 |
+
auditMaskFields: ["name"],
|
| 19 |
+
columns: {"id": { columnName: "id", modelName: "id", logPolicy: "plain", logicalType: "integer", decode: "string", nullable: false }, "customerOrder": { columnName: "customer_order", modelName: "customer_order", logPolicy: "plain", logicalType: "integer", decode: "string", nullable: false }, "name": { columnName: "name", modelName: "name", logPolicy: "plain", logicalType: "text", decode: "native", nullable: false }, "version": { columnName: "version", modelName: "version", logPolicy: "plain", logicalType: "integer", decode: "number", nullable: false }},
|
| 20 |
+
relations: {"customerOrder": { targetEntity: "CustomerOrder", localKey: "customerOrder", foreignKey: "id", many: false }}
|
| 21 |
+
},
|
| 22 |
+
"Payment": {
|
| 23 |
+
table: "payment_data",
|
| 24 |
+
auditMaskFields: [],
|
| 25 |
+
columns: {"id": { columnName: "id", modelName: "id", logPolicy: "plain", logicalType: "integer", decode: "string", nullable: false }, "customerOrder": { columnName: "customer_order", modelName: "customer_order", logPolicy: "plain", logicalType: "integer", decode: "string", nullable: false }, "referenceCode": { columnName: "reference_code", modelName: "reference_code", logPolicy: "plain", logicalType: "text", decode: "native", nullable: false }, "version": { columnName: "version", modelName: "version", logPolicy: "plain", logicalType: "integer", decode: "number", nullable: false }},
|
| 26 |
+
relations: {"customerOrder": { targetEntity: "CustomerOrder", localKey: "customerOrder", foreignKey: "id", many: false }, "paymentAttemptList": { targetEntity: "PaymentAttempt", localKey: "id", foreignKey: "payment", many: true }}
|
| 27 |
+
},
|
| 28 |
+
"PaymentAttempt": {
|
| 29 |
+
table: "payment_attempt_data",
|
| 30 |
+
auditMaskFields: [],
|
| 31 |
+
columns: {"id": { columnName: "id", modelName: "id", logPolicy: "plain", logicalType: "integer", decode: "string", nullable: false }, "payment": { columnName: "payment", modelName: "payment", logPolicy: "plain", logicalType: "integer", decode: "string", nullable: false }, "referenceCode": { columnName: "reference_code", modelName: "reference_code", logPolicy: "plain", logicalType: "text", decode: "native", nullable: false }, "version": { columnName: "version", modelName: "version", logPolicy: "plain", logicalType: "integer", decode: "number", nullable: false }},
|
| 32 |
+
relations: {"payment": { targetEntity: "Payment", localKey: "payment", foreignKey: "id", many: false }}
|
| 33 |
+
},
|
| 34 |
+
"Shipment": {
|
| 35 |
+
table: "shipment_data",
|
| 36 |
+
auditMaskFields: [],
|
| 37 |
+
columns: {"id": { columnName: "id", modelName: "id", logPolicy: "plain", logicalType: "integer", decode: "string", nullable: false }, "customerOrder": { columnName: "customer_order", modelName: "customer_order", logPolicy: "plain", logicalType: "integer", decode: "string", nullable: false }, "referenceCode": { columnName: "reference_code", modelName: "reference_code", logPolicy: "plain", logicalType: "text", decode: "native", nullable: false }, "version": { columnName: "version", modelName: "version", logPolicy: "plain", logicalType: "integer", decode: "number", nullable: false }},
|
| 38 |
+
relations: {"customerOrder": { targetEntity: "CustomerOrder", localKey: "customerOrder", foreignKey: "id", many: false }}
|
| 39 |
+
}
|
| 40 |
+
};
|
source/teaql-ts/examples/trace-chain/lib/src/teaql-ts.ts
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import {
|
| 2 |
+
CheckException, EntityChecker, RuntimeModule,
|
| 3 |
+
SelectQuery as RuntimeSelectQuery, UserContext,
|
| 4 |
+
executeRelationFacets, QueryRequest, MutationIntent, MutationRequest, GraphMutationSession,
|
| 5 |
+
} from "teaql-ts";
|
| 6 |
+
|
| 7 |
+
export { CheckException, EntityRoot, ObjectLocation, SmartList, UserContext, executeRelationFacets, MutationIntent } from "teaql-ts";
|
| 8 |
+
export { GraphMutationSession, LoadedScalarSnapshot, MutationTraceScope } from "teaql-ts";
|
| 9 |
+
export type { EntityKey } from "teaql-ts";
|
| 10 |
+
export type { TeaQLPage } from "teaql-ts";
|
| 11 |
+
import type { QueryOperation } from "teaql-ts";
|
| 12 |
+
|
| 13 |
+
function soundex(input: unknown): string {
|
| 14 |
+
const text = String(input ?? "").toUpperCase().replace(/[^A-Z]/g, "");
|
| 15 |
+
if (!text) return "";
|
| 16 |
+
const code = (char: string): string => "BFPV".includes(char) ? "1"
|
| 17 |
+
: "CGJKQSXZ".includes(char) ? "2" : "DT".includes(char) ? "3"
|
| 18 |
+
: char === "L" ? "4" : "MN".includes(char) ? "5" : char === "R" ? "6" : "";
|
| 19 |
+
let result = text[0], previous = code(text[0]);
|
| 20 |
+
for (const char of text.slice(1)) {
|
| 21 |
+
const current = code(char);
|
| 22 |
+
if (current && current !== previous) result += current;
|
| 23 |
+
previous = current;
|
| 24 |
+
if (result.length === 4) break;
|
| 25 |
+
}
|
| 26 |
+
return (result + "000").slice(0, 4);
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
/** Generated naming adapter; query policy and execution remain in the formal runtime. */
|
| 30 |
+
export class SelectQuery extends RuntimeSelectQuery {
|
| 31 |
+
orderBy(field: string, direction: string): this {
|
| 32 |
+
return this.order({ field, expr: null, direction: direction === "desc" ? "Desc" : "Asc" } as any);
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
relationQuery(
|
| 36 |
+
name: string, query: RuntimeSelectQuery, localKey = "id", foreignKey = "id", many = true,
|
| 37 |
+
operation?: QueryOperation,
|
| 38 |
+
): this {
|
| 39 |
+
return super.relationQuery(name, query, localKey, foreignKey, many, operation);
|
| 40 |
+
}
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
export interface TeaQLDataService {
|
| 44 |
+
executeGraphSave<T>(intent: MutationIntent, work: (graph: GraphMutationSession) => Promise<T>): Promise<T>;
|
| 45 |
+
preflightMutation(mutation: any): any;
|
| 46 |
+
afterGraphCommit(work: () => void): void;
|
| 47 |
+
afterGraphRollback(work: () => void): void;
|
| 48 |
+
executeMutation(mutation: any): Promise<any>;
|
| 49 |
+
executeQuery(query: any): Promise<any[]>;
|
| 50 |
+
executeCount(query: any, alias?: string, operation?: QueryOperation): Promise<number>;
|
| 51 |
+
executeForStream(query: any, chunkSize?: number): AsyncIterable<any[]>;
|
| 52 |
+
close?(): Promise<void>;
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
export class TeaQLClient implements TeaQLDataService {
|
| 56 |
+
private data: Record<string, Record<string, any>> = {};
|
| 57 |
+
private nextIds: Record<string, number> = {};
|
| 58 |
+
private readonly checkers: Record<string, EntityChecker> = {};
|
| 59 |
+
private userContext = new UserContext();
|
| 60 |
+
private graphSaveActive = false;
|
| 61 |
+
private graphCommitActions: Array<() => void> = [];
|
| 62 |
+
private graphRollbackActions: Array<() => void> = [];
|
| 63 |
+
private graphSaveTail: Promise<void> = Promise.resolve();
|
| 64 |
+
private readonly mutationGovernanceEvents: any[] = [];
|
| 65 |
+
|
| 66 |
+
constructor(private storagePath?: string) {
|
| 67 |
+
if (storagePath) {
|
| 68 |
+
const fs = require("fs");
|
| 69 |
+
if (fs.existsSync(storagePath)) {
|
| 70 |
+
const state = JSON.parse(fs.readFileSync(storagePath, "utf8"));
|
| 71 |
+
this.data = state.data || {};
|
| 72 |
+
this.nextIds = state.nextIds || {};
|
| 73 |
+
}
|
| 74 |
+
}
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
/** Installs passive generated metadata. It never mutates storage. */
|
| 78 |
+
install(module: RuntimeModule): this {
|
| 79 |
+
Object.assign(this.checkers, module.checkers);
|
| 80 |
+
return this;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
setUserContext(context: UserContext): this {
|
| 84 |
+
this.userContext = context;
|
| 85 |
+
return this;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
get mutationGovernanceTrace(): readonly any[] {
|
| 89 |
+
return [...this.mutationGovernanceEvents];
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
private persist() {
|
| 93 |
+
if (!this.storagePath) return;
|
| 94 |
+
const fs = require("fs");
|
| 95 |
+
const path = require("path");
|
| 96 |
+
fs.mkdirSync(path.dirname(path.resolve(this.storagePath)), { recursive: true });
|
| 97 |
+
const temporaryPath = `${this.storagePath}.tmp`;
|
| 98 |
+
fs.writeFileSync(temporaryPath, JSON.stringify({ data: this.data, nextIds: this.nextIds }));
|
| 99 |
+
fs.renameSync(temporaryPath, this.storagePath);
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
async executeGraphSave<T>(intent: MutationIntent, work: (graph: GraphMutationSession) => Promise<T>): Promise<T> {
|
| 103 |
+
const graph = new GraphMutationSession(intent);
|
| 104 |
+
const predecessor = this.graphSaveTail;
|
| 105 |
+
let release!: () => void;
|
| 106 |
+
this.graphSaveTail = new Promise<void>(resolve => { release = resolve; });
|
| 107 |
+
await predecessor;
|
| 108 |
+
const dataSnapshot = JSON.parse(JSON.stringify(this.data));
|
| 109 |
+
const nextIdsSnapshot = { ...this.nextIds };
|
| 110 |
+
let fixEvidenceStarted = false;
|
| 111 |
+
let mutationPolicyGraphStarted = false;
|
| 112 |
+
try {
|
| 113 |
+
this.graphSaveActive = true;
|
| 114 |
+
this.graphCommitActions = [];
|
| 115 |
+
this.graphRollbackActions = [];
|
| 116 |
+
this.userContext.insertResource("fixTime", new Date());
|
| 117 |
+
this.userContext.beginFixEvidence();
|
| 118 |
+
fixEvidenceStarted = true;
|
| 119 |
+
this.userContext.beginMutationPolicyGraph();
|
| 120 |
+
mutationPolicyGraphStarted = true;
|
| 121 |
+
const result = await work(graph);
|
| 122 |
+
this.userContext.ensureMutationPolicyGraphComplete();
|
| 123 |
+
this.persist();
|
| 124 |
+
for (const action of this.graphCommitActions) action();
|
| 125 |
+
return result;
|
| 126 |
+
} catch (error) {
|
| 127 |
+
this.data = dataSnapshot;
|
| 128 |
+
this.nextIds = nextIdsSnapshot;
|
| 129 |
+
for (const action of [...this.graphRollbackActions].reverse()) action();
|
| 130 |
+
throw error;
|
| 131 |
+
} finally {
|
| 132 |
+
this.graphSaveActive = false;
|
| 133 |
+
this.graphCommitActions = [];
|
| 134 |
+
this.graphRollbackActions = [];
|
| 135 |
+
if (mutationPolicyGraphStarted) this.userContext.endMutationPolicyGraph();
|
| 136 |
+
this.userContext.removeResource("fixTime");
|
| 137 |
+
if (fixEvidenceStarted) this.userContext.finishFixEvidence();
|
| 138 |
+
release();
|
| 139 |
+
}
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
afterGraphCommit(work: () => void): void {
|
| 143 |
+
if (!this.graphSaveActive) throw new Error("No graph save is active");
|
| 144 |
+
this.graphCommitActions.push(work);
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
afterGraphRollback(work: () => void): void {
|
| 148 |
+
if (!this.graphSaveActive) throw new Error("No graph save is active");
|
| 149 |
+
this.graphRollbackActions.push(work);
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
preflightMutation(mutation: any): any {
|
| 153 |
+
mutation = this.checkAndFixMutation(mutation);
|
| 154 |
+
this.userContext.recordMutationPolicyPreflight(mutation);
|
| 155 |
+
return mutation;
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
private checkAndFixMutation(mutation: any): any {
|
| 159 |
+
if (mutation instanceof MutationRequest) mutation = mutation.mutation;
|
| 160 |
+
if (!String(mutation?.comment || "").trim()) throw new Error("Security audit failure: audit reason is required before mutation");
|
| 161 |
+
mutation = { ...mutation, payload: { ...(mutation?.payload || {}) } };
|
| 162 |
+
const checker = this.checkers[String(mutation.entity)];
|
| 163 |
+
if (!checker) return mutation;
|
| 164 |
+
const results: any[] = [];
|
| 165 |
+
const ownsFixTime = this.userContext.getResource("fixTime") === undefined;
|
| 166 |
+
if (ownsFixTime) this.userContext.insertResource("fixTime", new Date()).beginFixEvidence();
|
| 167 |
+
try {
|
| 168 |
+
checker.checkAndFix(this.userContext, mutation, results);
|
| 169 |
+
if (mutation.ledgerKey && mutation.ledgerRoot) for (const [field, value] of Object.entries(mutation.payload)) mutation.ledgerRoot.set(mutation.ledgerKey, field, value);
|
| 170 |
+
this.userContext.translateCheckResults(results);
|
| 171 |
+
if (results.length) throw new CheckException(results);
|
| 172 |
+
return mutation;
|
| 173 |
+
} finally { if (ownsFixTime) this.userContext.removeResource("fixTime").finishFixEvidence(); }
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
async executeMutation(mutation: any): Promise<any> {
|
| 177 |
+
mutation = this.checkAndFixMutation(mutation);
|
| 178 |
+
const mutationGovernance = this.userContext.enterMutationPolicy(mutation);
|
| 179 |
+
this.mutationGovernanceEvents.push(mutationGovernance);
|
| 180 |
+
const table = this.data[mutation.entity] ||= {};
|
| 181 |
+
if (mutation.action === "Create") {
|
| 182 |
+
const id = mutation.id ?? String(this.nextIds[mutation.entity] || 1);
|
| 183 |
+
this.nextIds[mutation.entity] = Number(id) + 1;
|
| 184 |
+
const record = { ...mutation.payload, id: String(id), version: Number(mutation.version || 0) + 1 };
|
| 185 |
+
table[String(id)] = record;
|
| 186 |
+
if (!this.graphSaveActive) this.persist();
|
| 187 |
+
return { success: true, id: String(id), version: record.version, persistedRecord: { ...record } };
|
| 188 |
+
}
|
| 189 |
+
if (mutation.action === "Update") {
|
| 190 |
+
const id = String(mutation.id);
|
| 191 |
+
if (!table[id]) throw new Error(`${mutation.entity}(${id}) does not exist`);
|
| 192 |
+
const expectedVersion = Number(mutation.version);
|
| 193 |
+
const currentVersion = Number(table[id].version || 0);
|
| 194 |
+
if (!Number.isFinite(expectedVersion) || expectedVersion !== currentVersion) {
|
| 195 |
+
throw new Error(
|
| 196 |
+
`Optimistic lock conflict for ${mutation.entity}(${id}): expected ${expectedVersion}, current ${currentVersion}`);
|
| 197 |
+
}
|
| 198 |
+
table[id] = { ...table[id], ...mutation.payload, id, version: Number(table[id].version || 0) + 1 };
|
| 199 |
+
if (!this.graphSaveActive) this.persist();
|
| 200 |
+
return { success: true, id, version: table[id].version, persistedRecord: { ...table[id] } };
|
| 201 |
+
}
|
| 202 |
+
if (mutation.action === "Delete") {
|
| 203 |
+
const id = String(mutation.id);
|
| 204 |
+
if (!table[id]) throw new Error(`${mutation.entity}(${id}) does not exist`);
|
| 205 |
+
const expectedVersion = Number(mutation.version);
|
| 206 |
+
const currentVersion = Number(table[id].version || 0);
|
| 207 |
+
if (!Number.isFinite(expectedVersion) || expectedVersion !== currentVersion) {
|
| 208 |
+
throw new Error(
|
| 209 |
+
`Optimistic lock conflict for ${mutation.entity}(${id}): expected ${expectedVersion}, current ${currentVersion}`);
|
| 210 |
+
}
|
| 211 |
+
table[id] = { ...table[id], id, version: -(currentVersion + 1) };
|
| 212 |
+
if (!this.graphSaveActive) this.persist();
|
| 213 |
+
return { success: true, id, version: table[id].version, deleted: true, persistedRecord: { ...table[id] } };
|
| 214 |
+
}
|
| 215 |
+
throw new Error(`Unsupported mutation action: ${mutation.action}`);
|
| 216 |
+
}
|
| 217 |
+
async query(context: any, req: any): Promise<any> {
|
| 218 |
+
return { rows: [] };
|
| 219 |
+
}
|
| 220 |
+
async executeQuery(query: any): Promise<any> {
|
| 221 |
+
if (!(query instanceof RuntimeSelectQuery)) {
|
| 222 |
+
throw new Error("TeaQL list execution requires the formal runtime SelectQuery");
|
| 223 |
+
}
|
| 224 |
+
query.prepareForList();
|
| 225 |
+
let rows = Object.values(this.data[query.entity] || {}).map((row: any) => ({ ...row }));
|
| 226 |
+
const matches = (row: any, expression: any): boolean => {
|
| 227 |
+
if (expression?.$and) return expression.$and.every((item: any) => matches(row, item));
|
| 228 |
+
return Object.entries(expression || {}).every(([field, predicate]: [string, any]) => {
|
| 229 |
+
if (predicate?.$eq !== undefined) return row[field] === (predicate.$eq?.id ?? predicate.$eq);
|
| 230 |
+
if (predicate?.$ne !== undefined) return row[field] !== (predicate.$ne?.id ?? predicate.$ne);
|
| 231 |
+
if (predicate?.$contains !== undefined) return String(row[field] ?? "").includes(String(predicate.$contains));
|
| 232 |
+
if (predicate?.$notContains !== undefined) return !String(row[field] ?? "").includes(String(predicate.$notContains));
|
| 233 |
+
if (predicate?.$startsWith !== undefined) return String(row[field] ?? "").startsWith(String(predicate.$startsWith));
|
| 234 |
+
if (predicate?.$notStartsWith !== undefined) return !String(row[field] ?? "").startsWith(String(predicate.$notStartsWith));
|
| 235 |
+
if (predicate?.$endsWith !== undefined) return String(row[field] ?? "").endsWith(String(predicate.$endsWith));
|
| 236 |
+
if (predicate?.$notEndsWith !== undefined) return !String(row[field] ?? "").endsWith(String(predicate.$notEndsWith));
|
| 237 |
+
if (predicate?.$soundLike !== undefined) return soundex(row[field]) === soundex(predicate.$soundLike);
|
| 238 |
+
if (predicate?.$in !== undefined) return predicate.$in.some((value: any) => row[field] === (value?.id ?? value));
|
| 239 |
+
if (predicate?.$notIn !== undefined) return !predicate.$notIn.some((value: any) => row[field] === (value?.id ?? value));
|
| 240 |
+
if (predicate?.$between !== undefined) return row[field] >= predicate.$between[0] && row[field] <= predicate.$between[1];
|
| 241 |
+
if (predicate?.$isNull === true) return row[field] === null || row[field] === undefined;
|
| 242 |
+
if (predicate?.$isNull === false) return row[field] !== null && row[field] !== undefined;
|
| 243 |
+
if (predicate?.$gt !== undefined) return row[field] > predicate.$gt;
|
| 244 |
+
if (predicate?.$gte !== undefined) return row[field] >= predicate.$gte;
|
| 245 |
+
if (predicate?.$lt !== undefined) return row[field] < predicate.$lt;
|
| 246 |
+
if (predicate?.$lte !== undefined) return row[field] <= predicate.$lte;
|
| 247 |
+
return true;
|
| 248 |
+
});
|
| 249 |
+
};
|
| 250 |
+
if (query.filterCondition) rows = rows.filter(row => matches(row, query.filterCondition));
|
| 251 |
+
if (query.aggregateItems?.length) {
|
| 252 |
+
return [Object.fromEntries(query.aggregateItems.map((aggregate: any) => {
|
| 253 |
+
if (String(aggregate.function).toLowerCase() !== "count") {
|
| 254 |
+
throw new Error(`Unsupported local aggregate: ${aggregate.function}`);
|
| 255 |
+
}
|
| 256 |
+
return [aggregate.alias, rows.length];
|
| 257 |
+
}))];
|
| 258 |
+
}
|
| 259 |
+
for (const order of [...query.orderItems].reverse()) {
|
| 260 |
+
rows.sort((a, b) => (a[order.field] === b[order.field] ? 0 : a[order.field] > b[order.field] ? 1 : -1) * (String(order.direction).toLowerCase() === "desc" ? -1 : 1));
|
| 261 |
+
}
|
| 262 |
+
const start = query.offsetValue || 0;
|
| 263 |
+
rows = rows.slice(start, start + query.limitValue);
|
| 264 |
+
for (const relation of (query.relations || []) as any[]) {
|
| 265 |
+
const localValues = new Set(rows.map((row: any) => row[relation.localKey || "id"]));
|
| 266 |
+
const relatedRows = (await this.executeQuery(relation.query)).filter(
|
| 267 |
+
(row: any) => localValues.has(row[relation.foreignKey || "id"]));
|
| 268 |
+
for (const row of rows) {
|
| 269 |
+
const matches = relatedRows.filter(
|
| 270 |
+
(related: any) => related[relation.foreignKey || "id"] === row[relation.localKey || "id"]);
|
| 271 |
+
row[relation.name] = relation.many === false ? matches[0] : matches;
|
| 272 |
+
}
|
| 273 |
+
}
|
| 274 |
+
if (query.selectItems.length > 0) {
|
| 275 |
+
const selections = new Set(query.selectItems);
|
| 276 |
+
for (const relation of (query.relations || []) as any[]) selections.add(relation.name);
|
| 277 |
+
rows = rows.map((row: any) => Object.fromEntries(
|
| 278 |
+
Object.entries(row).filter(([field]) => selections.has(field))));
|
| 279 |
+
}
|
| 280 |
+
return rows;
|
| 281 |
+
}
|
| 282 |
+
async executeCount(query: any, countAlias?: string, operation?: QueryOperation): Promise<number> {
|
| 283 |
+
if (typeof query?.forExactCount !== "function") {
|
| 284 |
+
throw new Error("TeaQL exact count requires the formal runtime SelectQuery");
|
| 285 |
+
}
|
| 286 |
+
const alias = countAlias ?? "__teaql_total";
|
| 287 |
+
const request = new QueryRequest(query).deriveOperation(query.forExactCount(alias), operation ?? {
|
| 288 |
+
kind: "named-count", ...(countAlias === undefined ? {} : { alias: countAlias }) });
|
| 289 |
+
const rows = await this.executeQuery(request.query);
|
| 290 |
+
const value = rows[0]?.[alias];
|
| 291 |
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
| 292 |
+
throw new Error(`TeaQL provider did not return exact count alias ${alias}`);
|
| 293 |
+
}
|
| 294 |
+
return value;
|
| 295 |
+
}
|
| 296 |
+
async *executeForStream(query: any, chunkSize = 1000): AsyncIterable<any[]> {
|
| 297 |
+
if (!Number.isInteger(chunkSize) || chunkSize <= 0) throw new Error("stream chunk size must be a positive integer");
|
| 298 |
+
const rows = await this.executeQuery(query);
|
| 299 |
+
for (let offset = 0; offset < rows.length; offset += chunkSize) {
|
| 300 |
+
yield rows.slice(offset, offset + chunkSize);
|
| 301 |
+
}
|
| 302 |
+
}
|
| 303 |
+
}
|
| 304 |
+
|
| 305 |
+
declare const require: any;
|
| 306 |
+
|
| 307 |
+
export function eq(a: any, b: any) { return {type: 'eq', field: a, value: b}; }
|
| 308 |
+
export function contain(a: any, b: any) { return {type: 'contain', field: a, value: b}; }
|
source/teaql-ts/examples/trace-chain/lib/teaql-i18n.json
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"schema": "teaql.i18n/v1",
|
| 3 |
+
"defaultLocale": "en",
|
| 4 |
+
"locales": {
|
| 5 |
+
"de": {
|
| 6 |
+
"vocabulary": {
|
| 7 |
+
},
|
| 8 |
+
"messages": {
|
| 9 |
+
}
|
| 10 |
+
},
|
| 11 |
+
"ko": {
|
| 12 |
+
"vocabulary": {
|
| 13 |
+
},
|
| 14 |
+
"messages": {
|
| 15 |
+
}
|
| 16 |
+
},
|
| 17 |
+
"pt": {
|
| 18 |
+
"vocabulary": {
|
| 19 |
+
},
|
| 20 |
+
"messages": {
|
| 21 |
+
}
|
| 22 |
+
},
|
| 23 |
+
"zh-TW": {
|
| 24 |
+
"vocabulary": {
|
| 25 |
+
},
|
| 26 |
+
"messages": {
|
| 27 |
+
}
|
| 28 |
+
},
|
| 29 |
+
"fil": {
|
| 30 |
+
"vocabulary": {
|
| 31 |
+
},
|
| 32 |
+
"messages": {
|
| 33 |
+
}
|
| 34 |
+
},
|
| 35 |
+
"en": {
|
| 36 |
+
"vocabulary": {
|
| 37 |
+
"property.platform.name": "Name",
|
| 38 |
+
"property.shipment.version": "Version",
|
| 39 |
+
"property.customerOrder.orderNumber": "Order Number",
|
| 40 |
+
"property.orderItem.id": "Id",
|
| 41 |
+
"property.shipment.referenceCode": "Reference Code",
|
| 42 |
+
"property.customerOrder.description": "Description",
|
| 43 |
+
"entity.orderItem": "Order Item",
|
| 44 |
+
"property.orderItem.customerOrder": "Customer Order",
|
| 45 |
+
"property.orderItem.name": "Name",
|
| 46 |
+
"entity.customerOrder": "Customer Order",
|
| 47 |
+
"property.payment.customerOrder": "Customer Order",
|
| 48 |
+
"property.customerOrder.id": "Id",
|
| 49 |
+
"property.paymentAttempt.version": "Version",
|
| 50 |
+
"property.payment.version": "Version",
|
| 51 |
+
"property.shipment.customerOrder": "Customer Order",
|
| 52 |
+
"property.paymentAttempt.id": "Id",
|
| 53 |
+
"property.customerOrder.version": "Version",
|
| 54 |
+
"property.payment.id": "Id",
|
| 55 |
+
"entity.platform": "Platform",
|
| 56 |
+
"property.platform.id": "Id",
|
| 57 |
+
"property.customerOrder.platform": "Platform",
|
| 58 |
+
"entity.payment": "Payment",
|
| 59 |
+
"property.shipment.id": "Id",
|
| 60 |
+
"property.payment.referenceCode": "Reference Code",
|
| 61 |
+
"property.paymentAttempt.referenceCode": "Reference Code",
|
| 62 |
+
"entity.shipment": "Shipment",
|
| 63 |
+
"property.orderItem.version": "Version",
|
| 64 |
+
"property.platform.version": "Version",
|
| 65 |
+
"property.paymentAttempt.payment": "Payment",
|
| 66 |
+
"entity.paymentAttempt": "Payment Attempt"
|
| 67 |
+
},
|
| 68 |
+
"messages": {
|
| 69 |
+
}
|
| 70 |
+
},
|
| 71 |
+
"fr": {
|
| 72 |
+
"vocabulary": {
|
| 73 |
+
},
|
| 74 |
+
"messages": {
|
| 75 |
+
}
|
| 76 |
+
},
|
| 77 |
+
"zh-CN": {
|
| 78 |
+
"vocabulary": {
|
| 79 |
+
},
|
| 80 |
+
"messages": {
|
| 81 |
+
}
|
| 82 |
+
},
|
| 83 |
+
"es": {
|
| 84 |
+
"vocabulary": {
|
| 85 |
+
},
|
| 86 |
+
"messages": {
|
| 87 |
+
}
|
| 88 |
+
},
|
| 89 |
+
"ar": {
|
| 90 |
+
"vocabulary": {
|
| 91 |
+
},
|
| 92 |
+
"messages": {
|
| 93 |
+
}
|
| 94 |
+
},
|
| 95 |
+
"vi": {
|
| 96 |
+
"vocabulary": {
|
| 97 |
+
},
|
| 98 |
+
"messages": {
|
| 99 |
+
}
|
| 100 |
+
},
|
| 101 |
+
"th": {
|
| 102 |
+
"vocabulary": {
|
| 103 |
+
},
|
| 104 |
+
"messages": {
|
| 105 |
+
}
|
| 106 |
+
},
|
| 107 |
+
"uk": {
|
| 108 |
+
"vocabulary": {
|
| 109 |
+
},
|
| 110 |
+
"messages": {
|
| 111 |
+
}
|
| 112 |
+
},
|
| 113 |
+
"ja": {
|
| 114 |
+
"vocabulary": {
|
| 115 |
+
},
|
| 116 |
+
"messages": {
|
| 117 |
+
}
|
| 118 |
+
},
|
| 119 |
+
"id": {
|
| 120 |
+
"vocabulary": {
|
| 121 |
+
},
|
| 122 |
+
"messages": {
|
| 123 |
+
}
|
| 124 |
+
}
|
| 125 |
+
}
|
| 126 |
+
}
|
source/teaql-ts/examples/trace-chain/lib/tsconfig.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"compilerOptions": {
|
| 3 |
+
"target": "es2022",
|
| 4 |
+
"module": "commonjs",
|
| 5 |
+
"strict": true,
|
| 6 |
+
"esModuleInterop": true,
|
| 7 |
+
"skipLibCheck": true,
|
| 8 |
+
"forceConsistentCasingInFileNames": true,
|
| 9 |
+
"declaration": true
|
| 10 |
+
},
|
| 11 |
+
"include": ["src/**/*", "*.d.ts"]
|
| 12 |
+
}
|
source/teaql-ts/examples/trace-chain/model.xml
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
| 2 |
+
<root name="trace-chain-service" org="teaql" data_service="sqlite"
|
| 3 |
+
teaql_typescript_version="0.2.10" _module_key="root">
|
| 4 |
+
<platform _name="Platform" _module="Trace Chain" _module_key="trace-chain"
|
| 5 |
+
name="Trace Chain Verification"/>
|
| 6 |
+
<customer_order _name="Customer Order" _module="Trace Chain" _module_key="trace-chain"
|
| 7 |
+
platform="platform()" order_number="TRACE-ORDER-001"
|
| 8 |
+
description="Draft order"/>
|
| 9 |
+
<order_item _name="Order Item" _module="Trace Chain" _module_key="trace-chain"
|
| 10 |
+
customer_order="customer_order()" name="Available item" _audit_mask_fields="name"/>
|
| 11 |
+
<payment _name="Payment" _module="Trace Chain" _module_key="trace-chain"
|
| 12 |
+
customer_order="customer_order()" reference_code="TRACE-PAYMENT-001"/>
|
| 13 |
+
<payment_attempt _name="Payment Attempt" _module="Trace Chain" _module_key="trace-chain"
|
| 14 |
+
payment="payment()" reference_code="TRACE-ATTEMPT-001"/>
|
| 15 |
+
<shipment _name="Shipment" _module="Trace Chain" _module_key="trace-chain"
|
| 16 |
+
customer_order="customer_order()" reference_code="TRACE-SHIPMENT-001"/>
|
| 17 |
+
</root>
|
source/teaql-ts/examples/trace-chain/package-lock.json
ADDED
|
@@ -0,0 +1,826 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "teaql-typescript-trace-chain-example",
|
| 3 |
+
"lockfileVersion": 3,
|
| 4 |
+
"requires": true,
|
| 5 |
+
"packages": {
|
| 6 |
+
"": {
|
| 7 |
+
"name": "teaql-typescript-trace-chain-example",
|
| 8 |
+
"dependencies": {
|
| 9 |
+
"better-sqlite3": "^12.10.0",
|
| 10 |
+
"teaql-ts": "file:../.."
|
| 11 |
+
},
|
| 12 |
+
"devDependencies": {
|
| 13 |
+
"@types/better-sqlite3": "^7.6.12",
|
| 14 |
+
"@types/node": "^22.0.0",
|
| 15 |
+
"ts-node": "^10.9.2",
|
| 16 |
+
"typescript": "5.4.5"
|
| 17 |
+
}
|
| 18 |
+
},
|
| 19 |
+
"../..": {
|
| 20 |
+
"name": "@teaql/teaql",
|
| 21 |
+
"version": "0.3.1",
|
| 22 |
+
"license": "Apache-2.0",
|
| 23 |
+
"dependencies": {
|
| 24 |
+
"node-fetch": "^2.7.0"
|
| 25 |
+
},
|
| 26 |
+
"devDependencies": {
|
| 27 |
+
"@aws-sdk/client-s3": "3.1151.0",
|
| 28 |
+
"@aws-sdk/s3-request-presigner": "3.1151.0",
|
| 29 |
+
"@opentelemetry/api-logs": "^0.221.0",
|
| 30 |
+
"@opentelemetry/context-async-hooks": "^2.10.0",
|
| 31 |
+
"@opentelemetry/core": "^2.10.0",
|
| 32 |
+
"@opentelemetry/exporter-logs-otlp-http": "^0.221.0",
|
| 33 |
+
"@opentelemetry/exporter-metrics-otlp-http": "^0.221.0",
|
| 34 |
+
"@opentelemetry/exporter-trace-otlp-http": "^0.221.0",
|
| 35 |
+
"@opentelemetry/otlp-transformer": "0.221.0",
|
| 36 |
+
"@opentelemetry/resources": "^2.10.0",
|
| 37 |
+
"@opentelemetry/sdk-logs": "^0.221.0",
|
| 38 |
+
"@opentelemetry/sdk-metrics": "^2.10.0",
|
| 39 |
+
"@opentelemetry/sdk-trace-base": "^2.10.0",
|
| 40 |
+
"@sqlite.org/sqlite-wasm": "3.53.0-build1",
|
| 41 |
+
"@types/better-sqlite3": "^7.6.12",
|
| 42 |
+
"@types/jest": "^29.5.0",
|
| 43 |
+
"@types/node-fetch": "^2.6.13",
|
| 44 |
+
"@types/pg": "^8.11.0",
|
| 45 |
+
"better-sqlite3": "^12.10.0",
|
| 46 |
+
"esbuild": "^0.28.2",
|
| 47 |
+
"jest": "^29.5.0",
|
| 48 |
+
"jest-util": "^29.7.0",
|
| 49 |
+
"mysql2": "^3.11.0",
|
| 50 |
+
"peggy": "^5.1.0",
|
| 51 |
+
"pg": "^8.12.0",
|
| 52 |
+
"pg-query-stream": "^4.7.0",
|
| 53 |
+
"ts-jest": "^29.1.0",
|
| 54 |
+
"typescript": "5.4.5"
|
| 55 |
+
},
|
| 56 |
+
"peerDependencies": {
|
| 57 |
+
"@aws-sdk/client-s3": "3.1151.0",
|
| 58 |
+
"@aws-sdk/s3-request-presigner": "3.1151.0",
|
| 59 |
+
"@opentelemetry/api": "^1.9.1",
|
| 60 |
+
"@opentelemetry/api-logs": "^0.221.0",
|
| 61 |
+
"@opentelemetry/context-async-hooks": "^2.10.0",
|
| 62 |
+
"@opentelemetry/core": "^2.10.0",
|
| 63 |
+
"@opentelemetry/exporter-logs-otlp-http": "^0.221.0",
|
| 64 |
+
"@opentelemetry/exporter-metrics-otlp-http": "^0.221.0",
|
| 65 |
+
"@opentelemetry/exporter-trace-otlp-http": "^0.221.0",
|
| 66 |
+
"@opentelemetry/otlp-transformer": "0.221.0",
|
| 67 |
+
"@opentelemetry/resources": "^2.10.0",
|
| 68 |
+
"@opentelemetry/sdk-logs": "^0.221.0",
|
| 69 |
+
"@opentelemetry/sdk-metrics": "^2.10.0",
|
| 70 |
+
"@opentelemetry/sdk-trace-base": "^2.10.0",
|
| 71 |
+
"@sqlite.org/sqlite-wasm": "3.53.0-build1",
|
| 72 |
+
"better-sqlite3": "^12.10.0",
|
| 73 |
+
"expo-sqlite": "*",
|
| 74 |
+
"mysql2": "^3.11.0",
|
| 75 |
+
"pg": "^8.12.0",
|
| 76 |
+
"pg-query-stream": "^4.7.0"
|
| 77 |
+
},
|
| 78 |
+
"peerDependenciesMeta": {
|
| 79 |
+
"@aws-sdk/client-s3": {
|
| 80 |
+
"optional": true
|
| 81 |
+
},
|
| 82 |
+
"@aws-sdk/s3-request-presigner": {
|
| 83 |
+
"optional": true
|
| 84 |
+
},
|
| 85 |
+
"@opentelemetry/api": {
|
| 86 |
+
"optional": true
|
| 87 |
+
},
|
| 88 |
+
"@opentelemetry/api-logs": {
|
| 89 |
+
"optional": true
|
| 90 |
+
},
|
| 91 |
+
"@opentelemetry/context-async-hooks": {
|
| 92 |
+
"optional": true
|
| 93 |
+
},
|
| 94 |
+
"@opentelemetry/core": {
|
| 95 |
+
"optional": true
|
| 96 |
+
},
|
| 97 |
+
"@opentelemetry/exporter-logs-otlp-http": {
|
| 98 |
+
"optional": true
|
| 99 |
+
},
|
| 100 |
+
"@opentelemetry/exporter-metrics-otlp-http": {
|
| 101 |
+
"optional": true
|
| 102 |
+
},
|
| 103 |
+
"@opentelemetry/exporter-trace-otlp-http": {
|
| 104 |
+
"optional": true
|
| 105 |
+
},
|
| 106 |
+
"@opentelemetry/otlp-transformer": {
|
| 107 |
+
"optional": true
|
| 108 |
+
},
|
| 109 |
+
"@opentelemetry/resources": {
|
| 110 |
+
"optional": true
|
| 111 |
+
},
|
| 112 |
+
"@opentelemetry/sdk-logs": {
|
| 113 |
+
"optional": true
|
| 114 |
+
},
|
| 115 |
+
"@opentelemetry/sdk-metrics": {
|
| 116 |
+
"optional": true
|
| 117 |
+
},
|
| 118 |
+
"@opentelemetry/sdk-trace-base": {
|
| 119 |
+
"optional": true
|
| 120 |
+
},
|
| 121 |
+
"@sqlite.org/sqlite-wasm": {
|
| 122 |
+
"optional": true
|
| 123 |
+
},
|
| 124 |
+
"better-sqlite3": {
|
| 125 |
+
"optional": true
|
| 126 |
+
},
|
| 127 |
+
"expo-sqlite": {
|
| 128 |
+
"optional": true
|
| 129 |
+
},
|
| 130 |
+
"mysql2": {
|
| 131 |
+
"optional": true
|
| 132 |
+
},
|
| 133 |
+
"pg": {
|
| 134 |
+
"optional": true
|
| 135 |
+
},
|
| 136 |
+
"pg-query-stream": {
|
| 137 |
+
"optional": true
|
| 138 |
+
}
|
| 139 |
+
}
|
| 140 |
+
},
|
| 141 |
+
"node_modules/@cspotcode/source-map-support": {
|
| 142 |
+
"version": "0.8.1",
|
| 143 |
+
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
| 144 |
+
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
|
| 145 |
+
"dev": true,
|
| 146 |
+
"license": "MIT",
|
| 147 |
+
"dependencies": {
|
| 148 |
+
"@jridgewell/trace-mapping": "0.3.9"
|
| 149 |
+
},
|
| 150 |
+
"engines": {
|
| 151 |
+
"node": ">=12"
|
| 152 |
+
}
|
| 153 |
+
},
|
| 154 |
+
"node_modules/@jridgewell/resolve-uri": {
|
| 155 |
+
"version": "3.1.2",
|
| 156 |
+
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
| 157 |
+
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
| 158 |
+
"dev": true,
|
| 159 |
+
"license": "MIT",
|
| 160 |
+
"engines": {
|
| 161 |
+
"node": ">=6.0.0"
|
| 162 |
+
}
|
| 163 |
+
},
|
| 164 |
+
"node_modules/@jridgewell/sourcemap-codec": {
|
| 165 |
+
"version": "1.6.0",
|
| 166 |
+
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz",
|
| 167 |
+
"integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==",
|
| 168 |
+
"dev": true,
|
| 169 |
+
"license": "MIT"
|
| 170 |
+
},
|
| 171 |
+
"node_modules/@jridgewell/trace-mapping": {
|
| 172 |
+
"version": "0.3.9",
|
| 173 |
+
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
|
| 174 |
+
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
|
| 175 |
+
"dev": true,
|
| 176 |
+
"license": "MIT",
|
| 177 |
+
"dependencies": {
|
| 178 |
+
"@jridgewell/resolve-uri": "^3.0.3",
|
| 179 |
+
"@jridgewell/sourcemap-codec": "^1.4.10"
|
| 180 |
+
}
|
| 181 |
+
},
|
| 182 |
+
"node_modules/@tsconfig/node10": {
|
| 183 |
+
"version": "1.0.13",
|
| 184 |
+
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.13.tgz",
|
| 185 |
+
"integrity": "sha512-gcLdvR9HO1ZJBypsOGqaP6TFEzb6vIta0KSTLt9NAQ6pXQO3cRgSVyCN6pzYqI9DlJgY71XKO0dpDhCf08b3pg==",
|
| 186 |
+
"dev": true,
|
| 187 |
+
"license": "MIT"
|
| 188 |
+
},
|
| 189 |
+
"node_modules/@tsconfig/node12": {
|
| 190 |
+
"version": "1.0.11",
|
| 191 |
+
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
|
| 192 |
+
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
|
| 193 |
+
"dev": true,
|
| 194 |
+
"license": "MIT"
|
| 195 |
+
},
|
| 196 |
+
"node_modules/@tsconfig/node14": {
|
| 197 |
+
"version": "1.0.3",
|
| 198 |
+
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
|
| 199 |
+
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
|
| 200 |
+
"dev": true,
|
| 201 |
+
"license": "MIT"
|
| 202 |
+
},
|
| 203 |
+
"node_modules/@tsconfig/node16": {
|
| 204 |
+
"version": "1.0.4",
|
| 205 |
+
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
|
| 206 |
+
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
|
| 207 |
+
"dev": true,
|
| 208 |
+
"license": "MIT"
|
| 209 |
+
},
|
| 210 |
+
"node_modules/@types/better-sqlite3": {
|
| 211 |
+
"version": "7.6.13",
|
| 212 |
+
"resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.13.tgz",
|
| 213 |
+
"integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==",
|
| 214 |
+
"dev": true,
|
| 215 |
+
"license": "MIT",
|
| 216 |
+
"dependencies": {
|
| 217 |
+
"@types/node": "*"
|
| 218 |
+
}
|
| 219 |
+
},
|
| 220 |
+
"node_modules/@types/node": {
|
| 221 |
+
"version": "22.20.5",
|
| 222 |
+
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.5.tgz",
|
| 223 |
+
"integrity": "sha512-U2+DNr+wSjpsTS/wZGYHq7GcwfuSmKiKvoPvK22zwTlRhU91yOniN4qRR5KhIjvif7ysw/dz/hKmfDH0Ris4aA==",
|
| 224 |
+
"dev": true,
|
| 225 |
+
"license": "MIT",
|
| 226 |
+
"dependencies": {
|
| 227 |
+
"undici-types": "~6.21.0"
|
| 228 |
+
}
|
| 229 |
+
},
|
| 230 |
+
"node_modules/acorn": {
|
| 231 |
+
"version": "8.18.0",
|
| 232 |
+
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz",
|
| 233 |
+
"integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==",
|
| 234 |
+
"dev": true,
|
| 235 |
+
"license": "MIT",
|
| 236 |
+
"bin": {
|
| 237 |
+
"acorn": "bin/acorn"
|
| 238 |
+
},
|
| 239 |
+
"engines": {
|
| 240 |
+
"node": ">=0.4.0"
|
| 241 |
+
}
|
| 242 |
+
},
|
| 243 |
+
"node_modules/acorn-walk": {
|
| 244 |
+
"version": "8.3.5",
|
| 245 |
+
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz",
|
| 246 |
+
"integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==",
|
| 247 |
+
"dev": true,
|
| 248 |
+
"license": "MIT",
|
| 249 |
+
"dependencies": {
|
| 250 |
+
"acorn": "^8.11.0"
|
| 251 |
+
},
|
| 252 |
+
"engines": {
|
| 253 |
+
"node": ">=0.4.0"
|
| 254 |
+
}
|
| 255 |
+
},
|
| 256 |
+
"node_modules/arg": {
|
| 257 |
+
"version": "4.1.3",
|
| 258 |
+
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
|
| 259 |
+
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
|
| 260 |
+
"dev": true,
|
| 261 |
+
"license": "MIT"
|
| 262 |
+
},
|
| 263 |
+
"node_modules/base64-js": {
|
| 264 |
+
"version": "1.5.1",
|
| 265 |
+
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
| 266 |
+
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
| 267 |
+
"funding": [
|
| 268 |
+
{
|
| 269 |
+
"type": "github",
|
| 270 |
+
"url": "https://github.com/sponsors/feross"
|
| 271 |
+
},
|
| 272 |
+
{
|
| 273 |
+
"type": "patreon",
|
| 274 |
+
"url": "https://www.patreon.com/feross"
|
| 275 |
+
},
|
| 276 |
+
{
|
| 277 |
+
"type": "consulting",
|
| 278 |
+
"url": "https://feross.org/support"
|
| 279 |
+
}
|
| 280 |
+
],
|
| 281 |
+
"license": "MIT"
|
| 282 |
+
},
|
| 283 |
+
"node_modules/better-sqlite3": {
|
| 284 |
+
"version": "12.11.1",
|
| 285 |
+
"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.11.1.tgz",
|
| 286 |
+
"integrity": "sha512-dq9AtApgg5PGFtBzPFSBl3HZQjHok5gaQCM6zh2Yk0aSmDCs1CbnVI8/HgASQkNKsWFpseIO9beg5xxpYhbIfA==",
|
| 287 |
+
"hasInstallScript": true,
|
| 288 |
+
"license": "MIT",
|
| 289 |
+
"dependencies": {
|
| 290 |
+
"bindings": "^1.5.0",
|
| 291 |
+
"prebuild-install": "^7.1.1"
|
| 292 |
+
},
|
| 293 |
+
"engines": {
|
| 294 |
+
"node": "20.x || 22.x || 23.x || 24.x || 25.x || 26.x"
|
| 295 |
+
}
|
| 296 |
+
},
|
| 297 |
+
"node_modules/bindings": {
|
| 298 |
+
"version": "1.5.0",
|
| 299 |
+
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
| 300 |
+
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
|
| 301 |
+
"license": "MIT",
|
| 302 |
+
"dependencies": {
|
| 303 |
+
"file-uri-to-path": "1.0.0"
|
| 304 |
+
}
|
| 305 |
+
},
|
| 306 |
+
"node_modules/bl": {
|
| 307 |
+
"version": "4.1.0",
|
| 308 |
+
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
| 309 |
+
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
| 310 |
+
"license": "MIT",
|
| 311 |
+
"dependencies": {
|
| 312 |
+
"buffer": "^5.5.0",
|
| 313 |
+
"inherits": "^2.0.4",
|
| 314 |
+
"readable-stream": "^3.4.0"
|
| 315 |
+
}
|
| 316 |
+
},
|
| 317 |
+
"node_modules/buffer": {
|
| 318 |
+
"version": "5.7.1",
|
| 319 |
+
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
| 320 |
+
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
| 321 |
+
"funding": [
|
| 322 |
+
{
|
| 323 |
+
"type": "github",
|
| 324 |
+
"url": "https://github.com/sponsors/feross"
|
| 325 |
+
},
|
| 326 |
+
{
|
| 327 |
+
"type": "patreon",
|
| 328 |
+
"url": "https://www.patreon.com/feross"
|
| 329 |
+
},
|
| 330 |
+
{
|
| 331 |
+
"type": "consulting",
|
| 332 |
+
"url": "https://feross.org/support"
|
| 333 |
+
}
|
| 334 |
+
],
|
| 335 |
+
"license": "MIT",
|
| 336 |
+
"dependencies": {
|
| 337 |
+
"base64-js": "^1.3.1",
|
| 338 |
+
"ieee754": "^1.1.13"
|
| 339 |
+
}
|
| 340 |
+
},
|
| 341 |
+
"node_modules/chownr": {
|
| 342 |
+
"version": "1.1.4",
|
| 343 |
+
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
| 344 |
+
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
|
| 345 |
+
"license": "ISC"
|
| 346 |
+
},
|
| 347 |
+
"node_modules/create-require": {
|
| 348 |
+
"version": "1.1.1",
|
| 349 |
+
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
| 350 |
+
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
|
| 351 |
+
"dev": true,
|
| 352 |
+
"license": "MIT"
|
| 353 |
+
},
|
| 354 |
+
"node_modules/decompress-response": {
|
| 355 |
+
"version": "6.0.0",
|
| 356 |
+
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
|
| 357 |
+
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
|
| 358 |
+
"license": "MIT",
|
| 359 |
+
"dependencies": {
|
| 360 |
+
"mimic-response": "^3.1.0"
|
| 361 |
+
},
|
| 362 |
+
"engines": {
|
| 363 |
+
"node": ">=10"
|
| 364 |
+
},
|
| 365 |
+
"funding": {
|
| 366 |
+
"url": "https://github.com/sponsors/sindresorhus"
|
| 367 |
+
}
|
| 368 |
+
},
|
| 369 |
+
"node_modules/deep-extend": {
|
| 370 |
+
"version": "0.6.0",
|
| 371 |
+
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
| 372 |
+
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
|
| 373 |
+
"license": "MIT",
|
| 374 |
+
"engines": {
|
| 375 |
+
"node": ">=4.0.0"
|
| 376 |
+
}
|
| 377 |
+
},
|
| 378 |
+
"node_modules/detect-libc": {
|
| 379 |
+
"version": "2.1.2",
|
| 380 |
+
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
| 381 |
+
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
| 382 |
+
"license": "Apache-2.0",
|
| 383 |
+
"engines": {
|
| 384 |
+
"node": ">=8"
|
| 385 |
+
}
|
| 386 |
+
},
|
| 387 |
+
"node_modules/diff": {
|
| 388 |
+
"version": "4.0.4",
|
| 389 |
+
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz",
|
| 390 |
+
"integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==",
|
| 391 |
+
"dev": true,
|
| 392 |
+
"license": "BSD-3-Clause",
|
| 393 |
+
"engines": {
|
| 394 |
+
"node": ">=0.3.1"
|
| 395 |
+
}
|
| 396 |
+
},
|
| 397 |
+
"node_modules/end-of-stream": {
|
| 398 |
+
"version": "1.4.5",
|
| 399 |
+
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
|
| 400 |
+
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
|
| 401 |
+
"license": "MIT",
|
| 402 |
+
"dependencies": {
|
| 403 |
+
"once": "^1.4.0"
|
| 404 |
+
}
|
| 405 |
+
},
|
| 406 |
+
"node_modules/expand-template": {
|
| 407 |
+
"version": "2.0.3",
|
| 408 |
+
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
|
| 409 |
+
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
|
| 410 |
+
"license": "(MIT OR WTFPL)",
|
| 411 |
+
"engines": {
|
| 412 |
+
"node": ">=6"
|
| 413 |
+
}
|
| 414 |
+
},
|
| 415 |
+
"node_modules/file-uri-to-path": {
|
| 416 |
+
"version": "1.0.0",
|
| 417 |
+
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
| 418 |
+
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
|
| 419 |
+
"license": "MIT"
|
| 420 |
+
},
|
| 421 |
+
"node_modules/fs-constants": {
|
| 422 |
+
"version": "1.0.0",
|
| 423 |
+
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
| 424 |
+
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
| 425 |
+
"license": "MIT"
|
| 426 |
+
},
|
| 427 |
+
"node_modules/github-from-package": {
|
| 428 |
+
"version": "0.0.0",
|
| 429 |
+
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
|
| 430 |
+
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
|
| 431 |
+
"license": "MIT"
|
| 432 |
+
},
|
| 433 |
+
"node_modules/ieee754": {
|
| 434 |
+
"version": "1.2.1",
|
| 435 |
+
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
| 436 |
+
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
| 437 |
+
"funding": [
|
| 438 |
+
{
|
| 439 |
+
"type": "github",
|
| 440 |
+
"url": "https://github.com/sponsors/feross"
|
| 441 |
+
},
|
| 442 |
+
{
|
| 443 |
+
"type": "patreon",
|
| 444 |
+
"url": "https://www.patreon.com/feross"
|
| 445 |
+
},
|
| 446 |
+
{
|
| 447 |
+
"type": "consulting",
|
| 448 |
+
"url": "https://feross.org/support"
|
| 449 |
+
}
|
| 450 |
+
],
|
| 451 |
+
"license": "BSD-3-Clause"
|
| 452 |
+
},
|
| 453 |
+
"node_modules/inherits": {
|
| 454 |
+
"version": "2.0.4",
|
| 455 |
+
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
| 456 |
+
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
| 457 |
+
"license": "ISC"
|
| 458 |
+
},
|
| 459 |
+
"node_modules/ini": {
|
| 460 |
+
"version": "1.3.8",
|
| 461 |
+
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
| 462 |
+
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
|
| 463 |
+
"license": "ISC"
|
| 464 |
+
},
|
| 465 |
+
"node_modules/make-error": {
|
| 466 |
+
"version": "1.3.6",
|
| 467 |
+
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
| 468 |
+
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
|
| 469 |
+
"dev": true,
|
| 470 |
+
"license": "ISC"
|
| 471 |
+
},
|
| 472 |
+
"node_modules/mimic-response": {
|
| 473 |
+
"version": "3.1.0",
|
| 474 |
+
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
|
| 475 |
+
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
|
| 476 |
+
"license": "MIT",
|
| 477 |
+
"engines": {
|
| 478 |
+
"node": ">=10"
|
| 479 |
+
},
|
| 480 |
+
"funding": {
|
| 481 |
+
"url": "https://github.com/sponsors/sindresorhus"
|
| 482 |
+
}
|
| 483 |
+
},
|
| 484 |
+
"node_modules/minimist": {
|
| 485 |
+
"version": "1.2.8",
|
| 486 |
+
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
| 487 |
+
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
| 488 |
+
"license": "MIT",
|
| 489 |
+
"funding": {
|
| 490 |
+
"url": "https://github.com/sponsors/ljharb"
|
| 491 |
+
}
|
| 492 |
+
},
|
| 493 |
+
"node_modules/mkdirp-classic": {
|
| 494 |
+
"version": "0.5.3",
|
| 495 |
+
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
|
| 496 |
+
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
|
| 497 |
+
"license": "MIT"
|
| 498 |
+
},
|
| 499 |
+
"node_modules/napi-build-utils": {
|
| 500 |
+
"version": "2.0.0",
|
| 501 |
+
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
|
| 502 |
+
"integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
|
| 503 |
+
"license": "MIT"
|
| 504 |
+
},
|
| 505 |
+
"node_modules/node-abi": {
|
| 506 |
+
"version": "3.96.0",
|
| 507 |
+
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.96.0.tgz",
|
| 508 |
+
"integrity": "sha512-rebQ/lz7i0EkoLzUVSrKRzA69zMkwLp95kKMWoMDkkM00Suxz0D7zEQPwRml5fQum24mj7bPvmlgLAmu2JCiYg==",
|
| 509 |
+
"license": "MIT",
|
| 510 |
+
"dependencies": {
|
| 511 |
+
"semver": "^7.3.5"
|
| 512 |
+
},
|
| 513 |
+
"engines": {
|
| 514 |
+
"node": ">=10"
|
| 515 |
+
}
|
| 516 |
+
},
|
| 517 |
+
"node_modules/once": {
|
| 518 |
+
"version": "1.4.0",
|
| 519 |
+
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
| 520 |
+
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
| 521 |
+
"license": "ISC",
|
| 522 |
+
"dependencies": {
|
| 523 |
+
"wrappy": "1"
|
| 524 |
+
}
|
| 525 |
+
},
|
| 526 |
+
"node_modules/prebuild-install": {
|
| 527 |
+
"version": "7.1.3",
|
| 528 |
+
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
|
| 529 |
+
"integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
|
| 530 |
+
"deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.",
|
| 531 |
+
"license": "MIT",
|
| 532 |
+
"dependencies": {
|
| 533 |
+
"detect-libc": "^2.0.0",
|
| 534 |
+
"expand-template": "^2.0.3",
|
| 535 |
+
"github-from-package": "0.0.0",
|
| 536 |
+
"minimist": "^1.2.3",
|
| 537 |
+
"mkdirp-classic": "^0.5.3",
|
| 538 |
+
"napi-build-utils": "^2.0.0",
|
| 539 |
+
"node-abi": "^3.3.0",
|
| 540 |
+
"pump": "^3.0.0",
|
| 541 |
+
"rc": "^1.2.7",
|
| 542 |
+
"simple-get": "^4.0.0",
|
| 543 |
+
"tar-fs": "^2.0.0",
|
| 544 |
+
"tunnel-agent": "^0.6.0"
|
| 545 |
+
},
|
| 546 |
+
"bin": {
|
| 547 |
+
"prebuild-install": "bin.js"
|
| 548 |
+
},
|
| 549 |
+
"engines": {
|
| 550 |
+
"node": ">=10"
|
| 551 |
+
}
|
| 552 |
+
},
|
| 553 |
+
"node_modules/pump": {
|
| 554 |
+
"version": "3.0.4",
|
| 555 |
+
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
|
| 556 |
+
"integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
|
| 557 |
+
"license": "MIT",
|
| 558 |
+
"dependencies": {
|
| 559 |
+
"end-of-stream": "^1.1.0",
|
| 560 |
+
"once": "^1.3.1"
|
| 561 |
+
}
|
| 562 |
+
},
|
| 563 |
+
"node_modules/rc": {
|
| 564 |
+
"version": "1.2.8",
|
| 565 |
+
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
|
| 566 |
+
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
|
| 567 |
+
"license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
|
| 568 |
+
"dependencies": {
|
| 569 |
+
"deep-extend": "^0.6.0",
|
| 570 |
+
"ini": "~1.3.0",
|
| 571 |
+
"minimist": "^1.2.0",
|
| 572 |
+
"strip-json-comments": "~2.0.1"
|
| 573 |
+
},
|
| 574 |
+
"bin": {
|
| 575 |
+
"rc": "cli.js"
|
| 576 |
+
}
|
| 577 |
+
},
|
| 578 |
+
"node_modules/readable-stream": {
|
| 579 |
+
"version": "3.6.2",
|
| 580 |
+
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
| 581 |
+
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
| 582 |
+
"license": "MIT",
|
| 583 |
+
"dependencies": {
|
| 584 |
+
"inherits": "^2.0.3",
|
| 585 |
+
"string_decoder": "^1.1.1",
|
| 586 |
+
"util-deprecate": "^1.0.1"
|
| 587 |
+
},
|
| 588 |
+
"engines": {
|
| 589 |
+
"node": ">= 6"
|
| 590 |
+
}
|
| 591 |
+
},
|
| 592 |
+
"node_modules/safe-buffer": {
|
| 593 |
+
"version": "5.2.1",
|
| 594 |
+
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
| 595 |
+
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
| 596 |
+
"funding": [
|
| 597 |
+
{
|
| 598 |
+
"type": "github",
|
| 599 |
+
"url": "https://github.com/sponsors/feross"
|
| 600 |
+
},
|
| 601 |
+
{
|
| 602 |
+
"type": "patreon",
|
| 603 |
+
"url": "https://www.patreon.com/feross"
|
| 604 |
+
},
|
| 605 |
+
{
|
| 606 |
+
"type": "consulting",
|
| 607 |
+
"url": "https://feross.org/support"
|
| 608 |
+
}
|
| 609 |
+
],
|
| 610 |
+
"license": "MIT"
|
| 611 |
+
},
|
| 612 |
+
"node_modules/semver": {
|
| 613 |
+
"version": "7.8.5",
|
| 614 |
+
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
|
| 615 |
+
"integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
|
| 616 |
+
"license": "ISC",
|
| 617 |
+
"bin": {
|
| 618 |
+
"semver": "bin/semver.js"
|
| 619 |
+
},
|
| 620 |
+
"engines": {
|
| 621 |
+
"node": ">=10"
|
| 622 |
+
}
|
| 623 |
+
},
|
| 624 |
+
"node_modules/simple-concat": {
|
| 625 |
+
"version": "1.0.1",
|
| 626 |
+
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
|
| 627 |
+
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
|
| 628 |
+
"funding": [
|
| 629 |
+
{
|
| 630 |
+
"type": "github",
|
| 631 |
+
"url": "https://github.com/sponsors/feross"
|
| 632 |
+
},
|
| 633 |
+
{
|
| 634 |
+
"type": "patreon",
|
| 635 |
+
"url": "https://www.patreon.com/feross"
|
| 636 |
+
},
|
| 637 |
+
{
|
| 638 |
+
"type": "consulting",
|
| 639 |
+
"url": "https://feross.org/support"
|
| 640 |
+
}
|
| 641 |
+
],
|
| 642 |
+
"license": "MIT"
|
| 643 |
+
},
|
| 644 |
+
"node_modules/simple-get": {
|
| 645 |
+
"version": "4.0.1",
|
| 646 |
+
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
|
| 647 |
+
"integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
|
| 648 |
+
"funding": [
|
| 649 |
+
{
|
| 650 |
+
"type": "github",
|
| 651 |
+
"url": "https://github.com/sponsors/feross"
|
| 652 |
+
},
|
| 653 |
+
{
|
| 654 |
+
"type": "patreon",
|
| 655 |
+
"url": "https://www.patreon.com/feross"
|
| 656 |
+
},
|
| 657 |
+
{
|
| 658 |
+
"type": "consulting",
|
| 659 |
+
"url": "https://feross.org/support"
|
| 660 |
+
}
|
| 661 |
+
],
|
| 662 |
+
"license": "MIT",
|
| 663 |
+
"dependencies": {
|
| 664 |
+
"decompress-response": "^6.0.0",
|
| 665 |
+
"once": "^1.3.1",
|
| 666 |
+
"simple-concat": "^1.0.0"
|
| 667 |
+
}
|
| 668 |
+
},
|
| 669 |
+
"node_modules/string_decoder": {
|
| 670 |
+
"version": "1.3.0",
|
| 671 |
+
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
| 672 |
+
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
| 673 |
+
"license": "MIT",
|
| 674 |
+
"dependencies": {
|
| 675 |
+
"safe-buffer": "~5.2.0"
|
| 676 |
+
}
|
| 677 |
+
},
|
| 678 |
+
"node_modules/strip-json-comments": {
|
| 679 |
+
"version": "2.0.1",
|
| 680 |
+
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
| 681 |
+
"integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
|
| 682 |
+
"license": "MIT",
|
| 683 |
+
"engines": {
|
| 684 |
+
"node": ">=0.10.0"
|
| 685 |
+
}
|
| 686 |
+
},
|
| 687 |
+
"node_modules/tar-fs": {
|
| 688 |
+
"version": "2.1.5",
|
| 689 |
+
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz",
|
| 690 |
+
"integrity": "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==",
|
| 691 |
+
"license": "MIT",
|
| 692 |
+
"dependencies": {
|
| 693 |
+
"chownr": "^1.1.1",
|
| 694 |
+
"mkdirp-classic": "^0.5.2",
|
| 695 |
+
"pump": "^3.0.0",
|
| 696 |
+
"tar-stream": "^2.1.4"
|
| 697 |
+
}
|
| 698 |
+
},
|
| 699 |
+
"node_modules/tar-stream": {
|
| 700 |
+
"version": "2.2.0",
|
| 701 |
+
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
| 702 |
+
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
| 703 |
+
"license": "MIT",
|
| 704 |
+
"dependencies": {
|
| 705 |
+
"bl": "^4.0.3",
|
| 706 |
+
"end-of-stream": "^1.4.1",
|
| 707 |
+
"fs-constants": "^1.0.0",
|
| 708 |
+
"inherits": "^2.0.3",
|
| 709 |
+
"readable-stream": "^3.1.1"
|
| 710 |
+
},
|
| 711 |
+
"engines": {
|
| 712 |
+
"node": ">=6"
|
| 713 |
+
}
|
| 714 |
+
},
|
| 715 |
+
"node_modules/teaql-ts": {
|
| 716 |
+
"resolved": "../..",
|
| 717 |
+
"link": true
|
| 718 |
+
},
|
| 719 |
+
"node_modules/ts-node": {
|
| 720 |
+
"version": "10.9.2",
|
| 721 |
+
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
| 722 |
+
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
|
| 723 |
+
"dev": true,
|
| 724 |
+
"license": "MIT",
|
| 725 |
+
"dependencies": {
|
| 726 |
+
"@cspotcode/source-map-support": "^0.8.0",
|
| 727 |
+
"@tsconfig/node10": "^1.0.7",
|
| 728 |
+
"@tsconfig/node12": "^1.0.7",
|
| 729 |
+
"@tsconfig/node14": "^1.0.0",
|
| 730 |
+
"@tsconfig/node16": "^1.0.2",
|
| 731 |
+
"acorn": "^8.4.1",
|
| 732 |
+
"acorn-walk": "^8.1.1",
|
| 733 |
+
"arg": "^4.1.0",
|
| 734 |
+
"create-require": "^1.1.0",
|
| 735 |
+
"diff": "^4.0.1",
|
| 736 |
+
"make-error": "^1.1.1",
|
| 737 |
+
"v8-compile-cache-lib": "^3.0.1",
|
| 738 |
+
"yn": "3.1.1"
|
| 739 |
+
},
|
| 740 |
+
"bin": {
|
| 741 |
+
"ts-node": "dist/bin.js",
|
| 742 |
+
"ts-node-cwd": "dist/bin-cwd.js",
|
| 743 |
+
"ts-node-esm": "dist/bin-esm.js",
|
| 744 |
+
"ts-node-script": "dist/bin-script.js",
|
| 745 |
+
"ts-node-transpile-only": "dist/bin-transpile.js",
|
| 746 |
+
"ts-script": "dist/bin-script-deprecated.js"
|
| 747 |
+
},
|
| 748 |
+
"peerDependencies": {
|
| 749 |
+
"@swc/core": ">=1.2.50",
|
| 750 |
+
"@swc/wasm": ">=1.2.50",
|
| 751 |
+
"@types/node": "*",
|
| 752 |
+
"typescript": ">=2.7"
|
| 753 |
+
},
|
| 754 |
+
"peerDependenciesMeta": {
|
| 755 |
+
"@swc/core": {
|
| 756 |
+
"optional": true
|
| 757 |
+
},
|
| 758 |
+
"@swc/wasm": {
|
| 759 |
+
"optional": true
|
| 760 |
+
}
|
| 761 |
+
}
|
| 762 |
+
},
|
| 763 |
+
"node_modules/tunnel-agent": {
|
| 764 |
+
"version": "0.6.0",
|
| 765 |
+
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
| 766 |
+
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
|
| 767 |
+
"license": "Apache-2.0",
|
| 768 |
+
"dependencies": {
|
| 769 |
+
"safe-buffer": "^5.0.1"
|
| 770 |
+
},
|
| 771 |
+
"engines": {
|
| 772 |
+
"node": "*"
|
| 773 |
+
}
|
| 774 |
+
},
|
| 775 |
+
"node_modules/typescript": {
|
| 776 |
+
"version": "5.4.5",
|
| 777 |
+
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
|
| 778 |
+
"integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
|
| 779 |
+
"dev": true,
|
| 780 |
+
"license": "Apache-2.0",
|
| 781 |
+
"bin": {
|
| 782 |
+
"tsc": "bin/tsc",
|
| 783 |
+
"tsserver": "bin/tsserver"
|
| 784 |
+
},
|
| 785 |
+
"engines": {
|
| 786 |
+
"node": ">=14.17"
|
| 787 |
+
}
|
| 788 |
+
},
|
| 789 |
+
"node_modules/undici-types": {
|
| 790 |
+
"version": "6.21.0",
|
| 791 |
+
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
| 792 |
+
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
| 793 |
+
"dev": true,
|
| 794 |
+
"license": "MIT"
|
| 795 |
+
},
|
| 796 |
+
"node_modules/util-deprecate": {
|
| 797 |
+
"version": "1.0.2",
|
| 798 |
+
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
| 799 |
+
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
| 800 |
+
"license": "MIT"
|
| 801 |
+
},
|
| 802 |
+
"node_modules/v8-compile-cache-lib": {
|
| 803 |
+
"version": "3.0.1",
|
| 804 |
+
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
|
| 805 |
+
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
|
| 806 |
+
"dev": true,
|
| 807 |
+
"license": "MIT"
|
| 808 |
+
},
|
| 809 |
+
"node_modules/wrappy": {
|
| 810 |
+
"version": "1.0.2",
|
| 811 |
+
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
| 812 |
+
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
| 813 |
+
"license": "ISC"
|
| 814 |
+
},
|
| 815 |
+
"node_modules/yn": {
|
| 816 |
+
"version": "3.1.1",
|
| 817 |
+
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
|
| 818 |
+
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
|
| 819 |
+
"dev": true,
|
| 820 |
+
"license": "MIT",
|
| 821 |
+
"engines": {
|
| 822 |
+
"node": ">=6"
|
| 823 |
+
}
|
| 824 |
+
}
|
| 825 |
+
}
|
| 826 |
+
}
|
source/teaql-ts/examples/trace-chain/package.json
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "teaql-typescript-trace-chain-example",
|
| 3 |
+
"private": true,
|
| 4 |
+
"scripts": { "build": "tsc --noEmit", "start": "ts-node app.ts", "test:shared-reference": "ts-node shared-reference.ts", "test:page": "ts-node paging.ts", "test:stream-capture": "ts-node stream-capture.ts", "test:relation-aggregate": "ts-node relation-aggregate.ts", "test:checker-overlap": "ts-node checker-overlap.ts", "test:plan-item-lineage": "ts-node plan-item-lineage.ts", "test:bootstrap-intent": "ts-node bootstrap-intent.ts", "test:standard-telemetry": "ts-node standard-telemetry.ts", "test:standard-telemetry-graph": "ts-node standard-telemetry-graph.ts" },
|
| 5 |
+
"dependencies": { "teaql-ts": "file:../..", "better-sqlite3": "^12.10.0" },
|
| 6 |
+
"devDependencies": { "typescript": "5.4.5", "ts-node": "^10.9.2", "@types/node": "^22.0.0", "@types/better-sqlite3": "^7.6.12" }
|
| 7 |
+
}
|
source/teaql-ts/examples/trace-chain/paging.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import assert from 'node:assert/strict';
|
| 2 |
+
import { randomUUID, createHash } from 'node:crypto';
|
| 3 |
+
import { mkdirSync, readFileSync, readdirSync } from 'node:fs';
|
| 4 |
+
import { dirname, join, resolve } from 'node:path';
|
| 5 |
+
import { EntityRoot, SelectQuery, UserContext } from 'teaql-ts';
|
| 6 |
+
import { AbstractSQLTeaQLClient, SQLExecutionEvidenceStore } from 'teaql-ts/sql/core';
|
| 7 |
+
import { SQLiteDriver } from 'teaql-ts/sql/sqlite';
|
| 8 |
+
import { Q } from './lib/src/generated/Q';
|
| 9 |
+
import { E } from './lib/src/generated/E';
|
| 10 |
+
import { GENERATED_RUNTIME_MODULE } from './lib/src/runtime-module';
|
| 11 |
+
|
| 12 |
+
function manifest(directory: string, prefix = ''): string {
|
| 13 |
+
return readdirSync(directory,{withFileTypes:true}).sort((a,b)=>a.name.localeCompare(b.name))
|
| 14 |
+
.map(entry=>entry.isDirectory()?manifest(join(directory,entry.name),`${prefix}${entry.name}/`)
|
| 15 |
+
:`${createHash('sha256').update(readFileSync(join(directory,entry.name))).digest('hex')} ${prefix}${entry.name}\n`).join('');
|
| 16 |
+
}
|
| 17 |
+
class Client extends AbstractSQLTeaQLClient {
|
| 18 |
+
constructor(driver:SQLiteDriver){super(driver,GENERATED_RUNTIME_MODULE.schemas);}
|
| 19 |
+
}
|
| 20 |
+
class Context extends UserContext {
|
| 21 |
+
allowed?:string[];
|
| 22 |
+
calls=0;
|
| 23 |
+
override prepareQuery(query:SelectQuery):SelectQuery {
|
| 24 |
+
this.calls++;
|
| 25 |
+
const prepared=super.prepareQuery(query);
|
| 26 |
+
if(this.allowed && prepared.entity==='CustomerOrder') prepared.filter({$and:[prepared.filterCondition,{id:{$in:this.allowed}}]});
|
| 27 |
+
return prepared;
|
| 28 |
+
}
|
| 29 |
+
}
|
| 30 |
+
const ledger=(entity:unknown)=>(entity as {_root:EntityRoot})._root;
|
| 31 |
+
async function main() {
|
| 32 |
+
const before=manifest('lib');
|
| 33 |
+
const database=resolve(process.env.TEAQL_TRACE_CHAIN_PAGE_DB??'.local/paging.sqlite');
|
| 34 |
+
mkdirSync(dirname(database),{recursive:true});
|
| 35 |
+
const client=new Client(new SQLiteDriver(database)).install(GENERATED_RUNTIME_MODULE).setDiagnosticSQLLogSink(undefined);
|
| 36 |
+
const context=new Context().insertResource('dataService',client);
|
| 37 |
+
const sql=new SQLExecutionEvidenceStore();
|
| 38 |
+
const audits:Readonly<Record<string,unknown>>[]=[];
|
| 39 |
+
client.setRuntimeTelemetrySink(sql).setAuditSink(event=>{audits.push(event);});
|
| 40 |
+
const failures:unknown[]=[];
|
| 41 |
+
try {
|
| 42 |
+
await context.ensureSchema(); await context.ensureSchema();
|
| 43 |
+
for(const mode of ['page','scope','list','stream']) {
|
| 44 |
+
try {
|
| 45 |
+
context.allowed=undefined;
|
| 46 |
+
const group=`VISIBLE-PAGE-${randomUUID()}`;
|
| 47 |
+
const privateName='PRIVATE-TS-PAGE-CHILD-CANARY';
|
| 48 |
+
const ids:string[]=[];
|
| 49 |
+
for(let i=0;i<(mode==='scope'?4:3);i++) {
|
| 50 |
+
const root=Q.customerOrders().comment('initialize page root').purpose('verify page isolation').newEntity(context)
|
| 51 |
+
.updatePlatform('1').updateOrderNumber(`${group}-${i}`).updateDescription(group);
|
| 52 |
+
root.orderItemList().push(Q.orderItems().comment('initialize page child').purpose('verify page isolation').newEntity(context).updateName(privateName));
|
| 53 |
+
await root.auditAs('seed page graph').save(context); ids.push(root.id!);
|
| 54 |
+
}
|
| 55 |
+
const paged=mode==='page'||mode==='scope';
|
| 56 |
+
if(mode==='scope')context.allowed=ids.slice(0,3);
|
| 57 |
+
if(!paged)context.allowed=ids.slice(1,3);
|
| 58 |
+
sql.enableAll();audits.length=0;context.calls=0;
|
| 59 |
+
const request=Q.customerOrders().withDescriptionIs(group)
|
| 60 |
+
.selectOrderItemListWith(Q.orderItems().withNameIs(privateName).limit(2))
|
| 61 |
+
.orderByIdAscending().limit(3).comment(`inspect ${privateName} ${group}`);
|
| 62 |
+
let page;
|
| 63 |
+
if(paged)page=await request.offset(1).limit(2).count()
|
| 64 |
+
.purpose(`verify ${privateName} ${group}`).executeForList(context);
|
| 65 |
+
else {
|
| 66 |
+
const executable=request.purpose(`verify ${privateName} ${group}`);
|
| 67 |
+
const data=mode==='list'?Array.from(await executable.executeForList(context)):[];
|
| 68 |
+
if(mode==='stream')for await(const entity of executable.executeForStream(context,1))data.push(entity);
|
| 69 |
+
page={data,totalCount:undefined};
|
| 70 |
+
}
|
| 71 |
+
assert.equal(page.totalCount,paged?3:undefined,'count and data must use the same Context-scoped request');
|
| 72 |
+
assert.equal(context.calls,1,'prepare Context once for count and rows');
|
| 73 |
+
const rows=Array.from(page.data);
|
| 74 |
+
assert.deepEqual(rows.map(row=>E.customerOrder(row).id().eval()),ids.slice(1,3));
|
| 75 |
+
assert.notEqual(ledger(rows[0]),ledger(rows[1]),'page roots need independent mutation ownership');
|
| 76 |
+
const childIDs=rows.map((row,i)=>{
|
| 77 |
+
assert.equal(row.orderItemList().length,1);
|
| 78 |
+
const child=row.orderItemList()[0];
|
| 79 |
+
assert.equal(ledger(row),ledger(child),'owned child must join only its parent graph');
|
| 80 |
+
assert.equal(E.orderItem(child).name().eval(),privateName);
|
| 81 |
+
assert.equal(E.orderItem(child).customerOrderId().eval(),ids[i+1]);
|
| 82 |
+
return child.id!;
|
| 83 |
+
});
|
| 84 |
+
const statements=sql.snapshot();
|
| 85 |
+
assert.equal(statements.filter(entry=>entry.traceChain?.some(node=>
|
| 86 |
+
node.kind==='comment' && node.detail==='count()')).length,paged?1:0,
|
| 87 |
+
'only explicit count() creates the total query; no retired page-route alias');
|
| 88 |
+
assert.equal(statements.length,paged?4:3,'only count (if requested), root and two SQLite child probes execute');
|
| 89 |
+
assert(!JSON.stringify(statements).includes(privateName),'page/count/relation logs must mask child source');
|
| 90 |
+
for(const entry of statements){
|
| 91 |
+
assert(entry.comment?.includes(group));assert(entry.purpose?.includes(group));
|
| 92 |
+
assert.equal(entry.tracePath[0].name,'CustomerOrder');
|
| 93 |
+
assert.equal(entry.tracePath[entry.tracePath.length-1].kind,'sql');
|
| 94 |
+
}
|
| 95 |
+
context.allowed=undefined;
|
| 96 |
+
rows.forEach((row,i)=>{
|
| 97 |
+
row.updateDescription(`${group}-saved-${i}`);
|
| 98 |
+
row.orderItemList()[0].updateName(`saved child ${i}`).auditAs(`edit page child ${i}`);
|
| 99 |
+
});
|
| 100 |
+
for(let i=0;i<2;i++) {
|
| 101 |
+
audits.length=0;sql.enableAll();
|
| 102 |
+
const reason=`save independent page ${i}`;
|
| 103 |
+
await rows[i].auditAs(reason).save(context);
|
| 104 |
+
assert.equal(audits.length,2,'only owning root and child commit');
|
| 105 |
+
for(const event of audits)assert.equal((event.mutationLineage as any[])[0].detail,reason);
|
| 106 |
+
for(let j=0;j<2;j++) {
|
| 107 |
+
const reloaded=await Q.customerOrders().withIdIs(ids[j+1]).selectOrderItemListWith(Q.orderItems().limit(2)).limit(1)
|
| 108 |
+
.comment('reload page graph').purpose('verify independent persistence').executeForList(context);
|
| 109 |
+
const root=reloaded[0],child=root.orderItemList()[0];
|
| 110 |
+
assert.equal(E.customerOrder(root).description().eval(),j<=i?`${group}-saved-${j}`:group);
|
| 111 |
+
assert.equal(E.customerOrder(root).version().eval(),j<=i?2:1);
|
| 112 |
+
assert.equal(E.orderItem(child).name().eval(),j<=i?`saved child ${j}`:privateName);
|
| 113 |
+
assert.equal(E.orderItem(child).version().eval(),j<=i?2:1);
|
| 114 |
+
}
|
| 115 |
+
}
|
| 116 |
+
console.log(`PAGE_OBSERVED ${JSON.stringify({mode,group,ids,childIDs,total:page.totalCount,offset:paged?1:0,size:2,physicalQueries:statements.length})}`);
|
| 117 |
+
console.log(`PAGE OWNERSHIP PASSED: ${mode}`);
|
| 118 |
+
} catch(error) {failures.push(error);console.error(`PAGE FAILED: ${mode}`,error);}
|
| 119 |
+
}
|
| 120 |
+
assert.equal(manifest('lib'),before,'generated library unchanged');
|
| 121 |
+
assert.equal(failures.length,0,'all page scenarios must pass');
|
| 122 |
+
} finally {await client.close();}
|
| 123 |
+
}
|
| 124 |
+
main().catch(error=>{console.error(error);process.exitCode=1;});
|
source/teaql-ts/examples/trace-chain/plan-item-lineage.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import assert from 'node:assert/strict';
|
| 2 |
+
import { createHash, randomUUID } from 'node:crypto';
|
| 3 |
+
import { mkdirSync, readFileSync, readdirSync } from 'node:fs';
|
| 4 |
+
import { join, resolve } from 'node:path';
|
| 5 |
+
import { DelegatingMutationPolicyApprovalProvider, DelegatingMutationPolicyRegistry,
|
| 6 |
+
MutationPlan, MutationRequest, TraceNode, UserContext } from 'teaql-ts';
|
| 7 |
+
import { AbstractSQLTeaQLClient, MutationResult, SQLExecutionEvidenceStore,
|
| 8 |
+
SQLExecutionMetadata, SqlQueryResult, SqlSession } from 'teaql-ts/sql/core';
|
| 9 |
+
import { SQLiteDriver } from 'teaql-ts/sql/sqlite';
|
| 10 |
+
import { Q } from './lib/src/generated/Q';
|
| 11 |
+
import { E } from './lib/src/generated/E';
|
| 12 |
+
import { GENERATED_RUNTIME_MODULE } from './lib/src/runtime-module';
|
| 13 |
+
|
| 14 |
+
// Byte fingerprints only; generated source is not used for API discovery.
|
| 15 |
+
function fingerprint(directory: string, prefix = ''): string {
|
| 16 |
+
return readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))
|
| 17 |
+
.map(entry => entry.isDirectory() ? fingerprint(join(directory, entry.name), `${prefix}${entry.name}/`)
|
| 18 |
+
: `${createHash('sha256').update(readFileSync(join(directory, entry.name))).digest('hex')} ${prefix}${entry.name}\n`).join('');
|
| 19 |
+
}
|
| 20 |
+
const originalLibrary = fingerprint('lib');
|
| 21 |
+
const database = resolve(process.env.TEAQL_TRACE_CHAIN_PLAN_DB ?? '.local/plan-item-lineage.sqlite');
|
| 22 |
+
mkdirSync(join(database, '..'), { recursive: true });
|
| 23 |
+
class Driver extends SQLiteDriver {
|
| 24 |
+
readonly writes: Array<{ sql: string; values: readonly unknown[]; transaction?: number }> = [];
|
| 25 |
+
readonly transactions: Array<{ id: number; committed: boolean }> = [];
|
| 26 |
+
activeTransaction?: number;
|
| 27 |
+
async transaction<T>(work: (session: SqlSession) => Promise<T>): Promise<T> {
|
| 28 |
+
const transaction = { id: this.transactions.length + 1, committed: false };
|
| 29 |
+
this.transactions.push(transaction);
|
| 30 |
+
const result = await super.transaction(async session => {
|
| 31 |
+
this.activeTransaction = transaction.id;
|
| 32 |
+
try { return await work(session); }
|
| 33 |
+
finally { this.activeTransaction = undefined; }
|
| 34 |
+
});
|
| 35 |
+
transaction.committed = true;
|
| 36 |
+
return result;
|
| 37 |
+
}
|
| 38 |
+
async query(sql: string, values: any[] = []): Promise<SqlQueryResult> {
|
| 39 |
+
if (/^(INSERT|UPDATE)/.test(sql) && sql.includes('order_item_data')) {
|
| 40 |
+
this.writes.push({ sql, values: [...values], transaction: this.activeTransaction });
|
| 41 |
+
}
|
| 42 |
+
return super.query(sql, values);
|
| 43 |
+
}
|
| 44 |
+
}
|
| 45 |
+
class Client extends AbstractSQLTeaQLClient {
|
| 46 |
+
readonly commands: Array<{ entity: string; id: string; reason: string; lineage: readonly TraceNode[] }> = [];
|
| 47 |
+
constructor(driver: Driver) { super(driver, GENERATED_RUNTIME_MODULE.schemas); }
|
| 48 |
+
async executeMutation(request: any): Promise<MutationResult> {
|
| 49 |
+
assert(request instanceof MutationRequest, 'ordinary generated save owns every request');
|
| 50 |
+
const result = await super.executeMutation(request);
|
| 51 |
+
this.commands.push({ entity: request.mutation.entity, id: result.id, reason: request.comment,
|
| 52 |
+
lineage: request.traceFor({ entity: request.mutation.entity, id: result.id }) });
|
| 53 |
+
return result;
|
| 54 |
+
}
|
| 55 |
+
}
|
| 56 |
+
const plain = (nodes: unknown) => (nodes as readonly TraceNode[])
|
| 57 |
+
.map(node => [node.kind, node.name, node.entityId, node.detail]);
|
| 58 |
+
|
| 59 |
+
async function main() {
|
| 60 |
+
const driver = new Driver(database);
|
| 61 |
+
const client = new Client(driver).install(GENERATED_RUNTIME_MODULE);
|
| 62 |
+
const context = new UserContext().insertResource('dataService', client);
|
| 63 |
+
client.setUserContext(context);
|
| 64 |
+
const evidence = new SQLExecutionEvidenceStore();
|
| 65 |
+
const diagnostics: SQLExecutionMetadata[] = [];
|
| 66 |
+
const audits: Readonly<Record<string, unknown>>[] = [];
|
| 67 |
+
const reviewed: MutationPlan[] = [];
|
| 68 |
+
client.setRuntimeTelemetrySink(evidence).setDiagnosticSQLLogSink({ write: entry => diagnostics.push(entry) })
|
| 69 |
+
.setAuditSink(event => { audits.push(event); });
|
| 70 |
+
try {
|
| 71 |
+
await context.ensureSchema();
|
| 72 |
+
const identity = { policyId: 'trace-plan-items', version: '1', fingerprint: 'sha256:trace-plan-items-v1' };
|
| 73 |
+
context.withMutationPolicyRegistry(new DelegatingMutationPolicyRegistry(key =>
|
| 74 |
+
key === 'CustomerOrder.saveGraph' ? { identity, review: (_context, plan) => {
|
| 75 |
+
reviewed.push(plan); return { verdict: 'allow' };
|
| 76 |
+
} } : undefined));
|
| 77 |
+
context.withMutationPolicyApprovalProvider(new DelegatingMutationPolicyApprovalProvider(policy =>
|
| 78 |
+
({ policy, approvedBy: 'trace-example-owner', approvedAt: new Date('2026-10-04T00:00:00Z') })));
|
| 79 |
+
|
| 80 |
+
for (const logging of [true, false]) {
|
| 81 |
+
client.setQueryLoggingEnabled(logging).setMutationLoggingEnabled(logging);
|
| 82 |
+
const nonce = randomUUID();
|
| 83 |
+
const order = Q.customerOrders().comment('initialize plan root').purpose('verify ordered graph plan').newEntity(context)
|
| 84 |
+
.updatePlatform('1').updateOrderNumber(`PLAN-${nonce}`).updateDescription('before');
|
| 85 |
+
const first = Q.orderItems().comment('initialize first plan item').purpose('verify ordered graph plan').newEntity(context);
|
| 86 |
+
const second = Q.orderItems().comment('initialize second plan item').purpose('verify ordered graph plan').newEntity(context);
|
| 87 |
+
order.orderItemList().push(first, second);
|
| 88 |
+
first.auditAs('prepare first item'); second.auditAs('prepare second item');
|
| 89 |
+
for (const phase of ['create', 'update'] as const) {
|
| 90 |
+
const secrets = [`LEFTPRIVATE${phase.toUpperCase()}${nonce}`, `RIGHTPRIVATE${phase.toUpperCase()}${nonce}`];
|
| 91 |
+
first.updateName(secrets[0]); second.updateName(secrets[1]);
|
| 92 |
+
order.updateDescription(phase);
|
| 93 |
+
const reason = `align ${secrets[0]} with ${secrets[1]}`;
|
| 94 |
+
reviewed.length = 0; client.commands.length = 0; driver.writes.length = 0; driver.transactions.length = 0;
|
| 95 |
+
diagnostics.length = 0; audits.length = 0; evidence.enableAll();
|
| 96 |
+
await order.auditAs(reason).save(context);
|
| 97 |
+
assert.equal(reviewed.length, 1, 'one governed plan, not two independently approved saves');
|
| 98 |
+
const plan = reviewed[0];
|
| 99 |
+
assert.equal(plan.auditReason, reason, 'raw caller intent stays unchanged');
|
| 100 |
+
assert.equal(plan.operations.length, 3);
|
| 101 |
+
const items = plan.operations.filter(operation => operation.entity === 'OrderItem');
|
| 102 |
+
assert.equal(items.length, 2);
|
| 103 |
+
assert.deepEqual(items.map(operation => operation.changedValues.name), secrets);
|
| 104 |
+
assert(items.every(operation => operation.kind === phase));
|
| 105 |
+
assert(Object.isFrozen(plan) && Object.isFrozen(plan.operations));
|
| 106 |
+
const expected = [
|
| 107 |
+
[['auditReason', 'CustomerOrder', order.id, reason]],
|
| 108 |
+
[['auditReason', 'CustomerOrder', order.id, reason], ['auditReason', 'OrderItem', first.id, 'prepare first item']],
|
| 109 |
+
[['auditReason', 'CustomerOrder', order.id, reason], ['auditReason', 'OrderItem', second.id, 'prepare second item']],
|
| 110 |
+
];
|
| 111 |
+
assert.deepEqual(client.commands.map(command => [command.entity, command.id]),
|
| 112 |
+
[['CustomerOrder', order.id], ['OrderItem', first.id], ['OrderItem', second.id]]);
|
| 113 |
+
assert.deepEqual(client.commands.map(command => plain(command.lineage)), expected);
|
| 114 |
+
assert(client.commands.every(command => command.reason === reason));
|
| 115 |
+
assert.equal(driver.writes.length, 2);
|
| 116 |
+
assert.deepEqual(driver.transactions, [{ id: 1, committed: true }], 'one real atomic graph transaction');
|
| 117 |
+
assert(driver.writes.every(write => write.transaction === 1));
|
| 118 |
+
assert(driver.writes[0].values.includes(secrets[0]) && !driver.writes[0].values.includes(secrets[1]));
|
| 119 |
+
assert(driver.writes[1].values.includes(secrets[1]) && !driver.writes[1].values.includes(secrets[0]));
|
| 120 |
+
const physical = evidence.snapshot();
|
| 121 |
+
assert.equal(physical.length, 6, 'root plus two item writes and three real readbacks');
|
| 122 |
+
assert.equal(audits.length, 3);
|
| 123 |
+
assert.equal(diagnostics.length, logging ? 6 : 0);
|
| 124 |
+
const safe = JSON.stringify({ physical, diagnostics, audits });
|
| 125 |
+
for (const secret of secrets) assert(!safe.includes(secret), 'sibling secret leaked through inherited prose');
|
| 126 |
+
const safeReason = 'align [REDACTED] with [REDACTED]';
|
| 127 |
+
const safeExpected = expected.map(nodes => nodes.map((node, index) =>
|
| 128 |
+
index === 0 ? [node[0], node[1], node[2], safeReason] : node));
|
| 129 |
+
for (let index = 0; index < 3; index++) {
|
| 130 |
+
const write = physical[index * 2], read = physical[index * 2 + 1];
|
| 131 |
+
assert.equal(write.affectedRows, 1); assert.equal(read.operation, 'select'); assert.equal(read.resultCount, 1);
|
| 132 |
+
assert.deepEqual(write.mutationLineage, read.mutationLineage);
|
| 133 |
+
assert.deepEqual(audits[index].mutationLineage, write.mutationLineage);
|
| 134 |
+
assert.deepEqual(plain(write.mutationLineage), safeExpected[index], 'complete SQL item lineage');
|
| 135 |
+
assert.deepEqual(plain(audits[index].mutationLineage), safeExpected[index], 'complete committed item lineage');
|
| 136 |
+
assert.equal(write.auditReason, safeReason, 'safe write retains the masked root intent');
|
| 137 |
+
assert.equal(read.auditReason, safeReason, 'safe readback retains the masked root intent');
|
| 138 |
+
const leaf = write.mutationLineage![write.mutationLineage!.length - 1];
|
| 139 |
+
assert.equal(leaf.entityId, index === 0 ? order.id : index === 1 ? first.id : second.id);
|
| 140 |
+
if (index > 0) assert.equal(leaf.detail, index === 1 ? 'prepare first item' : 'prepare second item');
|
| 141 |
+
}
|
| 142 |
+
// The exact same words are not private in an unrelated request that
|
| 143 |
+
// neither binds nor loads these items; stale graph masking must not linger.
|
| 144 |
+
evidence.enableAll();
|
| 145 |
+
const independent = `independent ${secrets.join(' ')}`;
|
| 146 |
+
await Q.platforms().limit(1).comment(independent).purpose('verify completed plan privacy isolation').executeForList(context);
|
| 147 |
+
assert.equal(evidence.snapshot()[0].comment, independent);
|
| 148 |
+
const loaded = await Q.orderItems().withIdIs(first.id).limit(1)
|
| 149 |
+
.comment('read first committed item').purpose('verify item plan persistence').executeForList(context);
|
| 150 |
+
assert.equal(E.orderItem(loaded[0]).name().eval(), secrets[0]);
|
| 151 |
+
console.log(JSON.stringify({ case: 'TC-MUT-09/TC-REQ-16', path: 'existing MutationPlan and root save',
|
| 152 |
+
logging, phase, reviewedPlans: 1, operations: 3, sameTypeItems: 2,
|
| 153 |
+
transactions: 1, commands: 3, physicalStatements: 6, committedAudits: 3, siblingPrivacy: true, nextRequestIndependent: true }));
|
| 154 |
+
}
|
| 155 |
+
}
|
| 156 |
+
} finally { await client.close(); }
|
| 157 |
+
assert.equal(fingerprint('lib'), originalLibrary);
|
| 158 |
+
console.log('PASS TypeScript generated plan item lineage: 4 scenarios; one plan, ordered same-type items, sibling privacy, independent next request');
|
| 159 |
+
}
|
| 160 |
+
main().catch(error => { console.error(error); process.exitCode = 1; });
|
source/teaql-ts/examples/trace-chain/relation-aggregate.ts
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import assert from 'node:assert/strict';
|
| 2 |
+
import {createHash, randomUUID} from 'node:crypto';
|
| 3 |
+
import {mkdirSync, readFileSync, readdirSync} from 'node:fs';
|
| 4 |
+
import {dirname, join, resolve} from 'node:path';
|
| 5 |
+
import {UserContext} from 'teaql-ts';
|
| 6 |
+
import {AbstractSQLTeaQLClient, SQLExecutionEvidenceStore} from 'teaql-ts/sql/core';
|
| 7 |
+
import {SQLiteDriver} from 'teaql-ts/sql/sqlite';
|
| 8 |
+
import {Q} from './lib/src/generated/Q';
|
| 9 |
+
import {E} from './lib/src/generated/E';
|
| 10 |
+
import {GENERATED_RUNTIME_MODULE} from './lib/src/runtime-module';
|
| 11 |
+
|
| 12 |
+
type Order = Parameters<typeof E.customerOrder>[0];
|
| 13 |
+
type Payment = Parameters<typeof E.payment>[0];
|
| 14 |
+
|
| 15 |
+
const manifest = (path: string): string => readdirSync(path, {withFileTypes: true})
|
| 16 |
+
.sort((a, b) => a.name.localeCompare(b.name)).map(entry => entry.isDirectory()
|
| 17 |
+
? manifest(join(path, entry.name))
|
| 18 |
+
: createHash('sha256').update(readFileSync(join(path, entry.name))).digest('hex')).join('');
|
| 19 |
+
|
| 20 |
+
class Driver extends SQLiteDriver {
|
| 21 |
+
calls = 0;
|
| 22 |
+
aggregateFailure?: Error;
|
| 23 |
+
override async query(sql: string, values: any[] = []) {
|
| 24 |
+
this.calls++;
|
| 25 |
+
if (this.aggregateFailure && /COUNT\(/i.test(sql)) throw this.aggregateFailure;
|
| 26 |
+
return super.query(sql, values);
|
| 27 |
+
}
|
| 28 |
+
override async *stream(sql: string, values: any[] = []) {
|
| 29 |
+
this.calls++;
|
| 30 |
+
yield* super.stream(sql, values);
|
| 31 |
+
}
|
| 32 |
+
}
|
| 33 |
+
class Client extends AbstractSQLTeaQLClient {
|
| 34 |
+
constructor(driver: Driver) { super(driver, GENERATED_RUNTIME_MODULE.schemas); }
|
| 35 |
+
}
|
| 36 |
+
async function collect<T>(stream: AsyncIterable<T>): Promise<T[]> {
|
| 37 |
+
const result: T[] = [];
|
| 38 |
+
for await (const row of stream) result.push(row);
|
| 39 |
+
return result;
|
| 40 |
+
}
|
| 41 |
+
function relatedCount(entity: object, alias: string): number {
|
| 42 |
+
const value = (entity as unknown as Record<string, unknown>)[alias];
|
| 43 |
+
assert.equal(typeof value, 'number', `related count ${alias} was not loaded`);
|
| 44 |
+
assert(Number.isSafeInteger(value));
|
| 45 |
+
return value as number;
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
async function main() {
|
| 49 |
+
const before = manifest('lib');
|
| 50 |
+
const path = resolve(process.env.TEAQL_TRACE_CHAIN_AGGREGATE_DB ?? '.local/relation-aggregate.sqlite');
|
| 51 |
+
mkdirSync(dirname(path), {recursive: true});
|
| 52 |
+
const driver = new Driver(path);
|
| 53 |
+
const client = new Client(driver).install(GENERATED_RUNTIME_MODULE).setDiagnosticSQLLogSink(undefined);
|
| 54 |
+
const context = new UserContext().insertResource('dataService', client);
|
| 55 |
+
const evidence = new SQLExecutionEvidenceStore();
|
| 56 |
+
client.setRuntimeTelemetrySink(evidence);
|
| 57 |
+
const group = randomUUID(), secret = 'PRIVATE-GENERATED-AGGREGATE', alias = 'matchingItems';
|
| 58 |
+
const ids: string[] = [];
|
| 59 |
+
try {
|
| 60 |
+
await context.ensureSchema();
|
| 61 |
+
await context.ensureSchema();
|
| 62 |
+
for (let i = 0; i < 2; i++) {
|
| 63 |
+
const order = Q.customerOrders().comment('initialize aggregate fixture').purpose('verify generated relation aggregate')
|
| 64 |
+
.newEntity(context).updatePlatform('1').updateOrderNumber(`${group}-${i}`).updateDescription(group);
|
| 65 |
+
for (const name of [secret, 'ordinary item']) {
|
| 66 |
+
order.orderItemList().push(Q.orderItems().comment('initialize item').purpose('verify count predicate')
|
| 67 |
+
.newEntity(context).updateName(name));
|
| 68 |
+
}
|
| 69 |
+
order.paymentList().push(Q.payments().comment('initialize payment').purpose('verify nested count')
|
| 70 |
+
.newEntity(context).updateReferenceCode(`${group}-${i}`));
|
| 71 |
+
await order.auditAs('seed generated aggregate graph').save(context);
|
| 72 |
+
ids.push(order.id!);
|
| 73 |
+
}
|
| 74 |
+
for (const logging of [true, false]) {
|
| 75 |
+
client.setQueryLoggingEnabled(logging);
|
| 76 |
+
const filtered = await Q.payments().filterByCustomerOrderIn(ids[0]).limit(1)
|
| 77 |
+
.selectCustomerOrderWith(Q.customerOrders().withIdIs('0').limit(1))
|
| 78 |
+
.comment('load a filtered forward reference').purpose('distinguish NotLoaded details from null')
|
| 79 |
+
.executeForList(context);
|
| 80 |
+
assert.equal(filtered.length, 1);
|
| 81 |
+
const identity = E.payment(filtered[0]).customerOrder().eval();
|
| 82 |
+
assert(identity, 'a filtered target must retain its actual FK identity');
|
| 83 |
+
assert.equal(E.customerOrder(identity).id().eval(), ids[0]);
|
| 84 |
+
assert.throws(() => E.customerOrder(identity).description().eval(),
|
| 85 |
+
{name: 'TeaQLNotLoadedError'},
|
| 86 |
+
'unfetched description must not become a loaded-null value');
|
| 87 |
+
const visible = await Q.payments().filterByCustomerOrderIn(ids[0]).limit(1)
|
| 88 |
+
.selectCustomerOrderWith(Q.customerOrders().withIdIs(ids[0]).limit(1))
|
| 89 |
+
.comment('load the full forward reference').purpose('verify independent detail loading')
|
| 90 |
+
.executeForList(context);
|
| 91 |
+
const full = E.payment(visible[0]).customerOrder().eval();
|
| 92 |
+
assert(full);
|
| 93 |
+
assert.equal(E.customerOrder(full).description().eval(), group);
|
| 94 |
+
assert.throws(() => E.customerOrder(identity).description().eval(),
|
| 95 |
+
{name: 'TeaQLNotLoadedError'},
|
| 96 |
+
'a later loaded view must not leak into the filtered edge');
|
| 97 |
+
console.log(`FORWARD_NOTLOADED_OBSERVED ${JSON.stringify({logging, id: ids[0]})}`);
|
| 98 |
+
}
|
| 99 |
+
for (const nested of [false, true]) for (const mode of ['list', 'stream-full', 'stream-tail']) {
|
| 100 |
+
for (const logging of [true, false]) {
|
| 101 |
+
evidence.enableAll();
|
| 102 |
+
client.setQueryLoggingEnabled(logging);
|
| 103 |
+
const child = Q.orderItems().withNameIs(secret).limit(2);
|
| 104 |
+
const orders = Q.customerOrders().withIdIn(...ids).limit(2)
|
| 105 |
+
.countOrderItemsWith(alias, child)
|
| 106 |
+
.selectOrderItemListWith(Q.orderItems().limit(2));
|
| 107 |
+
const payments = logging
|
| 108 |
+
? Q.payments().withCustomerOrderMatching(Q.customerOrders().withIdIn(...ids).limit(2))
|
| 109 |
+
: Q.payments().filterByCustomerOrderIn(...ids);
|
| 110 |
+
const query = nested ? payments.limit(2).selectCustomerOrderWith(orders) : orders;
|
| 111 |
+
const request = query.comment(`inspect ${secret}`).purpose('verify generated aggregate ancestry');
|
| 112 |
+
const start = driver.calls;
|
| 113 |
+
const rows = mode === 'list' ? await request.executeForList(context)
|
| 114 |
+
: await collect<Order | Payment>(request.executeForStream(context, mode === 'stream-full' ? 1 : 3));
|
| 115 |
+
assert.equal(rows.length, 2);
|
| 116 |
+
const chunkCount = mode === 'stream-full' ? 2 : 1;
|
| 117 |
+
const calls = 1 + 2 + chunkCount * (nested ? 2 : 1);
|
| 118 |
+
assert.equal(driver.calls - start, calls, 'actual aggregate and relation SQL must execute even with logs off');
|
| 119 |
+
for (const row of rows) {
|
| 120 |
+
// Narrow the public union at its known query boundary, not generated implementation state.
|
| 121 |
+
const order = nested ? E.payment(row as Payment).customerOrder().eval() : row as Order;
|
| 122 |
+
assert(order);
|
| 123 |
+
assert(ids.includes(E.customerOrder(order).id().eval()!));
|
| 124 |
+
assert.equal(relatedCount(order, alias), 1);
|
| 125 |
+
assert.equal(E.customerOrder(order).orderItemList().size().eval(), 2);
|
| 126 |
+
}
|
| 127 |
+
if (logging) {
|
| 128 |
+
const entries = evidence.snapshot();
|
| 129 |
+
assert.equal(entries.length, calls);
|
| 130 |
+
assert(!JSON.stringify(entries).includes(secret));
|
| 131 |
+
assert(entries.every(entry => entry.tracePath[0].name === (nested ? 'Payment' : 'CustomerOrder')));
|
| 132 |
+
const aggregate = entries.filter(entry => /COUNT\(/i.test(entry.parameterizedSQL));
|
| 133 |
+
assert.equal(aggregate.length, chunkCount);
|
| 134 |
+
for (const entry of aggregate) {
|
| 135 |
+
assert.deepEqual(entry.tracePath.filter(frame => frame.kind === 'relation').map(frame => frame.name),
|
| 136 |
+
nested ? ['customerOrder', 'orderItemList'] : ['orderItemList']);
|
| 137 |
+
}
|
| 138 |
+
}
|
| 139 |
+
console.log(`AGGREGATE_OBSERVED ${JSON.stringify({nested, mode, logging, rows: rows.length, calls})}`);
|
| 140 |
+
}
|
| 141 |
+
}
|
| 142 |
+
client.setQueryLoggingEnabled(true);
|
| 143 |
+
const loaded = await Q.customerOrders().withIdIs(ids[0]).countOrderItemsAs(alias)
|
| 144 |
+
.selectOrderItemListWith(Q.orderItems().limit(2)).limit(1)
|
| 145 |
+
.comment('load graph with a computed projection').purpose('verify aggregate is not mutation data').executeForList(context);
|
| 146 |
+
assert.equal(relatedCount(loaded[0], alias), 2);
|
| 147 |
+
evidence.enableAll();
|
| 148 |
+
await loaded[0].updateDescription(`saved-${group}`).auditAs('update aggregate-loaded graph').save(context);
|
| 149 |
+
const writes = evidence.snapshot().filter(entry => entry.operation === 'update');
|
| 150 |
+
assert.equal(writes.length, 1, 'unchanged children and count projection are not mutations');
|
| 151 |
+
assert(!writes[0].parameterizedSQL.includes(alias));
|
| 152 |
+
const reloaded = await Q.customerOrders().withIdIs(ids[0]).countOrderItemsAs(alias).limit(1)
|
| 153 |
+
.comment('recheck saved graph').purpose('verify computed count survives ordinary save').executeForList(context);
|
| 154 |
+
assert.equal(E.customerOrder(reloaded[0]).description().eval(), `saved-${group}`);
|
| 155 |
+
assert.equal(relatedCount(reloaded[0], alias), 2);
|
| 156 |
+
evidence.enableAll();
|
| 157 |
+
const failure = new Error('generated aggregate failure');
|
| 158 |
+
driver.aggregateFailure = failure;
|
| 159 |
+
await assert.rejects(collect(Q.customerOrders().withIdIn(...ids).countOrderItemsAs(alias).limit(2)
|
| 160 |
+
.comment('reject incomplete aggregate rows').purpose('verify failed stream provenance').executeForStream(context, 1)),
|
| 161 |
+
error => error === failure);
|
| 162 |
+
assert.deepEqual(evidence.snapshot().map(entry => entry.executionOutcome), ['failure', 'failure']);
|
| 163 |
+
driver.aggregateFailure = undefined;
|
| 164 |
+
assert.equal(manifest('lib'), before, 'generated library must remain unchanged');
|
| 165 |
+
console.log('PASS TypeScript generated relation aggregates: 12 combinations, audited save and stream failure');
|
| 166 |
+
} finally { await client.close(); }
|
| 167 |
+
}
|
| 168 |
+
main().catch(error => { console.error(error); process.exitCode = 1; });
|