@honua/sdk-esri-compat 0.1.12 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/columnar/apache-arrow.d.ts +17 -0
- package/columnar/apache-arrow.d.ts.map +1 -0
- package/columnar/apache-arrow.js +1036 -0
- package/columnar/batch-cache-conformance.d.ts +66 -0
- package/columnar/batch-cache-conformance.d.ts.map +1 -0
- package/columnar/batch-cache-conformance.js +317 -0
- package/columnar/batch-cache-indexeddb.d.ts +31 -0
- package/columnar/batch-cache-indexeddb.d.ts.map +1 -0
- package/columnar/batch-cache-indexeddb.js +148 -0
- package/columnar/batch-cache.d.ts +298 -0
- package/columnar/batch-cache.d.ts.map +1 -0
- package/columnar/batch-cache.js +757 -0
- package/columnar/geoarrow-aggregate.d.ts +178 -0
- package/columnar/geoarrow-aggregate.d.ts.map +1 -0
- package/columnar/geoarrow-aggregate.js +976 -0
- package/columnar/geoarrow-patch.d.ts +382 -0
- package/columnar/geoarrow-patch.d.ts.map +1 -0
- package/columnar/geoarrow-patch.js +1656 -0
- package/columnar/geoarrow-reproject.d.ts +22 -0
- package/columnar/geoarrow-reproject.d.ts.map +1 -0
- package/columnar/geoarrow-reproject.js +119 -0
- package/columnar/geoarrow-serialization.d.ts +68 -0
- package/columnar/geoarrow-serialization.d.ts.map +1 -0
- package/columnar/geoarrow-serialization.js +331 -0
- package/columnar/geoarrow-types.d.ts +271 -0
- package/columnar/geoarrow-types.d.ts.map +1 -0
- package/columnar/geoarrow-types.js +15 -0
- package/columnar/geoarrow.d.ts +52 -0
- package/columnar/geoarrow.d.ts.map +1 -0
- package/columnar/geoarrow.js +1469 -0
- package/columnar/index.d.ts +43 -0
- package/columnar/index.d.ts.map +1 -0
- package/columnar/index.js +29 -0
- package/columnar/operators.d.ts +70 -0
- package/columnar/operators.d.ts.map +1 -0
- package/columnar/operators.js +307 -0
- package/columnar/result.d.ts +369 -0
- package/columnar/result.d.ts.map +1 -0
- package/columnar/result.js +815 -0
- package/columnar/telemetry.d.ts +152 -0
- package/columnar/telemetry.d.ts.map +1 -0
- package/columnar/telemetry.js +265 -0
- package/columnar/transfer.d.ts +28 -0
- package/columnar/transfer.d.ts.map +1 -0
- package/columnar/transfer.js +669 -0
- package/columnar/types.d.ts +175 -0
- package/columnar/types.d.ts.map +1 -0
- package/columnar/types.js +22 -0
- package/columnar/worker.d.ts +157 -0
- package/columnar/worker.d.ts.map +1 -0
- package/columnar/worker.js +1059 -0
- package/connect-url-safety.d.ts +53 -0
- package/connect-url-safety.js +189 -0
- package/contract/pmtiles.d.ts +6 -5
- package/contract/pmtiles.d.ts.map +1 -1
- package/contract/pmtiles.js +30 -5
- package/core/client.d.ts.map +1 -1
- package/core/client.js +87 -19
- package/core/deprecation-notice.d.ts +28 -0
- package/core/deprecation-notice.d.ts.map +1 -0
- package/core/deprecation-notice.js +22 -0
- package/core/esri-geojson.d.ts.map +1 -1
- package/core/esri-geojson.js +10 -6
- package/core/optional-grpc-peer.d.ts +15 -0
- package/core/optional-grpc-peer.d.ts.map +1 -0
- package/core/optional-grpc-peer.js +60 -0
- package/esri-compat/basemap-gallery.d.ts +2 -0
- package/esri-compat/basemap-gallery.d.ts.map +1 -1
- package/esri-compat/basemap-gallery.js +12 -0
- package/esri-compat/basemap.d.ts +4 -0
- package/esri-compat/basemap.d.ts.map +1 -1
- package/esri-compat/basemap.js +70 -0
- package/esri-compat/bookmarks.d.ts +2 -0
- package/esri-compat/bookmarks.d.ts.map +1 -1
- package/esri-compat/bookmarks.js +12 -0
- package/esri-compat/controls.d.ts +18 -0
- package/esri-compat/controls.d.ts.map +1 -1
- package/esri-compat/controls.js +120 -57
- package/esri-compat/directions.d.ts +4 -0
- package/esri-compat/directions.d.ts.map +1 -1
- package/esri-compat/directions.js +30 -20
- package/esri-compat/editor.d.ts +4 -0
- package/esri-compat/editor.d.ts.map +1 -1
- package/esri-compat/editor.js +16 -0
- package/esri-compat/esri-config.d.ts +2 -1
- package/esri-compat/esri-config.d.ts.map +1 -1
- package/esri-compat/feature-effect.d.ts +23 -0
- package/esri-compat/feature-effect.d.ts.map +1 -0
- package/esri-compat/feature-effect.js +12 -0
- package/esri-compat/feature-form.d.ts +6 -0
- package/esri-compat/feature-form.d.ts.map +1 -1
- package/esri-compat/feature-form.js +63 -0
- package/esri-compat/feature-layer.d.ts +21 -2
- package/esri-compat/feature-layer.d.ts.map +1 -1
- package/esri-compat/feature-layer.js +172 -1
- package/esri-compat/feature-table.d.ts +5 -0
- package/esri-compat/feature-table.d.ts.map +1 -1
- package/esri-compat/feature-table.js +23 -0
- package/esri-compat/identity-manager.d.ts +1 -1
- package/esri-compat/identity-manager.js +1 -1
- package/esri-compat/legend.d.ts +2 -0
- package/esri-compat/legend.d.ts.map +1 -1
- package/esri-compat/legend.js +98 -0
- package/esri-compat/locator.d.ts +1 -1
- package/esri-compat/locator.js +1 -1
- package/esri-compat/map-view-mount.d.ts +1 -0
- package/esri-compat/map-view-mount.d.ts.map +1 -1
- package/esri-compat/map-view-mount.js +46 -25
- package/esri-compat/map-view.d.ts +13 -0
- package/esri-compat/map-view.d.ts.map +1 -1
- package/esri-compat/map-view.js +94 -8
- package/esri-compat/map.d.ts +5 -1
- package/esri-compat/map.d.ts.map +1 -1
- package/esri-compat/map.js +10 -0
- package/esri-compat/measurement.d.ts +2 -0
- package/esri-compat/measurement.d.ts.map +1 -1
- package/esri-compat/measurement.js +14 -0
- package/esri-compat/point.d.ts +7 -0
- package/esri-compat/point.d.ts.map +1 -1
- package/esri-compat/point.js +33 -3
- package/esri-compat/popup.d.ts +2 -0
- package/esri-compat/popup.d.ts.map +1 -1
- package/esri-compat/popup.js +12 -0
- package/esri-compat/portal.d.ts +1 -1
- package/esri-compat/portal.js +1 -1
- package/esri-compat/print.d.ts +3 -0
- package/esri-compat/print.d.ts.map +1 -1
- package/esri-compat/print.js +15 -0
- package/esri-compat/search.d.ts +4 -0
- package/esri-compat/search.d.ts.map +1 -1
- package/esri-compat/search.js +25 -28
- package/esri-compat/sketch.d.ts +2 -0
- package/esri-compat/sketch.d.ts.map +1 -1
- package/esri-compat/sketch.js +12 -0
- package/esri-compat/widget-host.d.ts +46 -17
- package/esri-compat/widget-host.d.ts.map +1 -1
- package/esri-compat/widget-host.js +84 -20
- package/esri-compat/widget-shell-hosts.d.ts +61 -0
- package/esri-compat/widget-shell-hosts.d.ts.map +1 -0
- package/esri-compat/widget-shell-hosts.js +76 -0
- package/index.d.ts +3 -1
- package/index.js +1 -0
- package/offline/digest.d.ts +15 -0
- package/offline/digest.js +58 -0
- package/offline/quota.d.ts +161 -0
- package/offline/quota.js +370 -0
- package/offline/types.d.ts +349 -0
- package/offline/types.js +75 -0
- package/package.json +21 -2
- package/query-planner/canonical-filter.d.ts +30 -0
- package/query-planner/canonical-filter.d.ts.map +1 -0
- package/query-planner/canonical-filter.js +30 -0
- package/query-planner/canonical.d.ts +7 -0
- package/query-planner/canonical.d.ts.map +1 -0
- package/query-planner/canonical.js +145 -0
- package/query-planner/columnar-plan.d.ts +63 -0
- package/query-planner/columnar-plan.d.ts.map +1 -0
- package/query-planner/columnar-plan.js +94 -0
- package/query-planner/cql2-json.d.ts +17 -0
- package/query-planner/cql2-json.d.ts.map +1 -0
- package/query-planner/cql2-json.js +646 -0
- package/query-planner/diagnostics.d.ts +35 -0
- package/query-planner/diagnostics.d.ts.map +1 -0
- package/query-planner/diagnostics.js +386 -0
- package/query-planner/duckdb.d.ts +79 -0
- package/query-planner/duckdb.d.ts.map +1 -0
- package/query-planner/duckdb.js +772 -0
- package/query-planner/execution-context.d.ts +5 -0
- package/query-planner/execution-context.d.ts.map +1 -0
- package/query-planner/execution-context.js +52 -0
- package/query-planner/executor.d.ts +5 -0
- package/query-planner/executor.d.ts.map +1 -0
- package/query-planner/executor.js +229 -0
- package/query-planner/geoservices.d.ts +91 -0
- package/query-planner/geoservices.d.ts.map +1 -0
- package/query-planner/geoservices.js +688 -0
- package/query-planner/grpc.d.ts +100 -0
- package/query-planner/grpc.d.ts.map +1 -0
- package/query-planner/grpc.js +760 -0
- package/query-planner/index.d.ts +59 -0
- package/query-planner/index.d.ts.map +1 -0
- package/query-planner/index.js +43 -0
- package/query-planner/ir.d.ts +25 -0
- package/query-planner/ir.d.ts.map +1 -0
- package/query-planner/ir.js +479 -0
- package/query-planner/local-aggregate.d.ts +5 -0
- package/query-planner/local-aggregate.d.ts.map +1 -0
- package/query-planner/local-aggregate.js +126 -0
- package/query-planner/odata-protocol-module.d.ts +54 -0
- package/query-planner/odata-protocol-module.d.ts.map +1 -0
- package/query-planner/odata-protocol-module.js +199 -0
- package/query-planner/odata-v1.d.ts +23 -0
- package/query-planner/odata-v1.d.ts.map +1 -0
- package/query-planner/odata-v1.js +202 -0
- package/query-planner/odata.d.ts +45 -0
- package/query-planner/odata.d.ts.map +1 -0
- package/query-planner/odata.js +519 -0
- package/query-planner/ogc-compiler.d.ts +55 -0
- package/query-planner/ogc-compiler.d.ts.map +1 -0
- package/query-planner/ogc-compiler.js +480 -0
- package/query-planner/ogc-features.d.ts +53 -0
- package/query-planner/ogc-features.d.ts.map +1 -0
- package/query-planner/ogc-features.js +639 -0
- package/query-planner/planner.d.ts +17 -0
- package/query-planner/planner.d.ts.map +1 -0
- package/query-planner/planner.js +937 -0
- package/query-planner/representation.d.ts +59 -0
- package/query-planner/representation.d.ts.map +1 -0
- package/query-planner/representation.js +140 -0
- package/query-planner/resource.d.ts +94 -0
- package/query-planner/resource.d.ts.map +1 -0
- package/query-planner/resource.js +526 -0
- package/query-planner/semantic-canonical.d.ts +15 -0
- package/query-planner/semantic-canonical.d.ts.map +1 -0
- package/query-planner/semantic-canonical.js +62 -0
- package/query-planner/semantic-compat.d.ts +10 -0
- package/query-planner/semantic-compat.d.ts.map +1 -0
- package/query-planner/semantic-compat.js +35 -0
- package/query-planner/semantic-compiler.d.ts +64 -0
- package/query-planner/semantic-compiler.d.ts.map +1 -0
- package/query-planner/semantic-compiler.js +81 -0
- package/query-planner/semantic-literals.d.ts +30 -0
- package/query-planner/semantic-literals.d.ts.map +1 -0
- package/query-planner/semantic-literals.js +133 -0
- package/query-planner/semantic-types.d.ts +265 -0
- package/query-planner/semantic-types.d.ts.map +1 -0
- package/query-planner/semantic-types.js +1 -0
- package/query-planner/semantic.d.ts +54 -0
- package/query-planner/semantic.d.ts.map +1 -0
- package/query-planner/semantic.js +1421 -0
- package/query-planner/types.d.ts +712 -0
- package/query-planner/types.d.ts.map +1 -0
- package/query-planner/types.js +49 -0
- package/query-planner/wfs-protocol-module.d.ts +57 -0
- package/query-planner/wfs-protocol-module.d.ts.map +1 -0
- package/query-planner/wfs-protocol-module.js +731 -0
- package/query-planner/wfs-semantic.d.ts +58 -0
- package/query-planner/wfs-semantic.d.ts.map +1 -0
- package/query-planner/wfs-semantic.js +547 -0
- package/query-planner/wfs-v1.d.ts +41 -0
- package/query-planner/wfs-v1.d.ts.map +1 -0
- package/query-planner/wfs-v1.js +366 -0
- package/query-planner/wfs.d.ts +4 -0
- package/query-planner/wfs.d.ts.map +1 -0
- package/query-planner/wfs.js +2 -0
- package/widget-capabilities.d.ts +67 -0
- package/widget-capabilities.js +152 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Source } from "../contract/types.js";
|
|
2
|
+
import { type ExecuteQueryPlanOptions, type QueryExecutionPlanV1 } from "./types.js";
|
|
3
|
+
/** @internal Shared lightweight accepted-plan context boundary for v1 consumers. */
|
|
4
|
+
export declare function assertQueryPlanExecutionContextV1<T>(plan: QueryExecutionPlanV1, source: Source<T>, options: ExecuteQueryPlanOptions): void;
|
|
5
|
+
//# sourceMappingURL=execution-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution-context.d.ts","sourceRoot":"","sources":["../../../src/query-planner/execution-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAInD,OAAO,EACL,KAAK,uBAAuB,EAE5B,KAAK,oBAAoB,EAE1B,MAAM,YAAY,CAAC;AAEpB,oFAAoF;AACpF,wBAAgB,iCAAiC,CAAC,CAAC,EACjD,IAAI,EAAE,oBAAoB,EAC1B,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EACjB,OAAO,EAAE,uBAAuB,GAC/B,IAAI,CA0CN"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { canonicalStringify, toJsonValue } from "./canonical.js";
|
|
2
|
+
import { createPlanValidity, createQueryPlanProvenance } from "./diagnostics.js";
|
|
3
|
+
import { queryIrSourceIdentity } from "./ir.js";
|
|
4
|
+
import { HonuaQueryPlanExecutionError, } from "./types.js";
|
|
5
|
+
/** @internal Shared lightweight accepted-plan context boundary for v1 consumers. */
|
|
6
|
+
export function assertQueryPlanExecutionContextV1(plan, source, options) {
|
|
7
|
+
const current = queryIrSourceIdentity(source.descriptor, options);
|
|
8
|
+
const executionMode = options.executionMode ?? plan.validity.executionMode;
|
|
9
|
+
const currentIr = { ...plan.ir, source: current };
|
|
10
|
+
const currentProvenance = createQueryPlanProvenance(source.descriptor, current, options);
|
|
11
|
+
// Representation is plan-bound, not source-bound: it is re-asserted here so
|
|
12
|
+
// the validity fingerprint recomputes identically, never re-decided.
|
|
13
|
+
const currentValidity = createPlanValidity(currentIr, currentProvenance, plan.capabilityPolicy, plan.fallback, executionMode, plan.validity.representation);
|
|
14
|
+
if (currentValidity.fingerprint === plan.validity.fingerprint)
|
|
15
|
+
return;
|
|
16
|
+
if (!sameForeignSourceIdentity(current, plan.ir.source)) {
|
|
17
|
+
throw planContextError("foreign-plan", "source-identity-changed");
|
|
18
|
+
}
|
|
19
|
+
if (!sameJson(current.authorizationScope, plan.ir.source.authorizationScope)) {
|
|
20
|
+
throw planContextError("foreign-plan", "authorization-scope-changed");
|
|
21
|
+
}
|
|
22
|
+
if (executionMode !== plan.validity.executionMode) {
|
|
23
|
+
throw planContextError("foreign-plan", "execution-mode-changed");
|
|
24
|
+
}
|
|
25
|
+
if (current.sourceVersion !== plan.ir.source.sourceVersion) {
|
|
26
|
+
throw planContextError("stale-plan", "source-version-changed");
|
|
27
|
+
}
|
|
28
|
+
if (current.schemaVersion !== plan.ir.source.schemaVersion ||
|
|
29
|
+
!sameJson(currentProvenance.schema, plan.provenance.schema)) {
|
|
30
|
+
throw planContextError("stale-plan", "schema-changed");
|
|
31
|
+
}
|
|
32
|
+
if (!sameJson(current.capabilities, plan.ir.source.capabilities)) {
|
|
33
|
+
throw planContextError("stale-plan", "capabilities-changed");
|
|
34
|
+
}
|
|
35
|
+
if (!sameJson(currentProvenance.discovery, plan.provenance.discovery)) {
|
|
36
|
+
throw planContextError("stale-plan", "discovery-changed");
|
|
37
|
+
}
|
|
38
|
+
throw planContextError("stale-plan", "source-identity-changed");
|
|
39
|
+
}
|
|
40
|
+
function sameForeignSourceIdentity(current, planned) {
|
|
41
|
+
const omitMutableBindings = (value) => {
|
|
42
|
+
const { authorizationScope: _authorizationScope, capabilities: _capabilities, schemaVersion: _schemaVersion, sourceVersion: _sourceVersion, ...identity } = value;
|
|
43
|
+
return identity;
|
|
44
|
+
};
|
|
45
|
+
return sameJson(omitMutableBindings(current), omitMutableBindings(planned));
|
|
46
|
+
}
|
|
47
|
+
function sameJson(left, right) {
|
|
48
|
+
return canonicalStringify(toJsonValue(left)) === canonicalStringify(toJsonValue(right));
|
|
49
|
+
}
|
|
50
|
+
function planContextError(code, reason) {
|
|
51
|
+
return new HonuaQueryPlanExecutionError(code, `${code === "stale-plan" ? "Query plan context is stale" : "Query plan belongs to a foreign context"}; explain a replacement plan`, { context: { reason } }, reason);
|
|
52
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Source } from "../contract/types.js";
|
|
2
|
+
import { type ExecuteQueryPlanOptions, type QueryExecutionPlan, type QueryPlanExecution } from "./types.js";
|
|
3
|
+
/** Execute an already-reviewed plan. This function validates; it never replans. */
|
|
4
|
+
export declare function executeQueryPlan<T>(plan: QueryExecutionPlan, source: Source<T>, options?: ExecuteQueryPlanOptions): Promise<QueryPlanExecution<T>>;
|
|
5
|
+
//# sourceMappingURL=executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../src/query-planner/executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAUlE,OAAO,EACL,KAAK,uBAAuB,EAK5B,KAAK,kBAAkB,EAEvB,KAAK,kBAAkB,EAExB,MAAM,YAAY,CAAC;AAEpB,mFAAmF;AACnF,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EACjB,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CA0BhC"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { HonuaAbortError } from "../core/errors.js";
|
|
2
|
+
import { canonicalStringify, toJsonValue } from "./canonical.js";
|
|
3
|
+
import { createPlanValidity, createQueryPlanProvenance } from "./diagnostics.js";
|
|
4
|
+
import { assertQueryPlanExecutionContextV1 } from "./execution-context.js";
|
|
5
|
+
import { queryFromCanonical, queryIrSourceIdentityV2 } from "./ir.js";
|
|
6
|
+
import { aggregateLocally } from "./local-aggregate.js";
|
|
7
|
+
import { validateQueryPlanSnapshot } from "./planner.js";
|
|
8
|
+
import { parseGeoParquetResourceHandle, resolveGeoParquetResource } from "./resource.js";
|
|
9
|
+
import { HonuaQueryPlanExecutionError, } from "./types.js";
|
|
10
|
+
/** Execute an already-reviewed plan. This function validates; it never replans. */
|
|
11
|
+
export async function executeQueryPlan(plan, source, options = {}) {
|
|
12
|
+
const acceptedPlan = validateQueryPlanSnapshot(plan);
|
|
13
|
+
assertPlanContext(acceptedPlan, source, options);
|
|
14
|
+
// This executor is the object-representation executor. Silently answering a
|
|
15
|
+
// columnar-selected plan with feature objects would misreport the
|
|
16
|
+
// representation the plan (and any batch identity derived from it) declares.
|
|
17
|
+
if (acceptedPlan.validity.representation !== "object") {
|
|
18
|
+
throw new HonuaQueryPlanExecutionError("invalid-plan", `executeQueryPlan returns object results, but this plan selected "${acceptedPlan.validity.representation}" execution; execute it through the plan's columnar producer or explain with representation: "object"`);
|
|
19
|
+
}
|
|
20
|
+
throwIfExecutionAborted(options.signal);
|
|
21
|
+
const remote = acceptedPlan.steps[0];
|
|
22
|
+
if (!remote || remote.engine !== "remote") {
|
|
23
|
+
throw new HonuaQueryPlanExecutionError("invalid-plan", "A query plan must begin with a remote step");
|
|
24
|
+
}
|
|
25
|
+
const remoteResult = acceptedPlan.version === "2.0"
|
|
26
|
+
? await executeGeoParquetRemote(acceptedPlan, remote, source, options)
|
|
27
|
+
: await executeRemote(remote, source, options.signal);
|
|
28
|
+
throwIfExecutionAborted(options.signal);
|
|
29
|
+
const local = acceptedPlan.steps[1];
|
|
30
|
+
const result = local ? executeLocal(acceptedPlan, local, remoteResult, options.signal) : remoteResult;
|
|
31
|
+
throwIfExecutionAborted(options.signal);
|
|
32
|
+
return { planId: acceptedPlan.id, fingerprint: acceptedPlan.fingerprint, result };
|
|
33
|
+
}
|
|
34
|
+
function assertPlanContext(plan, source, options) {
|
|
35
|
+
if (plan.version === "1.0") {
|
|
36
|
+
assertQueryPlanExecutionContextV1(plan, source, options);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const current = queryIrSourceIdentityV2(source.descriptor, plan.ir.source.geoparquet.resource, options);
|
|
40
|
+
const executionMode = options.executionMode ?? plan.validity.executionMode;
|
|
41
|
+
const currentIr = { ...plan.ir, source: current };
|
|
42
|
+
const currentProvenance = createQueryPlanProvenance(source.descriptor, current, options);
|
|
43
|
+
const currentValidity = createPlanValidity(currentIr, currentProvenance, plan.capabilityPolicy, plan.fallback, executionMode, plan.validity.representation);
|
|
44
|
+
if (currentValidity.fingerprint === plan.validity.fingerprint)
|
|
45
|
+
return;
|
|
46
|
+
if (!sameForeignSourceIdentity(current, plan.ir.source)) {
|
|
47
|
+
throw planContextError("foreign-plan", "source-identity-changed");
|
|
48
|
+
}
|
|
49
|
+
if (!sameJson(current.authorizationScope, plan.ir.source.authorizationScope)) {
|
|
50
|
+
throw planContextError("foreign-plan", "authorization-scope-changed");
|
|
51
|
+
}
|
|
52
|
+
if (executionMode !== plan.validity.executionMode) {
|
|
53
|
+
throw planContextError("foreign-plan", "execution-mode-changed");
|
|
54
|
+
}
|
|
55
|
+
if (current.sourceVersion !== plan.ir.source.sourceVersion) {
|
|
56
|
+
throw planContextError("stale-plan", "source-version-changed");
|
|
57
|
+
}
|
|
58
|
+
if (current.schemaVersion !== plan.ir.source.schemaVersion ||
|
|
59
|
+
!sameJson(currentProvenance.schema, plan.provenance.schema)) {
|
|
60
|
+
throw planContextError("stale-plan", "schema-changed");
|
|
61
|
+
}
|
|
62
|
+
if (!sameJson(current.capabilities, plan.ir.source.capabilities)) {
|
|
63
|
+
throw planContextError("stale-plan", "capabilities-changed");
|
|
64
|
+
}
|
|
65
|
+
if (!sameJson(currentProvenance.discovery, plan.provenance.discovery)) {
|
|
66
|
+
throw planContextError("stale-plan", "discovery-changed");
|
|
67
|
+
}
|
|
68
|
+
throw planContextError("stale-plan", "source-identity-changed");
|
|
69
|
+
}
|
|
70
|
+
function sameForeignSourceIdentity(current, planned) {
|
|
71
|
+
const omitMutableBindings = (value) => {
|
|
72
|
+
const { authorizationScope: _authorizationScope, capabilities: _capabilities, schemaVersion: _schemaVersion, sourceVersion: _sourceVersion, ...identity } = value;
|
|
73
|
+
return identity;
|
|
74
|
+
};
|
|
75
|
+
return sameJson(omitMutableBindings(current), omitMutableBindings(planned));
|
|
76
|
+
}
|
|
77
|
+
function sameJson(left, right) {
|
|
78
|
+
return canonicalStringify(toJsonValue(left)) === canonicalStringify(toJsonValue(right));
|
|
79
|
+
}
|
|
80
|
+
function planContextError(code, reason) {
|
|
81
|
+
return new HonuaQueryPlanExecutionError(code, `${code === "stale-plan" ? "Query plan context is stale" : "Query plan belongs to a foreign context"}; explain a replacement plan`, { context: { reason } }, reason);
|
|
82
|
+
}
|
|
83
|
+
async function executeGeoParquetRemote(plan, step, source, options) {
|
|
84
|
+
const handle = parseGeoParquetResourceHandle(plan.ir.source.geoparquet.resource);
|
|
85
|
+
if (typeof options.authorizationContextId !== "string" ||
|
|
86
|
+
options.authorizationContextId !== handle.authorizationContextId ||
|
|
87
|
+
typeof options.geoParquetResourceResolver !== "function") {
|
|
88
|
+
throw new HonuaQueryPlanExecutionError("resource-unavailable", "GeoParquet resource is unavailable");
|
|
89
|
+
}
|
|
90
|
+
const resolved = await resolveGeoParquetResource(handle, options.geoParquetResourceResolver, {
|
|
91
|
+
authorizationContextId: options.authorizationContextId,
|
|
92
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
93
|
+
});
|
|
94
|
+
if (signalAborted(options.signal))
|
|
95
|
+
throw new HonuaAbortError();
|
|
96
|
+
let adapterValue;
|
|
97
|
+
try {
|
|
98
|
+
adapterValue = source.protocol("geoparquet");
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
throw resourceExecutionFailed();
|
|
102
|
+
}
|
|
103
|
+
const executeResolvedQuery = safeAdapterMethod(adapterValue, "executeResolvedQuery");
|
|
104
|
+
if (!executeResolvedQuery)
|
|
105
|
+
throw resourceExecutionFailed();
|
|
106
|
+
const geometryColumn = plan.ir.source.geoparquet.geometryColumn;
|
|
107
|
+
const effectiveSchema = plan.ir.source.geoparquet.effectiveSchema;
|
|
108
|
+
try {
|
|
109
|
+
const result = (await Reflect.apply(executeResolvedQuery, adapterValue, [
|
|
110
|
+
{
|
|
111
|
+
sources: resolved.sources,
|
|
112
|
+
operation: step.operation,
|
|
113
|
+
query: queryFromCanonical(step.query, options.signal),
|
|
114
|
+
sourceId: plan.ir.source.id,
|
|
115
|
+
...(geometryColumn
|
|
116
|
+
? {
|
|
117
|
+
geometry: {
|
|
118
|
+
column: geometryColumn,
|
|
119
|
+
encoding: plan.ir.source.geoparquet.geometryEncoding ?? "wkb",
|
|
120
|
+
...(plan.ir.source.geoparquet.bboxColumn ? { bboxColumn: plan.ir.source.geoparquet.bboxColumn } : {}),
|
|
121
|
+
...(plan.ir.source.geoparquet.nativeDimensions
|
|
122
|
+
? { nativeDimensions: plan.ir.source.geoparquet.nativeDimensions }
|
|
123
|
+
: {}),
|
|
124
|
+
},
|
|
125
|
+
}
|
|
126
|
+
: {}),
|
|
127
|
+
...(effectiveSchema ? { effectiveSchema } : {}),
|
|
128
|
+
},
|
|
129
|
+
]));
|
|
130
|
+
if (signalAborted(options.signal))
|
|
131
|
+
throw new HonuaAbortError();
|
|
132
|
+
return result;
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
if (signalAborted(options.signal))
|
|
136
|
+
throw new HonuaAbortError();
|
|
137
|
+
throw resourceExecutionFailed();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const MAX_ADAPTER_PROTOTYPE_DEPTH = 16;
|
|
141
|
+
/** Resolve a data-method without invoking accessors or unbounded prototype traps. */
|
|
142
|
+
function safeAdapterMethod(value, key) {
|
|
143
|
+
try {
|
|
144
|
+
if (value === null || typeof value !== "object")
|
|
145
|
+
return undefined;
|
|
146
|
+
const visited = new Set();
|
|
147
|
+
let current = value;
|
|
148
|
+
for (let depth = 0; current !== null && depth < MAX_ADAPTER_PROTOTYPE_DEPTH; depth += 1) {
|
|
149
|
+
if (visited.has(current))
|
|
150
|
+
return undefined;
|
|
151
|
+
visited.add(current);
|
|
152
|
+
const descriptor = Object.getOwnPropertyDescriptor(current, key);
|
|
153
|
+
if (descriptor) {
|
|
154
|
+
return "value" in descriptor && typeof descriptor.value === "function" ? descriptor.value : undefined;
|
|
155
|
+
}
|
|
156
|
+
current = Object.getPrototypeOf(current);
|
|
157
|
+
}
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function signalAborted(signal) {
|
|
165
|
+
if (!signal)
|
|
166
|
+
return false;
|
|
167
|
+
try {
|
|
168
|
+
return signal.aborted;
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
function resourceExecutionFailed() {
|
|
175
|
+
return new HonuaQueryPlanExecutionError("resource-execution-failed", "GeoParquet resource execution failed");
|
|
176
|
+
}
|
|
177
|
+
function executeRemote(step, source, signal) {
|
|
178
|
+
const query = queryFromCanonical(step.query, signal);
|
|
179
|
+
switch (step.operation) {
|
|
180
|
+
case "query":
|
|
181
|
+
return source.query(query);
|
|
182
|
+
case "queryAll":
|
|
183
|
+
return source.queryAll(query);
|
|
184
|
+
case "queryAggregate":
|
|
185
|
+
if (!query.aggregation) {
|
|
186
|
+
throw new HonuaQueryPlanExecutionError("invalid-plan", "queryAggregate step is missing aggregation intent");
|
|
187
|
+
}
|
|
188
|
+
return source.queryAggregate({ ...query, aggregation: query.aggregation });
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function executeLocal(plan, step, remoteResult, signal) {
|
|
192
|
+
throwIfExecutionAborted(signal);
|
|
193
|
+
if (step.engine !== "client" || step.operation !== "aggregate" || plan.steps.length !== 2) {
|
|
194
|
+
throw new HonuaQueryPlanExecutionError("invalid-plan", "The first planner version supports one bounded local aggregate step");
|
|
195
|
+
}
|
|
196
|
+
if (step.inputStepId !== plan.steps[0]?.id) {
|
|
197
|
+
throw new HonuaQueryPlanExecutionError("invalid-plan", "Local aggregate input does not reference the remote step");
|
|
198
|
+
}
|
|
199
|
+
if (remoteResult.features.length > step.maxRows || remoteResult.exceededTransferLimit) {
|
|
200
|
+
throw new HonuaQueryPlanExecutionError("unsafe-materialization", `Bounded-local input exceeded ${step.maxRows} rows; use server pushdown or a columnar execution engine`);
|
|
201
|
+
}
|
|
202
|
+
if (step.maxBytes !== undefined) {
|
|
203
|
+
throwIfExecutionAborted(signal);
|
|
204
|
+
const actualBytes = new TextEncoder().encode(JSON.stringify(remoteResult.features)).byteLength;
|
|
205
|
+
throwIfExecutionAborted(signal);
|
|
206
|
+
if (actualBytes > step.maxBytes) {
|
|
207
|
+
throw new HonuaQueryPlanExecutionError("unsafe-materialization", `Bounded-local input measured ${actualBytes} bytes, exceeding maxBytes ${step.maxBytes}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const aggregateRows = aggregateLocally(remoteResult.features, step.aggregation, plan.ir.query, signal);
|
|
211
|
+
throwIfExecutionAborted(signal);
|
|
212
|
+
return {
|
|
213
|
+
features: [],
|
|
214
|
+
exceededTransferLimit: false,
|
|
215
|
+
aggregateRows,
|
|
216
|
+
degraded: [
|
|
217
|
+
{
|
|
218
|
+
capability: "queryAggregate",
|
|
219
|
+
reason: `queryAggregate executed locally after enforcing a ${step.maxRows}-row materialization ceiling.`,
|
|
220
|
+
protocol: plan.ir.source.protocol,
|
|
221
|
+
sourceId: plan.ir.source.id,
|
|
222
|
+
},
|
|
223
|
+
],
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function throwIfExecutionAborted(signal) {
|
|
227
|
+
if (signalAborted(signal))
|
|
228
|
+
throw new HonuaAbortError();
|
|
229
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { SourceSchemaV2 } from "../contract/schema.js";
|
|
2
|
+
import { type SemanticCompilationResult } from "./semantic-compiler.js";
|
|
3
|
+
import { type SemanticCompilerFieldMapping } from "./semantic-literals.js";
|
|
4
|
+
import type { SemanticQuery, SourceSpatiality } from "./semantic-types.js";
|
|
5
|
+
import type { CanonicalQuery, GeoServicesCompiledQueryV1, QueryIrSourceIdentity } from "./types.js";
|
|
6
|
+
/**
|
|
7
|
+
* Compile canonical query IR to the existing FeatureServer `query` request
|
|
8
|
+
* vocabulary without performing network or metadata I/O.
|
|
9
|
+
*/
|
|
10
|
+
export declare function compileGeoServicesQuery(source: QueryIrSourceIdentity, query: CanonicalQuery): GeoServicesCompiledQueryV1;
|
|
11
|
+
export type SemanticGeoServicesProtocol = "geoservices-feature-service" | "geoservices-map-service";
|
|
12
|
+
export type SemanticGeoServicesSpatialRelationship = "esriSpatialRelIntersects" | "esriSpatialRelContains" | "esriSpatialRelWithin" | "esriSpatialRelCrosses" | "esriSpatialRelTouches" | "esriSpatialRelOverlaps";
|
|
13
|
+
/** Static, credential-free layer evidence required by semantic GeoServices compilation. */
|
|
14
|
+
export interface SemanticGeoServicesSourceIdentity {
|
|
15
|
+
readonly protocol: SemanticGeoServicesProtocol;
|
|
16
|
+
readonly serviceId: string;
|
|
17
|
+
readonly layerId: number;
|
|
18
|
+
readonly sourceVersion?: string;
|
|
19
|
+
/** Exact relationships advertised by layer metadata. Omission is not treated as support. */
|
|
20
|
+
readonly supportedSpatialRelationships?: readonly SemanticGeoServicesSpatialRelationship[];
|
|
21
|
+
/** Layer-level `supportsAdvancedQueries`; required before emitting orderByFields. */
|
|
22
|
+
readonly supportsAdvancedQueries?: boolean;
|
|
23
|
+
/** `advancedQueryCapabilities.supportsPagination`; required for resultOffset/resultRecordCount. */
|
|
24
|
+
readonly supportsPagination?: boolean;
|
|
25
|
+
/** Layer `supportsStatistics`; required for outStatistics/groupByFieldsForStatistics. */
|
|
26
|
+
readonly supportsStatistics?: boolean;
|
|
27
|
+
/** Explicit layer evidence for resultOffset on statistics requests. */
|
|
28
|
+
readonly supportsPaginationOnAggregatedQueries?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface SemanticGeoServicesCompileOptions<TRecord = Record<string, unknown>, TSpatiality extends SourceSpatiality = SourceSpatiality> {
|
|
31
|
+
readonly query: SemanticQuery<TRecord, SemanticGeoServicesProtocol, TSpatiality>;
|
|
32
|
+
readonly schema: SourceSchemaV2;
|
|
33
|
+
readonly source: SemanticGeoServicesSourceIdentity;
|
|
34
|
+
}
|
|
35
|
+
export interface SemanticGeoServicesSpatialReference {
|
|
36
|
+
readonly wkid?: number;
|
|
37
|
+
readonly wkt?: string;
|
|
38
|
+
}
|
|
39
|
+
export type SemanticGeoServicesGeometry = {
|
|
40
|
+
readonly x: number;
|
|
41
|
+
readonly y: number;
|
|
42
|
+
readonly z?: number;
|
|
43
|
+
} | {
|
|
44
|
+
readonly points: readonly (readonly number[])[];
|
|
45
|
+
} | {
|
|
46
|
+
readonly paths: readonly (readonly (readonly number[])[])[];
|
|
47
|
+
} | {
|
|
48
|
+
readonly rings: readonly (readonly (readonly number[])[])[];
|
|
49
|
+
} | {
|
|
50
|
+
readonly xmin: number;
|
|
51
|
+
readonly ymin: number;
|
|
52
|
+
readonly xmax: number;
|
|
53
|
+
readonly ymax: number;
|
|
54
|
+
};
|
|
55
|
+
/** Canonical pre-image of a GeoServices layer `query` request. */
|
|
56
|
+
export interface SemanticGeoServicesCompiledQueryV1 {
|
|
57
|
+
readonly compiler: "geoservices-sql92-semantic-query-v1";
|
|
58
|
+
readonly dialect: "geoservices-sql92";
|
|
59
|
+
readonly protocol: SemanticGeoServicesProtocol;
|
|
60
|
+
readonly schemaFingerprint: SourceSchemaV2["fingerprint"];
|
|
61
|
+
readonly queryFingerprint: `sha256:${string}`;
|
|
62
|
+
readonly requestFingerprint: `sha256:${string}`;
|
|
63
|
+
readonly serviceId: string;
|
|
64
|
+
readonly layerId: number;
|
|
65
|
+
readonly sourceVersion?: string;
|
|
66
|
+
readonly sqlFormat: "standard";
|
|
67
|
+
readonly where?: string;
|
|
68
|
+
readonly outFields?: readonly string[];
|
|
69
|
+
readonly returnGeometry: boolean;
|
|
70
|
+
readonly returnZ?: boolean;
|
|
71
|
+
readonly returnM?: boolean;
|
|
72
|
+
readonly outSr?: SemanticGeoServicesSpatialReference;
|
|
73
|
+
readonly orderByFields?: string;
|
|
74
|
+
readonly resultOffset?: number;
|
|
75
|
+
readonly resultRecordCount?: number;
|
|
76
|
+
readonly geometry?: SemanticGeoServicesGeometry;
|
|
77
|
+
readonly geometryType?: "esriGeometryPoint" | "esriGeometryMultipoint" | "esriGeometryPolyline" | "esriGeometryPolygon" | "esriGeometryEnvelope";
|
|
78
|
+
readonly inSr?: SemanticGeoServicesSpatialReference;
|
|
79
|
+
readonly spatialRel?: SemanticGeoServicesSpatialRelationship;
|
|
80
|
+
readonly outStatistics?: readonly {
|
|
81
|
+
readonly statisticType: "count" | "sum" | "avg" | "min" | "max" | "stddev" | "var";
|
|
82
|
+
readonly onStatisticField: string;
|
|
83
|
+
readonly outStatisticFieldName: string;
|
|
84
|
+
}[];
|
|
85
|
+
readonly groupByFieldsForStatistics?: string;
|
|
86
|
+
readonly fieldMappings: readonly SemanticCompilerFieldMapping[];
|
|
87
|
+
readonly usesNativeFilter: boolean;
|
|
88
|
+
}
|
|
89
|
+
/** Compile a validated semantic AST to an exact GeoServices SQL-92 request. */
|
|
90
|
+
export declare function compileSemanticGeoServicesQuery<TRecord, TSpatiality extends SourceSpatiality>(options: SemanticGeoServicesCompileOptions<TRecord, TSpatiality>): SemanticCompilationResult<SemanticGeoServicesCompiledQueryV1>;
|
|
91
|
+
//# sourceMappingURL=geoservices.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geoservices.d.ts","sourceRoot":"","sources":["../../../src/query-planner/geoservices.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAQV,cAAc,EACf,MAAM,uBAAuB,CAAC;AAK/B,OAAO,EAEL,KAAK,yBAAyB,EAO/B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,KAAK,4BAA4B,EAWlC,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAe,aAAa,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,KAAK,EAAE,cAAc,EAAE,0BAA0B,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAGpG;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,qBAAqB,EAC7B,KAAK,EAAE,cAAc,GACpB,0BAA0B,CAmE5B;AAsBD,MAAM,MAAM,2BAA2B,GAAG,6BAA6B,GAAG,yBAAyB,CAAC;AAEpG,MAAM,MAAM,sCAAsC,GAC9C,0BAA0B,GAC1B,wBAAwB,GACxB,sBAAsB,GACtB,uBAAuB,GACvB,uBAAuB,GACvB,wBAAwB,CAAC;AAE7B,2FAA2F;AAC3F,MAAM,WAAW,iCAAiC;IAChD,QAAQ,CAAC,QAAQ,EAAE,2BAA2B,CAAC;IAC/C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,4FAA4F;IAC5F,QAAQ,CAAC,6BAA6B,CAAC,EAAE,SAAS,sCAAsC,EAAE,CAAC;IAC3F,qFAAqF;IACrF,QAAQ,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAC3C,mGAAmG;IACnG,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC,yFAAyF;IACzF,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC,uEAAuE;IACvE,QAAQ,CAAC,qCAAqC,CAAC,EAAE,OAAO,CAAC;CAC1D;AAED,MAAM,WAAW,iCAAiC,CAChD,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,WAAW,SAAS,gBAAgB,GAAG,gBAAgB;IAEvD,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,EAAE,2BAA2B,EAAE,WAAW,CAAC,CAAC;IACjF,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,iCAAiC,CAAC;CACpD;AAED,MAAM,WAAW,mCAAmC;IAClD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,2BAA2B,GACnC;IAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/D;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAA;CAAE,GACnD;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAA;CAAE,GAC/D;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAA;CAAE,GAC/D;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnG,kEAAkE;AAClE,MAAM,WAAW,kCAAkC;IACjD,QAAQ,CAAC,QAAQ,EAAE,qCAAqC,CAAC;IACzD,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,2BAA2B,CAAC;IAC/C,QAAQ,CAAC,iBAAiB,EAAE,cAAc,CAAC,aAAa,CAAC,CAAC;IAC1D,QAAQ,CAAC,gBAAgB,EAAE,UAAU,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,kBAAkB,EAAE,UAAU,MAAM,EAAE,CAAC;IAChD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,mCAAmC,CAAC;IACrD,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,2BAA2B,CAAC;IAChD,QAAQ,CAAC,YAAY,CAAC,EAClB,mBAAmB,GACnB,wBAAwB,GACxB,sBAAsB,GACtB,qBAAqB,GACrB,sBAAsB,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,mCAAmC,CAAC;IACpD,QAAQ,CAAC,UAAU,CAAC,EAAE,sCAAsC,CAAC;IAC7D,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS;QAChC,QAAQ,CAAC,aAAa,EAAE,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,KAAK,CAAC;QACnF,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;QAClC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;KACxC,EAAE,CAAC;IACJ,QAAQ,CAAC,0BAA0B,CAAC,EAAE,MAAM,CAAC;IAC7C,QAAQ,CAAC,aAAa,EAAE,SAAS,4BAA4B,EAAE,CAAC;IAChE,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACpC;AA0BD,+EAA+E;AAC/E,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,WAAW,SAAS,gBAAgB,EAC3F,OAAO,EAAE,iCAAiC,CAAC,OAAO,EAAE,WAAW,CAAC,GAC/D,yBAAyB,CAAC,kCAAkC,CAAC,CAgD/D"}
|