measure.approx_count_distinct(field)estimates a distinct count with ClickHouseuniq(uniqIfwith measure filters), far cheaper than the exactcount_distinct(uniqExact) on large columns. Catalogs and semantic contracts mark it, and derived measures that use it,approximate: true, as TypeScript does; it is duplicate-insensitive throughbelongs_to. Publishing it is refused until deployment contract 3, as in TypeScript.Exported client contracts keep
isNullandisNotNullon boolean filters that allow them (RFC 0023), instead of dropping them.Documentation for the ported ClickHouse features: null checks, aggregate states, row resolution, segments, window and shift measures, in the Python datasets pages and the package README. A shared execution corpus (
specs/datasets/time-measures-corpus-v1.json) now checks Python's window and shift results row for row against TypeScript.measure.shiftcan wrap a window, a derived measure or another shift, as in TypeScript: a prior-year year-to-date, a shifted average order value, orshift(shift(x)). The wrapped measure is recalculated over the earlier interval, and shifted formulas divide shifted aggregates. Derived measures over derived measures that read windows or shifts are now planned too, instead of refused. Definitions reject dependency cycles through shifts and formulas, and catalogs report the grains both the shift and its input support. A shifted formula has no single aggregation, so its catalog and semantic contract entries omitaggregationandfield, hashing the same as TypeScript. A query is refused asinput-invalidwhen nested shifts would need more than 64 evaluation contexts or 1024 evaluated measures.client.stream(target, query)andclient.stream_arrow(target, query)stream a dataset query's result instead of returning it whole, so memory stays flat however many rows there are.streamyields batches of the rowsexecutereturns;stream_arrowyieldspyarrow.RecordBatches with ClickHouse's native column types (decimal128,uint64), withread_all()andto_reader()for DuckDB, polars and pandas (hypequery[arrow]). Both run the queryexecutewould, under the same settings, tenant scope, deadline and cancellation, without the cache or pagination. Use them as context managers (async withon the async client): closing a stream early stops the query, withKILL QUERYwhere a control connection is configured. Every ClickHouse and chDB executor streams; a result that grows pastmax_result_rowsormax_result_bytesfails astoo-largerather than ending short. Custom executors stream by implementing the newStreamingQueryExecutorprotocol.Streams have ceilings of their own.
DatasetLimits(max_stream_rows=...)lets a dataset allow streams more rows than the pages and agentsmax_result_sizebounds; a stream with nolimitruns under that ceiling as itsLIMITand ends there. A stream's memory stays flat, so its byte limit isstream_max_result_bytes, a newcreate_dataset_clientoption of at most 1 TiB. Without it, a stream keeps amax_result_bytesthe client's settings set and runs under 1 TiB in place of the default.max_result_rowsandmax_execution_timestill bound it, and a request context can still tighten all three.
Changelog
Every release across the hypequery packages and the Python SDK, newest first.
hypequery (Python)v0.1.0b4Pre-release 15 more changes in this release →@hypequery/servev0.25.0Minor Minor changes
- b99de97
Type dimension values in dataset and metric result rows (
DatasetRow,DatasetRowFor,MetricRow,MetricRowFor, and the results ofcreateDatasetClient(...).execute()) as what queries actually return. Numeric dimensions are nownumber | string | null, because the built-in ClickHouse adapter returnsInt64,UInt64and wider integers as JSON strings to keep their precision. Every dimension, andperiod, also includesnull, becauseNullablecolumns return SQL NULL. A newDimensionResultValue<T>type describes these values;@hypequery/servere-exports it.InferDimensionTypeis unchanged and still describes a dimension's declared type.This is a breaking type change. Code that read a numeric dimension as
number, or any dimension orperiodwithout handlingnull, now fails to compile. Convert withNumber(value)orBigInt(value)as needed, and check fornull. - 27f2580
Dataset endpoints can stream their results. Opt an entry in with
stream: trueorstream: { maxRows }(defaultmaxLimit, at most the dataset'slimits.maxStreamRows, elselimits.maxResultSize); a request then asks withAccept: application/x-ndjsonfor row batches as NDJSON frames (start,rows…, thenendwithrowCount, or anerrorframe if the query fails after the response began) orAccept: application/vnd.apache.arrow.streamfor an Arrow IPC stream. Streams keep the endpoint's auth, tenant isolation and validation, are never cached, and stop the query when the client disconnects. Endpoints withoutstream, and requests that don't ask, get the usual JSON page. Custom handlers can stream any body by returningstreamBody(stream, contentType); the Node and fetch adapters write it with backpressure.NDJSON_MEDIA_TYPEandARROW_STREAM_MEDIA_TYPEare exported. - ae3a5fd
TypeScript serve APIs can now export a client contract and enforce its schema pin.
api.clientContract()returns the build view of every dataset endpoint and measure-backed metric endpoint, with full paths and schema hashes.hypequery generate:clientturns it into typed React hooks for a frontend in another repository. SetclientContract: { mountPath }when the API is mounted below a prefix. Eachdatasetsandmetricskey must be the dataset's or metric's own name. Metrics with a fixed grain (metric.by(grain)) aren't advertised.- A request that sends
X-Hypequery-Client-Schemais checked before input validation. A stale hash gets409 VALIDATION_ERRORwithdetails.code: 'CLIENT_SCHEMA_CHANGED'. A matching hash runs under the strict client profile, and its response metadata is limited torequestId,timingMs,rowCount,paginationandcache.hit, as in Python. Requests without the header behave as before. - The default CORS allow-headers now include
X-Hypequery-Client-Schema.
1 more change in this release →Patch changes
- 8c5e6d2
Fix
extractClientConfig(api)returning paths without the API's base path and ignoringapi.route(...)overrides (for example/queries/helloinstead of/api/analytics/queries/hello), which sent React hooks configured from it to URLs that 404. It now returns the same routes asapi.manifest().extractClientConfigis deprecated in favour ofapi.manifest(), which@hypequery/reactaccepts directly asmanifest. - c320820
With a required tenant, the built-in
/openapi.json,/docsand semantic/contractendpoints returned 403 for any request without a tenant, including signed-in users without one. These endpoints only describe the API and read no tenant data, so they now skip tenant resolution. Every query, dataset and discovery endpoint still requires the tenant. - 89cb73f
Fix four issues found running serve against a live ClickHouse:
createFetchHandler(and the Vercel edge handler and Next.js mounts built on it) threwInvalid response status code 204on CORS preflight requests. Responses with 204, 205, and 304 now have no body.serve({ metrics })andserve({ datasets })threw "queryBuilderis required" when the builder came fromcontext: () => ({ db }), the form the docs lead with. Semantic endpoints now use each request'sctx.db. A request whose context returns nodbfails instead of using another request's builder.tenant: { column }withoutmodesilently skipped tenant filtering, becausemodedefaulted to'manual', which ignorescolumn. Setting acolumnnow defaultsmodeto'auto-inject'. Passmode: 'manual'to keep filtering in your own queries.createAnalyticsTokenIssuercould not mint scopes, so its tokens never satisfiedrequiredScopes. It now acceptsscopesand writes them as the standardscopeclaim.
@hypequery/protocolv0.25.0Minor Minor changes
- d8829e6
Portable semantic queries accept
havingandtimezone(RFC 0025), so a host running through the semantic data plane can execute what the MCPquery_datasettool and client contracts already advertise.@hypequery/protocol:validateProtocolSemanticQueryacceptshaving(dataset queries; each condition names a selected measure, with a numeric comparison) andtimezone(RFC 0018's pinned registry) under extensions 1 and 2. NewProtocolHavingConditionandProtocolHavingComparisonOperatortypes. Cache preimages refuse a non-emptyhavingor a non-UTCtimezonerather than leave them out of the key;"UTC"normalizes as if absent, so no existing preimage changes.@hypequery/deployment: the semantic data plane countshavingconditions againstmaxFilterstogether with filters and enforced constraints, refuses atimezoneon a dataset with no visible time field, and refuseshavingon a hidden measure exactly as it refuses selecting one.@hypequery/datasets: the portable executor passeshavingandtimezoneto the dataset client.
@hypequery/clickhousev2.15.0Minor Minor changes
- c320820
Aggregate result types now match what ClickHouse returns, instead of
stringfor every aggregate:sum():numberforFloat*andDecimalcolumns,stringfor integer columns (they widen to a quotedInt64), plus| nullforNullablecolumns. Over a subquery or CTE column known only asnumber, it isnumber | string.avg(),stddev(),variance():number | null. NaN over too few rows arrives asnull.min(),max(),argMin(),argMax(): the column's own type.quantile():number | nullfor numeric columns, the column's type for dates.count(),countDistinct(),approxCountDistinct(): unchanged (string).
Code that converted results with
Number(...)keeps compiling. Code that called string methods on, for example, aFloat64sum now gets a type error where it used to fail at runtime.Schemas can now declare
AggregateFunction(...)andSimpleAggregateFunction(fn, T)columns, so a generated schema containing an AggregatingMergeTree table type-checks withcreateQueryBuilder<IntrospectedSchema>(). ASimpleAggregateFunction(fn, T)column hasT's type; anAggregateFunctioncolumn is an opaque state that you read withmergeState().GROUP BY inference no longer adds a selected expression that wraps an aggregate (
round(avg(x), 2)) or a window function (rank() OVER (ORDER BY sum(x))), which ClickHouse rejected with "Aggregate function ... is found in GROUP BY".The readonly error for the precision-safe 64-bit setting now names the fixes that keep precision: setting
output_format_json_quote_64bit_integers = 1in the user's profile, orreadonly = 2.integerJsonEncoding: 'server-default'is still offered as the fallback.The legacy
hypequery-generate-typesgenerator types parameterized views, and typesSimpleAggregateFunctioncolumns by their value type, as@hypequery/clinow does. - 3bb485c
Stream results as Arrow.
builder.streamArrow()anddb.rawArrowStream(sql, params)return the result as Arrow IPC stream bytes (ClickHouseArrowStream) with native column types, for any Arrow reader to decode or for passing on unchanged. Batches are uncompressed by default, because JavaScript Arrow readers don't include the LZ4 codec; a connection-level or per-calloutput_format_arrow_compression_methodoverrides that.db.rawStream(sql, params)streams a raw statement's rows, asbuilder.stream()does for built queries. If ClickHouse fails after sending part of an Arrow result, the stream errors rather than handing the exception text to the decoder: with ClickHouse's own error on ClickHouse 25.11 or later, which marks the failure, and on older servers because the bytes end without Arrow's end-of-stream marker. Custom adapters can implement the new optionalDatabaseAdapter.streamArrow. - c320820
Fix JavaScript
Datefilter values againstDateTimesorting-key columns. ADateused to render as a quoted ISO string ('2026-03-01T00:00:00.000Z'), which ClickHouse rejects withTYPE_MISMATCHwhen it compares the string with aDateTimecolumn in the sorting key. The same happened for aDatecolumn, and for any value with milliseconds. ADatenow renders astoDateTime('2026-03-01 00:00:00', 'UTC'), or astoDateTime64(..., 3, 'UTC')when it has milliseconds or falls outside theDateTimerange. This keeps the exact UTC instant, still lets the primary index prune, and works inINlists. It applies towhere,between,in,rawQueryplaceholders andCrossFilter.CrossFilterno longer convertsDatevalues to ISO strings itself. Dates inside array, tuple and map parameters are still sent as ISO text, whichCASTparses correctly.
Patch changes
- 0ba4596
Arrow streams work for
readonly = 1users and catch mid-stream failures on servers before ClickHouse 25.11.streamArrow()andrawArrowStream()request the format with aFORMAT ArrowStreamclause instead of thedefault_formatsetting, whichreadonly = 1users may not change. A trailing;or comment is dropped first.- The uncompressed-batches default (
output_format_arrow_compression_method = 'none') is still sent, and areadonly = 1user accepts it when its profile already sets that value. When ClickHouse rejects it, the error explains the fix. The newarrowCompression: 'server-default'adapter option leaves the setting out, so batches use the server's compression method. - Detecting a mid-stream failure from its tagged exception block needs ClickHouse 25.11 or later, because older servers send no
X-ClickHouse-Exception-Tag. An Arrow stream from any server now also errors when its bytes end without Arrow's end-of-stream marker, so a failed or truncated stream no longer looks complete. On older servers, ClickHouse's error message is recovered from the response where possible.
- 3bb485c
stream()no longer hangs when an adapter's byte stream splits a JSON row across two chunks, keeps a final row that has no trailing newline, and keeps characters split across chunks intact. The built-in adapter was unaffected because its client hands over whole rows; custom adapters that stream raw bytes were.
@hypequery/cliv1.29.0Minor Minor changes
- 2d4f9aa
Add
hypequery skill install: writes hypequery's agent skills (hypequery-datasets,hypequery-query) where Claude Code (.claude/skills/), Cursor and Codex (.agents/skills/) load them.--agent,--scope project|user,--checkfor CI and--force; re-runs are idempotent and edited skills are never replaced without--force. - 524bcf5
Running
hypequerywith no command in an interactive terminal now startshypequery initinstead of printing help, sonpx hypequerytakes new users straight into setup. A one-line hint points tohypequery --helpfor the full command list. When the CLI is not attached to a terminal (scripts, CI, piped input), the bare command still prints help and exits with code 1, so nothing waits on a prompt. - fbe9482
generate:datasetsandinit --style datasetsnow read each table's engine fromsystem.tables, so scaffolded datasets no longer count rows ClickHouse hasn't merged yet. ReplacingMergeTree tables getrowResolution: { kind: 'final', engine: 'replacing' }(withdeletedColumnwhen the engine has one), and CollapsingMergeTree / VersionedCollapsingMergeTree tables get the matchingsignColumnresolution. Version, sign and deleted columns are no longer summed or averaged. Pre-aggregated tables drop the row-count measure:AggregateFunctioncolumns becomemeasure.merge(...)measures (parametric states such asquantile(0.9)are noted and skipped),SimpleAggregateFunction(sum|min|max, …)columns use that function, and SummingMergeTree tables sum only their summing columns (without a list, numeric columns outside the sorting key). If the engines can't be read, tables are scaffolded as before. - ae3a5fd
Add
hypequery export:client-contract <api-file>. It writes the client contract of a TypeScript serve API (client-contract.jsonby default) forhypequery generate:client, with--output,--stdout,--checkand--force, matching Python'shypequery export client-contract. Like Python, it refuses a contract with no endpoints.
2 more changes in this release →Patch changes
- 89cb73f
Report ClickHouse connection failures accurately:
generate,generate:datasets, anddevno longer report "Connected to ClickHouse" with 0 tables when the database is unreachable or rejects the credentials. They now show the real error.- A refused connection now shows its message and troubleshooting hints instead of an empty error.
- The ClickHouse client's raw stack-trace logging is off, so commands show only their own error output.
hypequery devshowed Docs and OpenAPI URLs without the base path forcreateAPIentries (for example/docsinstead of/api/analytics/docs). It now shows the routes the API actually serves.
- 141f0b6
hypequery --helpnow describes the CLI as "Type-safe embedded analytics on ClickHouse", matching the website and README.
@hypequery/deploymentv0.12.0Minor Minor changes
- d8829e6
Portable semantic queries accept
havingandtimezone(RFC 0025), so a host running through the semantic data plane can execute what the MCPquery_datasettool and client contracts already advertise.@hypequery/protocol:validateProtocolSemanticQueryacceptshaving(dataset queries; each condition names a selected measure, with a numeric comparison) andtimezone(RFC 0018's pinned registry) under extensions 1 and 2. NewProtocolHavingConditionandProtocolHavingComparisonOperatortypes. Cache preimages refuse a non-emptyhavingor a non-UTCtimezonerather than leave them out of the key;"UTC"normalizes as if absent, so no existing preimage changes.@hypequery/deployment: the semantic data plane countshavingconditions againstmaxFilterstogether with filters and enforced constraints, refuses atimezoneon a dataset with no visible time field, and refuseshavingon a hidden measure exactly as it refuses selecting one.@hypequery/datasets: the portable executor passeshavingandtimezoneto the dataset client.
@hypequery/mcpv0.12.0Minor Minor changes
- a649997
Hosted error details on MCP tool errors:
MCPToolErrorand its published error envelope carry optionalretryAfterSeconds,relistandreason(a host's own stable code), and a newMCP_RATE_LIMITEDcode (categorybudget, retryable).mcpToolErrorFromSemanticFailuremaps a semantic data-plane failure to the MCP error an agent receives, andcreateMCPErrorResponseis exported so hosts build tool errors exactly as the local server does.
Patch changes
- 148b262
Describe the package as a ClickHouse MCP server in its npm description, keywords and README, with a link to the five-minute quickstart.
- 75648f9
Add
mcpName(io.github.hypequery/hypequery) to the package manifest and aserver.json, so the server can be published to the official MCP Registry. The build and the release version step write the package version intoserver.json, since the registry verifiesmcpNameagainst the npm release it names. No runtime change.
@hypequery/datasetsv0.30.0Minor Minor changes
- 872713e
buildClientContractno longer advertiseshavingpredicates or a per-requesttimezoneby default. They are off unless the host's route passes them through to the data plane: a route that builds its operation from a fixed list of fields drops them, so a generated client could send them and get unfiltered rows. Hosts that pass them through opt in withcapabilities: { having: true, timezone: true }.Both flags are part of each endpoint's hashed schema, so upgrading moves the
schemaHashof every endpoint with a time field or a numeric measure. Regenerate clients (hypequery generate:client) after upgrading; until thengenerate:client --checkreports drift, and a host that validates requests against the new contract refuses an old client'stimezoneinstead of ignoring it. - b99de97
Type dimension values in dataset and metric result rows (
DatasetRow,DatasetRowFor,MetricRow,MetricRowFor, and the results ofcreateDatasetClient(...).execute()) as what queries actually return. Numeric dimensions are nownumber | string | null, because the built-in ClickHouse adapter returnsInt64,UInt64and wider integers as JSON strings to keep their precision. Every dimension, andperiod, also includesnull, becauseNullablecolumns return SQL NULL. A newDimensionResultValue<T>type describes these values;@hypequery/servere-exports it.InferDimensionTypeis unchanged and still describes a dimension's declared type.This is a breaking type change. Code that read a numeric dimension as
number, or any dimension orperiodwithout handlingnull, now fails to compile. Convert withNumber(value)orBigInt(value)as needed, and check fornull. - 3bb485c
Stream dataset and metric results.
createDatasetClient(...).stream(target, query, context)returns{ data, meta }, wheredatais aReadableStreamof row batches with the same row types and wire values asexecute(), so memory stays flat however many rows there are.streamArrow(target, query, context)returns the result as Arrow IPC stream bytes with native column types. Both apply the same validation and tenant scoping asexecute(). Their row ceiling islimits.maxResultSize, or the newlimits.maxStreamRowswhere a dataset declares one, so exports can be allowed more rows than pages and agents;meta.resultLimitreports when the ceiling bounded a query. Streams skip the result cache and report no pagination. They need@hypequery/clickhouse2.15.0 or later; the query builder protocol gains optionalstream,streamArrow,rawStreamandrawArrowStreammethods. - ae3a5fd
Add
buildDatasetClientContract(endpoints, { mountPath }). It builds an RFC 0018 client contract from dataset definitions and metrics. It mirrors Python'sexport_client_contract, so an equivalent definition exports the same contract in both languages.
2 more changes in this release →Patch changes
- 8d02067
Client contracts built from a deployment keep
isNullandisNotNullon boolean filters that allow them, as RFC 0023 specifies. They were previously dropped, so a boolean filter allowing only null checks disappeared from the contract. - 4c7cc13
A relationship join to a resolved (
FINAL) target whose deleted column is named_hq_matchno longer drops every target row: the join's match marker now avoids the current-row column's name.
@hypequery/reactv0.9.0Minor Minor changes
- a6b4478
Type dataset and metric dimension values from
InferApiTypeAPIs as what serve actually returns. Numeric dimensions are nownumber | string | null, because the built-in ClickHouse adapter returnsInt64,UInt64and wider integers as JSON strings to keep their precision. Every dimension, andperiod, also includesnull, becauseNullablecolumns return SQL NULL. Types from generated clients already followed these rules.This is a breaking type change. Code that read a numeric dimension as
number, or any dimension without handlingnull, now fails to compile. Convert withNumber(value)orBigInt(value)as needed, and check fornull.
hypequery (Python)v0.1.0b3Pre-release 9 more changes in this release →Datasets can run on embedded ClickHouse with the new
chdbextra:create_chdb_executor(path)(andcreate_async_chdb_executor) execute the same compiled, read-only, parameter-bound SQL in-process on chDB, with no server.pathis an on-disk directory or":memory:";database=sets where unqualified sources resolve. Results decode exactly as from a ClickHouse server.hypequery init --database chdbscaffolds a project on embedded ClickHouse, as the TypeScript CLI does: the standalone or FastAPI app opens a chDB database directory (--chdb-path, defaultanalytics.chdb) with no server or connection settings, and installs thechdbextra. An existing database is inspected like a server's; a new one gets the orders example and a seeding step.hypequery generate datasetsreads the same database from--chdb-path, the path init records inpyproject.toml, or a projectanalytics.chdbwhen no ClickHouse server is configured, and says plainly when another process such ashypequery devhas the database open.hypequery devserves a chDB project with reload, its default: the supervisor that checks the app before starting the worker now releases the app's database, since chDB holds a database directory for one process at a time (run_dev(reload=True)does the same; other chDB executors in the process stay open).The CLI now collects pseudonymous usage telemetry, on by default like the TypeScript CLI: one event per command with the command, flag names (never values), outcome, a duration bucket, and install context such as the Python version and installer. It never records code, SQL, names, paths or credentials, and never delays a command. Disable it with
hypequery telemetry disable,--no-telemetry,DO_NOT_TRACK=1orHYPEQUERY_TELEMETRY_DISABLED=1; setHYPEQUERY_TELEMETRY_DEBUG=1to print the event instead of sending it. Settings and the install ID are shared with the TypeScript CLI.New
hypequery telemetry [status|enable|disable]command and global--no-telemetryflag.create_api(client_profile=...)puts everyDatasetentry ofdatasets=in the client contract, so the shorthand can produce typed React hooks.
@hypequery/servev0.24.4Patch Patch changes
- 934b6ce
Type
ctx.tenantIdon the query resolver context. The pipeline already set it at runtime when atenantconfig extracts a tenant ID, butQueryRuntimeContextdid not declare it, so manual-mode resolvers readingctx.tenantIdfailed to type-check. Also corrects thecreateAuthSystemJSDoc example, which passed an options object to a function that takes only type parameters.
hypequery (Python)v0.1.0b2Pre-release 11 more changes in this release →hypequery initis guided in a terminal, as the TypeScript CLI is. It asks for whatever its flags leave unset: where to create the project; how to reach ClickHouse (the connection already in your environment, or a URL and credentials typed in, with the password hidden, used only to read the schema and never written to a file); which tables, when the database has more than ten; the tenant column, when one looks like a tenant id; and which app to scaffold, defaulting to FastAPI, Django or Flask when it finds one. A failed connection offers to try again, change the details, or create the offline example. It ends with the same choices as flags. Every flag answers its question, and--no-interactive, aCIenvironment variable, or input that is not a terminal skip the questions and keep the previous behavior.The
hypequeryCLI loads.env.localand.envfrom the directory it runs in, as the TypeScript CLI does. A variable already set wins over both files. The library and generated apps still read only the real environment;hypequery.cli.load_env_files(directory)applies the same rules in your own scripts, such as the scaffold README's seed step.When init can't reach ClickHouse, the message names
CLICKHOUSE_URLas well as the host settings and suggests--skip-connection, and the driver's own "Unexpected Http Driver Exception" log line no longer reaches the terminal.hypequery init --framework fastapiscaffolds a FastAPIapp.py: the bearer-token agents API mounted at/api/agents, and/analytics/<dataset>, a route of your own that refuses everyone until itscurrent_principaldependency reads your login. The project depends onfastapidirectly; hypequery adds no FastAPI extra.Declaring
filterson a dataset no longer makes its other dimensions unfilterable (RFC 0024), matching TypeScript. Callers may filter on every declared filter and every dimension not markedfilterable=False. A dimension's own filter takes the operators of the filters declared on its field, so declaringplan_filteronplanwithoperators=("eq",)also limitsplantoeq. Relationship filters reach every filterable, non-SQL dimension of abelongs_toorhas_onetarget. An explicit emptyfilters={}no longer disables filtering; mark a dimensionfilterable=Falseto keep it out. Catalogs, client contracts and deployment contracts are unchanged.Base dataset columns are always qualified (
__hq_base), not only when a relationship join is present. ClickHouse resolves an output alias before a column of the same name, so a dimensionstatusreading columncountrycaptured a filter or selection on the realstatuscolumn (silent wrong rows), and a measure named like its column (amount=measure.sum("amount")) broke any other measure or filter on that column.
@hypequery/datasetsv0.29.0Minor Minor changes
- 86f9207
Declaring
filterson a dataset no longer makes the rest of its dimensions unfilterable. A dataset's filterable fields are now its declared filters plus every dimension not markedfilterable: false(RFC 0024). A dimension that no declared filter is named after accepts the default operators, without null checks, unless filters declared on it list operators, in which case it takes theirs: declaringplan_filteronplanwithoperators: ['eq']also limitsplantoeq.Relationship filters reach every filterable, non-SQL dimension of a
belongsToorhasOnetarget. Rehydrated deployment contracts, whose filter map lists only the declared filters, follow the same rule. Validation, enforced constraints,buildDatasetInputSchemaand theDatasetFilterFortypes all agree.This widens what queries accept. To keep a dimension out of filters, mark it
filterable: false; an explicit emptyfiltersmap no longer disables filtering. Published catalogs and contracts are unchanged.
@hypequery/cliv1.28.0Minor Minor changes
- 0f1f056
hypequery generate:client --cloudgenerates typed React routes and types from the live Cloud release of the target chosen withhypequery login(or--project,--environmentand--endpointwithHYPEQUERY_API_TOKEN). The file also exportsclientBaseUrl, the origin the environment is served from.deploy --client <path>regenerates that file after each live publish; if regeneration fails, the deploy still succeeds and the CLI prints the command to retry.
Patch changes
- a7cf856
hypequery deployanddeployment:buildwarn when a served dataset has a customer-like column (tenant_id,org_id,organization_id,organisation_id,account_id,customer_id,workspace_idorcompany_id) in a dimension, measure or filter, and neither the dataset nor its endpoint is scoped by tenant. Without that, every caller can read every customer's rows. The warning names thetenantKeyline to add, or says to mark the dataset shared in Cloud. Thecloud.tsscaffold now explains what empty roles and scopes allow.
@hypequery/reactv0.8.0Minor Minor changes
- 0f1f056
Requests from a generated client that the server refuses with
409 CLIENT_SCHEMA_CHANGEDnow throwClientSchemaChangedError, a subclass ofHttpError, whose message says to regenerate the client.
@hypequery/mcpv0.11.2Patch Patch changes
- 17ffe2b
Strict client-query rejections say where they failed.
validateProtocolClientQuerynow sets a JSON Pointer on everyHQ_CLIENT_QUERYerror (/filters/0/value,/orderBy/1/field,/grainfor agents) instead of the root for most of them. Pointers name contract members and item indexes only; an unknown member is still reported at the root because its name is submitted data. The shared conformance fixtures pin the pointers for TypeScript and Python.The typed endpoint schemas from
buildClientContractQuerySchemascarry the pointer as the zod issue path, and the MCP HTTP bridge names it in its error message (Invalid client query at /filters/0/value.).
@hypequery/datasetsv0.28.0Minor Minor changes
- 4847c9c
Add
buildClientContract(deployment, options), which turns a deployment contract (for examplepublishToCloud's output) into a hashed client contract thathypequery generate:clientreads. It follows the Python builder's rules: unknown nullability for local fields, tenant-key filters never advertised, operators narrowed by field type, portable time grains, and limits narrowed by each dataset. Relationship fields are not exported yet. Hosts pass their own routes, query ceilings and default timezone;view: 'authorized'withincludemarks a caller's view;includefilters whole datasets only, so field-level narrowing stays with the host. Only datasets with an endpoint are exported, and a dataset with a field namedperiodalongside a time field is rejected.
Patch changes
- 17ffe2b
Strict client-query rejections say where they failed.
validateProtocolClientQuerynow sets a JSON Pointer on everyHQ_CLIENT_QUERYerror (/filters/0/value,/orderBy/1/field,/grainfor agents) instead of the root for most of them. Pointers name contract members and item indexes only; an unknown member is still reported at the root because its name is submitted data. The shared conformance fixtures pin the pointers for TypeScript and Python.The typed endpoint schemas from
buildClientContractQuerySchemascarry the pointer as the zod issue path, and the MCP HTTP bridge names it in its error message (Invalid client query at /filters/0/value.). - 2b5ff4e
Three planner fixes that change results:
- Base dataset columns are always qualified with the dataset source, not only
when a relationship join is present. ClickHouse resolves an output alias
before a column of the same name, so a dimension
statusreading columncountrycaptured a filter or selection on the realstatuscolumn (silent wrong rows), and a measure named like its column (amount: measure.sum('amount')) broke any other measure or filter on that column withILLEGAL_AGGREGATION. - Under a runtime scope of several tenants (
{ in: [...] }) or all tenants ({ scope: 'all' }), relationship joins also match the tenant keys, so a key reused by another tenant no longer joins that tenant's row.checkRelationshipscounts (key, tenant) pairs under those scopes to match. Single-tenant SQL is unchanged. - Formula
dividecasts the dividend to Float64. Decimal division kept the dividend's scale and truncated, soround(divide(revenue, nullIfZero(orders)), 2)could come out one cent low and a Decimal share such as 0.685 read 0.68.
- Base dataset columns are always qualified with the dataset source, not only
when a relationship join is present. ClickHouse resolves an output alias
before a column of the same name, so a dimension
@hypequery/protocolv0.24.2Patch Patch changes
- 17ffe2b
Strict client-query rejections say where they failed.
validateProtocolClientQuerynow sets a JSON Pointer on everyHQ_CLIENT_QUERYerror (/filters/0/value,/orderBy/1/field,/grainfor agents) instead of the root for most of them. Pointers name contract members and item indexes only; an unknown member is still reported at the root because its name is submitted data. The shared conformance fixtures pin the pointers for TypeScript and Python.The typed endpoint schemas from
buildClientContractQuerySchemascarry the pointer as the zod issue path, and the MCP HTTP bridge names it in its error message (Invalid client query at /filters/0/value.).
@hypequery/cliv1.27.0Minor Minor changes
- 07bc05f
Support
deploy --draft <name>anddeployment:submit --draft <name>for named Cloud code drafts. Draft uploads preserve Production, validate the returned draft and staging URL, and print staging details instead of Production endpoints.
Patch changes
- 6652388
generate:clientnames the output path it refuses, and why: the symbolic link or non-directory ancestor it found, with the same path written without the link (for example/tmp→/private/tmpon macOS). An ancestor that is a file is now reported as such, not as a bareENOTDIR. - 21171cf
Name the field when a client contract has one this version doesn't know.
ProtocolClientContractErrorgains an optionalfield: forHQ_CLIENT_UNKNOWN_FIELD, the first unknown member atpath(whose value, the parent object, is unchanged).hypequery generate:clientreports where it is (for example/endpoints/0/annotations) and suggests upgrading@hypequery/cli, since the contract usually comes from a newer hypequery. - 19c3de0
generate:datasetsnow maps ClickHouse column types by their exact outer type, the same mapping Cloud uses, instead of by substring. PreviouslyPoint,Array(Int32)andTuple(Float64, Float64)becamedimension.number()(with sum/avg measures), andArray(String)andMap(...)becamedimension.string(), so the generated catalog advertised scalars that queries then failed on. Each scalar element of a namedTuplenow becomes its own dimension throughtupleElement, named<column><Element>(pickupCity). Other composite columns (Array, Map, unnamed Tuple, geo, JSON) are left out with a comment in the generated file. Only date/time-typed columns are picked astimeKey, andtotalCountcounts a column that is actually a dimension.Generated field names no longer clash. A field name is also its SQL alias, and ClickHouse resolves an alias before a column of the same name, so a field only takes a source column's name when it reads exactly that column. Otherwise it takes a numeric suffix (
fareTotal2), with a comment saying why: with columnsfare_totalandfareTotal, the realfareTotalcolumn keeps its name. Measure names (totalCount,totalX,avgX) follow the same rule, so acountcolumn or afare/Farepair no longer produces duplicate keys.
@hypequery/protocolv0.24.1Patch Patch changes
- 21171cf
Name the field when a client contract has one this version doesn't know.
ProtocolClientContractErrorgains an optionalfield: forHQ_CLIENT_UNKNOWN_FIELD, the first unknown member atpath(whose value, the parent object, is unchanged).hypequery generate:clientreports where it is (for example/endpoints/0/annotations) and suggests upgrading@hypequery/cli, since the contract usually comes from a newer hypequery.
@hypequery/servev0.24.1Patch Patch changes
- eb75fc2
Node adapter (
createNodeHandler) now works inside Express, NestJS and Fastify without workarounds:- Routes on
req.originalUrlwhen a framework sets it, soapp.use('/api/analytics', createNodeHandler(api.handler))matches routes instead of returning 404. If you mounted under a prefix and setbasePath: ''to compensate for the stripped URL, setbasePathto the mount prefix instead. - Uses a body that an upstream parser already read (
express.json(),express.text(),express.raw(), NestJS's default parser) fromreq.bodyinstead of failing with a 400VALIDATION_ERROR. String and Buffer bodies still go throughbodyLimitand content-type parsing. On Fastify, setrequest.raw.body = request.bodybefore calling the handler, or hijack from anonRequesthook. - If the body stream was consumed and no
req.bodyis available, returns a 500 that explains how to fix the setup, instead of validating an empty body.
- Routes on
- e7fe2bd
Node adapter: a JSON request body left as text by
express.text()is parsed again when it was sent chunked or compressed, instead of reaching the endpoint as a raw string. When no length can be compared, a string body that is JSON object or array text is parsed and any other string is kept as a string, so a decoded"123"stays"123". As a result, a chunked or compressedexpress.text()body that is a bare JSON primitive (123,true,null) reaches the endpoint as a string; send such bodies with aContent-Length, or parse them withexpress.json(). And a JSON string decoded byexpress.json({ strict: false })is held tobodyLimit.
hypequery (Python)v0.1.0b1Pre-release 152 more changes in this release →hypequery init --framework standalone|django|flaskchooses the application written besidedatasets.py(decision 0023 step 6).standalone, the default, isapp.py: an API fromcreate_api, served as plain ASGI byhypequery devwith no web framework. It replaces thefastapichoice, which wrote the same app; to use FastAPI, mountappin it.--framework djangowrites a small runnable Django project (settings.py,urls.py,manage.py) andanalytics.py;--framework flaskwrites a Flaskapp.py. Both serve hypequery's endpoints natively (urls(api),blueprint(api)) twice: at/api/analyticsbehind the framework's own login (django_user,flask_session) with the same-origin check, and Django's CSRF middleware, for@hypequery/react; and at/api/agentsbehind a bearer token (HYPEQUERY_DEV_TOKENin development), for@hypequery/mcp. Each also has a view or route of its own on the per-request client. Until wired to a login, Flask's session API and route answer 401, and tenant-scoped datasets refuse signed-in Django users. Pyproject extras aredjangoorflask; the README covers secrets, hosts,jwt_strategyand moving the pieces into an existing Django project.--frameworkworks with--skip-connection: each framework gets the offline orders example, withdatasets.pyandseed.sql. The standalone example's dataset now lives indatasets.pytoo.hypequery initaccepts--tenant-column, likegenerate datasets, so a tenant-scoped project needs one command.hypequery initrecords--tables/--exclude-tablesinschema.json, andgenerate datasetsreuses that selection unless given--tables,--exclude-tablesor the new--all-tables. Regenerating no longer widens a project to every table in the database.The scaffold's
.env.example, README andapp.pymatch how discovery connected:CLICKHOUSE_URLwhen it was set, otherwise the host, port and TLS setting discovery used. Credentials stay placeholders.
@hypequery/datasetsv0.27.0Minor Minor changes
- f103760
Add
isNullandisNotNullcomparisons, which take no value (RFC 0023), so "has a churn date" ischurned_at IS NOT NULLrather than a sentinel range. A protocol comparison using one is{ kind: 'comparison', operator: 'isNotNull', left }with noright; a client query filter is{ field, operator: 'isNull' }with novalue. Validators reject a value on them and accept any field type. Measure fixed filters and segments can use them directly, including through the newisNull(field)andisNotNull(field)helpers (also re-exported by@hypequery/serve). Caller query filters are opt-in: a filter allows them only when itsoperatorslist names them, so default operator lists, and the identity of every existing deployment and client contract, are unchanged. The deployment data plane, the MCP dataset guide and the generated client input types support them, and the conformance corpus pins the new cases. Upgrade every consumer before publishing a contract that uses them: earlier validators reject the new operators.
@hypequery/protocolv0.24.0Minor Minor changes
- 24f82d5
Client contracts can carry an optional
annotationsmember per endpoint: the dataset group'slabel/descriptionand per-dimension/measurefieldstext (RFC 0018 amendment). Text follows the deployment contract's rules (non-blank, no control characters, at most 4096 UTF-8 bytes) and is excluded fromschemaHash, so rewording a description never trips the execution-time schema pin;contentHashstill covers it. The MCP HTTP bridge'slist_datasetsnow shows each group's own description (and label) instead of the generic text, andget_dataset_schemareturns the annotations with each endpoint profile.generate:clientemits them as JSDoc on eachClientApientry and output row field. Upgrade these packages before pointing them at a backend that emits annotations: earlier validators reject the new member. - f103760
Add
isNullandisNotNullcomparisons, which take no value (RFC 0023), so "has a churn date" ischurned_at IS NOT NULLrather than a sentinel range. A protocol comparison using one is{ kind: 'comparison', operator: 'isNotNull', left }with noright; a client query filter is{ field, operator: 'isNull' }with novalue. Validators reject a value on them and accept any field type. Measure fixed filters and segments can use them directly, including through the newisNull(field)andisNotNull(field)helpers (also re-exported by@hypequery/serve). Caller query filters are opt-in: a filter allows them only when itsoperatorslist names them, so default operator lists, and the identity of every existing deployment and client contract, are unchanged. The deployment data plane, the MCP dataset guide and the generated client input types support them, and the conformance corpus pins the new cases. Upgrade every consumer before publishing a contract that uses them: earlier validators reject the new operators.
@hypequery/servev0.24.0Minor Minor changes
- f103760
Add
isNullandisNotNullcomparisons, which take no value (RFC 0023), so "has a churn date" ischurned_at IS NOT NULLrather than a sentinel range. A protocol comparison using one is{ kind: 'comparison', operator: 'isNotNull', left }with noright; a client query filter is{ field, operator: 'isNull' }with novalue. Validators reject a value on them and accept any field type. Measure fixed filters and segments can use them directly, including through the newisNull(field)andisNotNull(field)helpers (also re-exported by@hypequery/serve). Caller query filters are opt-in: a filter allows them only when itsoperatorslist names them, so default operator lists, and the identity of every existing deployment and client contract, are unchanged. The deployment data plane, the MCP dataset guide and the generated client input types support them, and the conformance corpus pins the new cases. Upgrade every consumer before publishing a contract that uses them: earlier validators reject the new operators.
@hypequery/cliv1.26.0Minor Minor changes
- 24f82d5
Client contracts can carry an optional
annotationsmember per endpoint: the dataset group'slabel/descriptionand per-dimension/measurefieldstext (RFC 0018 amendment). Text follows the deployment contract's rules (non-blank, no control characters, at most 4096 UTF-8 bytes) and is excluded fromschemaHash, so rewording a description never trips the execution-time schema pin;contentHashstill covers it. The MCP HTTP bridge'slist_datasetsnow shows each group's own description (and label) instead of the generic text, andget_dataset_schemareturns the annotations with each endpoint profile.generate:clientemits them as JSDoc on eachClientApientry and output row field. Upgrade these packages before pointing them at a backend that emits annotations: earlier validators reject the new member. - f103760
Add
isNullandisNotNullcomparisons, which take no value (RFC 0023), so "has a churn date" ischurned_at IS NOT NULLrather than a sentinel range. A protocol comparison using one is{ kind: 'comparison', operator: 'isNotNull', left }with noright; a client query filter is{ field, operator: 'isNull' }with novalue. Validators reject a value on them and accept any field type. Measure fixed filters and segments can use them directly, including through the newisNull(field)andisNotNull(field)helpers (also re-exported by@hypequery/serve). Caller query filters are opt-in: a filter allows them only when itsoperatorslist names them, so default operator lists, and the identity of every existing deployment and client contract, are unchanged. The deployment data plane, the MCP dataset guide and the generated client input types support them, and the conformance corpus pins the new cases. Upgrade every consumer before publishing a contract that uses them: earlier validators reject the new operators.
@hypequery/protocol-conformancev0.17.0Minor Minor changes
- f103760
Add
isNullandisNotNullcomparisons, which take no value (RFC 0023), so "has a churn date" ischurned_at IS NOT NULLrather than a sentinel range. A protocol comparison using one is{ kind: 'comparison', operator: 'isNotNull', left }with noright; a client query filter is{ field, operator: 'isNull' }with novalue. Validators reject a value on them and accept any field type. Measure fixed filters and segments can use them directly, including through the newisNull(field)andisNotNull(field)helpers (also re-exported by@hypequery/serve). Caller query filters are opt-in: a filter allows them only when itsoperatorslist names them, so default operator lists, and the identity of every existing deployment and client contract, are unchanged. The deployment data plane, the MCP dataset guide and the generated client input types support them, and the conformance corpus pins the new cases. Upgrade every consumer before publishing a contract that uses them: earlier validators reject the new operators.
@hypequery/deploymentv0.11.0Minor Minor changes
- f103760
Add
isNullandisNotNullcomparisons, which take no value (RFC 0023), so "has a churn date" ischurned_at IS NOT NULLrather than a sentinel range. A protocol comparison using one is{ kind: 'comparison', operator: 'isNotNull', left }with noright; a client query filter is{ field, operator: 'isNull' }with novalue. Validators reject a value on them and accept any field type. Measure fixed filters and segments can use them directly, including through the newisNull(field)andisNotNull(field)helpers (also re-exported by@hypequery/serve). Caller query filters are opt-in: a filter allows them only when itsoperatorslist names them, so default operator lists, and the identity of every existing deployment and client contract, are unchanged. The deployment data plane, the MCP dataset guide and the generated client input types support them, and the conformance corpus pins the new cases. Upgrade every consumer before publishing a contract that uses them: earlier validators reject the new operators.
@hypequery/mcpv0.11.0Minor Minor changes
- 24f82d5
Client contracts can carry an optional
annotationsmember per endpoint: the dataset group'slabel/descriptionand per-dimension/measurefieldstext (RFC 0018 amendment). Text follows the deployment contract's rules (non-blank, no control characters, at most 4096 UTF-8 bytes) and is excluded fromschemaHash, so rewording a description never trips the execution-time schema pin;contentHashstill covers it. The MCP HTTP bridge'slist_datasetsnow shows each group's own description (and label) instead of the generic text, andget_dataset_schemareturns the annotations with each endpoint profile.generate:clientemits them as JSDoc on eachClientApientry and output row field. Upgrade these packages before pointing them at a backend that emits annotations: earlier validators reject the new member. - f103760
Add
isNullandisNotNullcomparisons, which take no value (RFC 0023), so "has a churn date" ischurned_at IS NOT NULLrather than a sentinel range. A protocol comparison using one is{ kind: 'comparison', operator: 'isNotNull', left }with noright; a client query filter is{ field, operator: 'isNull' }with novalue. Validators reject a value on them and accept any field type. Measure fixed filters and segments can use them directly, including through the newisNull(field)andisNotNull(field)helpers (also re-exported by@hypequery/serve). Caller query filters are opt-in: a filter allows them only when itsoperatorslist names them, so default operator lists, and the identity of every existing deployment and client contract, are unchanged. The deployment data plane, the MCP dataset guide and the generated client input types support them, and the conformance corpus pins the new cases. Upgrade every consumer before publishing a contract that uses them: earlier validators reject the new operators.
@hypequery/protocolv0.23.0Minor Minor changes
- 5c6c96c
Publish
measure.mergemeasures to the deployment contract (RFC 0022). A base measure may useaggregation: 'merge'with astateFunctionfrom the shared allowlist (now exported by@hypequery/protocol); it takes no filters orsql, and in contract 3 carriesapproximate: trueexactly for estimating states. Deployments rehydrate merge measures, so hosted runtimes can serve pre-aggregated tables. A metric over a merge measure is still refused, because the expression grammar has no merge aggregate.
@hypequery/datasetsv0.26.0Minor Minor changes
- 5c6c96c
Publish
measure.mergemeasures to the deployment contract (RFC 0022). A base measure may useaggregation: 'merge'with astateFunctionfrom the shared allowlist (now exported by@hypequery/protocol); it takes no filters orsql, and in contract 3 carriesapproximate: trueexactly for estimating states. Deployments rehydrate merge measures, so hosted runtimes can serve pre-aggregated tables. A metric over a merge measure is still refused, because the expression grammar has no merge aggregate.
@hypequery/servev0.23.0Minor Minor changes
- 18257df
Datasets can declare more than one time axis.
timeKeystays the default; list the others intimeKeys, then select one per query withtimeKey, on dataset and metric queries alike:Typed queries narrow
timeKeyto the dataset's declared axes, so a misspelled axis is a compile error (exported asDatasetTimeKeyNames). The selected axis drives grains, window and shift measures, and their bounded-range checks. Timezone-free filters on any declared axis use the query timezone. The result cache keys an alternate axis separately; queries on the default axis keep their existing keys. Catalogs and contracts publishtimeKeysonly when a dataset declares alternates.buildDatasetInputSchema/buildMetricInputSchematake a new opt-intimeKeyoption, which Serve endpoints andgenerateDatasetToolsenable, so other schemas and manifest hashes are unchanged. The deprecatedbackendpath rejects alternate axes.
Patch changes
- aad8ad3
initServe(...).serve()/.define()called with onlydatasetsand/ormetrics(noqueries) no longer widensInferApiTypeto a string index signature. The inferred API now keeps itsdataset:<name>and metric keys, socreateAnalyticsHooks<Api>()'suseDataset('orders', …)anduseMetric(…)type-check with inferred rows instead of typing the name asnever.
@hypequery/protocolv0.22.0Minor Minor changes
- ffc2610
Add
rowResolution(RFC 0021), the one API for reading versioned ClickHouse sources, in code and in the deployment contract, so they can be published.{ kind: 'final' }reads the source withFINAL; naming the engine (replacingwithdeletedColumn,collapsing/versioned-collapsingwithsignColumn) also keeps only current rows, on base reads and relationship targets. Deployment contracts preserve the policy on validation, hashing and rehydration, so a published dataset reads exactly as it does locally.final: trueis deprecated: it still works, is read asrowResolution: { kind: 'final' }, and logs a one-time warning. Its result-cache keys change once, because they are now built fromrowResolution.
@hypequery/reactv0.7.1Patch Patch changes
- edc2fb3
useDatasetanduseMetricresponses typemetaas present when the input setsincludeMeta: true, and everyuseInfiniteDataset/useInfiniteMetricpage typesmetaas present, since infinite queries always request it. Responses withoutincludeMetakeepmetaoptional.useDatasetanduseMetricoptions now typeselectagainst the narrowed response, and the hook's result type follows whatselectreturns.
@hypequery/datasetsv0.25.0Minor Minor changes
- 3492dc9
Add enforced constraints to
createDatasetClient:context.runtime.constraintstakes RFC 0019 comparisons (a declared filter or a one-hoprelationship.field) resolved from trusted context. They are ANDed onto every read of the dataset's source, in every query shape: aggregate, derived,having, window, shift, metrics, derived metrics and relationship joins. A constraint the dataset can't enforce refuses the call without describing the constraint. Constraints share the dataset'smaxFiltersceiling with the caller (at most 32 per call), enter the result-cache key, and are refused on the deprecated semantic-backend path rather than dropped. The runtime tenant and constraints are now applied at a single source-scoping step (RFC 0020). Queries without constraints generate identical SQL and keep their cache keys. - 18257df
Datasets can declare more than one time axis.
timeKeystays the default; list the others intimeKeys, then select one per query withtimeKey, on dataset and metric queries alike:Typed queries narrow
timeKeyto the dataset's declared axes, so a misspelled axis is a compile error (exported asDatasetTimeKeyNames). The selected axis drives grains, window and shift measures, and their bounded-range checks. Timezone-free filters on any declared axis use the query timezone. The result cache keys an alternate axis separately; queries on the default axis keep their existing keys. Catalogs and contracts publishtimeKeysonly when a dataset declares alternates.buildDatasetInputSchema/buildMetricInputSchematake a new opt-intimeKeyoption, which Serve endpoints andgenerateDatasetToolsenable, so other schemas and manifest hashes are unchanged. The deprecatedbackendpath rejects alternate axes. - ffc2610
Add
rowResolution(RFC 0021), the one API for reading versioned ClickHouse sources, in code and in the deployment contract, so they can be published.{ kind: 'final' }reads the source withFINAL; naming the engine (replacingwithdeletedColumn,collapsing/versioned-collapsingwithsignColumn) also keeps only current rows, on base reads and relationship targets. Deployment contracts preserve the policy on validation, hashing and rehydration, so a published dataset reads exactly as it does locally.final: trueis deprecated: it still works, is read asrowResolution: { kind: 'final' }, and logs a one-time warning. Its result-cache keys change once, because they are now built fromrowResolution.
Patch changes
- db271b2
Fix to-date measures returning
nullon every row in a non-UTC query timezone when they are reached through a nested derived measure (the composite time-measure plan). The to-date start is now kept in the query timezone instead of the server's.
@hypequery/protocolv0.21.0Minor Minor changes
- 9d97163
Add semantic client contract v1 validation, canonical identities and strict HTTP/MCP query validation. Compile typed endpoint/tool schemas from public descriptors and test Python/TypeScript with the required shared conformance family. Existing catalog schemas keep their defaults.
- e0f9c6e
Add field visibility and enforced constraints (RFC 0019).
@hypequery/protocolexportsvalidateProtocolFieldVisibilityandresolveProtocolVisibleDatasetFields. The semantic data plane acceptsresolveFieldVisibilityandresolveConstraints: hidden datasets and fields are refused exactly like unknown ones (before access and tenant checks), joins over hidden keys are hidden, and provider-enforced comparisons are ANDed onto every call within the dataset's filter ceiling.DeploymentSemanticContextInputnames the input every context resolver receives.projectAuthorizedDeploymentContracttakes avisibilityoption so discovery advertises only what execution accepts.
Patch changes
- cbf8691
MCP tools refuse a
limitabove the endpoint'smaxLimitwithMCP_INVALID_ARGUMENTSinstead of silently clamping it, so an agent never mistakes a shortened page for the whole answer. Tool schemas built from a client contract advertise that ceiling as thelimitmaximum, andvalidateProtocolClientQuery(..., 'mcp')enforces it. HTTP requests keep clamping, as both Serve implementations do. - e32fa97
Upgrade
@noble/hashesto v2. Hash outputs are unchanged.
@hypequery/servev0.22.0Minor Minor changes
- afa5e81
Serve accepts your schemas from Zod 3 or Zod 4. Query inputs and outputs are typed against a structural
ServeSchemainstead of Zod 3'sZodTypeAny, sonpm install zod(which now resolves Zod 4) works with the quick start, and existing Zod 3 projects keep compiling. Query-string coercion and the OpenAPI document read both majors. The optionalzodpeer range is now^3.23.8 || ^4.0.0.Serve and MCP now depend on
zod@^4.6.6(was^3.23.8), clearing GHSA-mrhx-c7xc-m3w5. For dataset and metric endpoints, whose schemas Serve builds,VALIDATION_ERRORissue text and codes now follow Zod 4 (for exampleInvalid option: expected one of …, and noreceivedfield). Endpoints with your own schemas report whatever your Zod reports, as before.hypequery initscaffoldszod@^4.6.6.
Patch changes
- bb910a4
Dataset and metric endpoints now enforce the related dataset's own policy. Previously a query on one served dataset could read fields of a related dataset through a relationship, such as
shipment.carrieronorders, even when the caller failed that dataset's own endpoint'srequiredRoles,requiredScopesor auth requirement. Such a query now answers403 FORBIDDENbefore it is planned. The check covers measures whose fixed filters read a related field, directly or through a derived measure, including the measures an omittedmeasureslist selects. A related dataset with no local auth setting inherits the API's global auth, as its own endpoint does, and policies are matched to the related dataset definition itself rather than to any dataset sharing its name. Related datasets that are not served as their own entry are unaffected, so existing APIs keep working unless they relied on reading a protected dataset through another one.
@hypequery/mcpv0.10.0Minor Minor changes
- 329f16b
Add an HTTP MCP executor over authorized Python client contracts, retaining endpoint-specific query permissions and schema pins. Bound discovery, tool manifests, streamed JSON results and execution time; reject redirects, stale views, private metadata and result fields outside the requested projection. Existing local and discovery-only executors remain supported.
MCPToolExecutor.listTools,listPromptsandgetPromptaccept an optional cancellation signal, which the protocol server now forwards from each request.
Patch changes
- aa10003
Exclude internal runtime and type-test programs from published package tarballs while preserving public runtime and declaration exports.
- cbf8691
MCP tools refuse a
limitabove the endpoint'smaxLimitwithMCP_INVALID_ARGUMENTSinstead of silently clamping it, so an agent never mistakes a shortened page for the whole answer. Tool schemas built from a client contract advertise that ceiling as thelimitmaximum, andvalidateProtocolClientQuery(..., 'mcp')enforces it. HTTP requests keep clamping, as both Serve implementations do. - afa5e81
Serve accepts your schemas from Zod 3 or Zod 4. Query inputs and outputs are typed against a structural
ServeSchemainstead of Zod 3'sZodTypeAny, sonpm install zod(which now resolves Zod 4) works with the quick start, and existing Zod 3 projects keep compiling. Query-string coercion and the OpenAPI document read both majors. The optionalzodpeer range is now^3.23.8 || ^4.0.0.Serve and MCP now depend on
zod@^4.6.6(was^3.23.8), clearing GHSA-mrhx-c7xc-m3w5. For dataset and metric endpoints, whose schemas Serve builds,VALIDATION_ERRORissue text and codes now follow Zod 4 (for exampleInvalid option: expected one of …, and noreceivedfield). Endpoints with your own schemas report whatever your Zod reports, as before.hypequery initscaffoldszod@^4.6.6.
@hypequery/datasetsv0.24.0Minor Minor changes
- 9d97163
Add semantic client contract v1 validation, canonical identities and strict HTTP/MCP query validation. Compile typed endpoint/tool schemas from public descriptors and test Python/TypeScript with the required shared conformance family. Existing catalog schemas keep their defaults.
- 4af1695
Add
measure.merge(stateFunction, field)(andmerge()for metric configs) to readAggregateFunctioncolumns of AggregatingMergeTree tables with the matching-Mergecombinator, for examplemeasure.merge('uniq', 'users')rendersuniqMerge(users). Trailing and to-date windows merge states across buckets, so weekly distinct counts from daily states are exact to the state function. State functions are allowlisted; merges of estimating states are catalogued asapproximate. Merge measures are refused with measure filters, rawsql, relationships, cumulative windows, semantic backends and deployment-contract publishing.@hypequery/clickhouseaddsmergeState(stateFunction, column, alias)to the query builder;QueryBuilderLikegains it as an optional member. - c1f1dd8
Add
final: trueto dataset definitions for ReplacingMergeTree and CollapsingMergeTree sources. Every query on the dataset, every join that targets it andcheckRelationshipsread the source with ClickHouseFINAL, so unmerged row versions are no longer counted and soft-deleted keys (ReplacingMergeTree(ver, is_deleted)) disappear. Builders gain an optionalfinal()protocol method; a final dataset is refused with a clear error on builders without it, on semantic backends, and when publishing to the deployment contract, which cannot carry the flag yet. Datasets withoutfinalgenerate identical SQL and keep their cache keys. - afa5e81
Zod-backed schema builders and agent tools now have their own entry,
@hypequery/datasets/schemas:generateDatasetTools,toOpenAITools,toAISDKTools,toMcpTools,buildDatasetInputSchema,buildMetricInputSchema,buildCanonicalSemanticQuerySchemas,toSemanticJsonSchema,buildDatasetInputProtocolSchema,buildMetricInputProtocolSchema,zodToProtocolSchema,ProtocolSchemaAdapterErrorandbuildClientContractQuerySchemas. Their root-entry re-exports still work and are marked@deprecated; 1.0 removes them, and Zod becomes an optional peer dependency needed only by/schemas.Datasets now depends on
zod@^4.6.6(was^3.22.4), which clears GHSA-mrhx-c7xc-m3w5 (memory exhaustion validating oversized arrays). Zod was only used to build datasets' own schemas, so this needs no change from you. The generated JSON Schemas andmanifestHashare unchanged. Two visible differences: validation messages for an unknown field now list the valid options (Invalid option: expected one of …instead ofInvalid enum value), andzodToProtocolSchemaaccepts schemas from Zod 3 or Zod 4. - 68b0aa8
Add
assertDeployable(dataset), which refuses derived measures the deployment contract cannot carry (a reference to another derived measure, or a literal anywhere other thanrounddecimals or acoalescefallback) with an error naming the dataset and measure, for exampleorders.doubled: a numeric literal cannot be an arithmetic operand in a deployable formula.buildProtocolDeploymentContract, and sohypequery deploy, runs the check before building the contract instead of failing later with only a contract path such as$.datasets[2].measures[19].expression.right.
14 more changes in this release →Patch changes
- bc14e60
Add
toSQLWithPlaceholders(placeholder)to the query builder: it compiles the query and writes each bound value through the callback, in SQL order, so a caller can number placeholders when embedding the statement in a larger one.@hypequery/datasetsadds it as an optionalQueryBuilderLikemember, used only by datasets dialects that number placeholders. ClickHouse datasets queries keep usingtoSQLWithParams, so existing builders and generated SQL are unchanged.
@hypequery/reactv0.7.0Minor Minor changes
- 4736fb3
Support generated Python client contracts with selection-aware nullable wire results, explicit default measures, metric aliases and endpoint schema headers. Preserve schema pins through route configuration and authentication refresh, and retain declared outputs for ordinary APIs without semantic metadata.
Patch changes
- aa10003
Exclude internal runtime and type-test programs from published package tarballs while preserving public runtime and declaration exports.
@hypequery/clickhousev2.14.0Minor Minor changes
- bc14e60
Add
toSQLWithPlaceholders(placeholder)to the query builder: it compiles the query and writes each bound value through the callback, in SQL order, so a caller can number placeholders when embedding the statement in a larger one.@hypequery/datasetsadds it as an optionalQueryBuilderLikemember, used only by datasets dialects that number placeholders. ClickHouse datasets queries keep usingtoSQLWithParams, so existing builders and generated SQL are unchanged. - 4af1695
Add
measure.merge(stateFunction, field)(andmerge()for metric configs) to readAggregateFunctioncolumns of AggregatingMergeTree tables with the matching-Mergecombinator, for examplemeasure.merge('uniq', 'users')rendersuniqMerge(users). Trailing and to-date windows merge states across buckets, so weekly distinct counts from daily states are exact to the state function. State functions are allowlisted; merges of estimating states are catalogued asapproximate. Merge measures are refused with measure filters, rawsql, relationships, cumulative windows, semantic backends and deployment-contract publishing.@hypequery/clickhouseaddsmergeState(stateFunction, column, alias)to the query builder;QueryBuilderLikegains it as an optional member.
Patch changes
- 1570a03
Upgrade
dotenvto v18 and load env files quietly, so dotenv's "injected env" log lines no longer appear in CLI output.
@hypequery/cliv1.25.0Minor Minor changes
- 3d1c757
Add MCP stdio bridging and discovery-only self-tests for authorized Python HTTP client contracts with
--client-contract-url. Read Bearer credentials fromHYPEQUERY_API_KEY, keep tenant resolution in Python, and abort discovery on shutdown. - b0d168e
Add offline
generate:clientgeneration of self-contained API types, installed POST route mappings and schema hashes from validated Python client contracts. Preserve typed filters, nullable wire values, metric aliases and default measures, with drift checks and explicit replacement of existing generated files.
Patch changes
- 4fda9e7
@hypequery/serveis now an optional peer dependency. Installing@hypequery/cliin a frontend project, for example to rungenerate:clientfor a Python backend, no longer makes npm install the server packages too.hypequery devsays to install@hypequery/servewhen it is missing. - 1570a03
Upgrade
dotenvto v18 and load env files quietly, so dotenv's "injected env" log lines no longer appear in CLI output. - afa5e81
Serve accepts your schemas from Zod 3 or Zod 4. Query inputs and outputs are typed against a structural
ServeSchemainstead of Zod 3'sZodTypeAny, sonpm install zod(which now resolves Zod 4) works with the quick start, and existing Zod 3 projects keep compiling. Query-string coercion and the OpenAPI document read both majors. The optionalzodpeer range is now^3.23.8 || ^4.0.0.Serve and MCP now depend on
zod@^4.6.6(was^3.23.8), clearing GHSA-mrhx-c7xc-m3w5. For dataset and metric endpoints, whose schemas Serve builds,VALIDATION_ERRORissue text and codes now follow Zod 4 (for exampleInvalid option: expected one of …, and noreceivedfield). Endpoints with your own schemas report whatever your Zod reports, as before.hypequery initscaffoldszod@^4.6.6.
@hypequery/protocol-conformancev0.16.0Minor Minor changes
- 9d97163
Add semantic client contract v1 validation, canonical identities and strict HTTP/MCP query validation. Compile typed endpoint/tool schemas from public descriptors and test Python/TypeScript with the required shared conformance family. Existing catalog schemas keep their defaults.
@hypequery/deploymentv0.10.0Minor Minor changes
- e0f9c6e
Add field visibility and enforced constraints (RFC 0019).
@hypequery/protocolexportsvalidateProtocolFieldVisibilityandresolveProtocolVisibleDatasetFields. The semantic data plane acceptsresolveFieldVisibilityandresolveConstraints: hidden datasets and fields are refused exactly like unknown ones (before access and tenant checks), joins over hidden keys are hidden, and provider-enforced comparisons are ANDed onto every call within the dataset's filter ceiling.DeploymentSemanticContextInputnames the input every context resolver receives.projectAuthorizedDeploymentContracttakes avisibilityoption so discovery advertises only what execution accepts.
@hypequery/protocolv0.20.0Minor Minor changes
- d1e4194
Add
checkProtocolDeploymentContract,checkProtocolDeploymentContractV3andcheckProtocolDatasetContract, which report every failure in a contract in one pass (bounded at 100) instead of throwing the first. They accept exactly what the matchingvalidate*functions accept and skip checks that depend on a part that already failed, so a mistake is not reported twice.A malformed SQL expression embedded in a deployment contract still fails with its
HQ_QUERY_IMPLEMENTATION_*code, but itspathnow locates it in the contract (for example$.datasets[0].dimensions[1].source.sql) instead of the expression root ($.sql).
@hypequery/cliv1.24.0Minor Minor changes
- 879180e
Enable CLI telemetry by default. Unless opted out, the CLI now sends pseudonymous usage events to Hypequery's first-party endpoint (
https://hypequery.com/api/telemetry) without needingHYPEQUERY_TELEMETRY_URL, which now only overrides the endpoint for staging or self-hosting. Events never include code, SQL, names, paths or credentials; see https://hypequery.com/docs/telemetry for every field. A one-time notice appears on the first interactive run. Opt out withhypequery telemetry disable,--no-telemetry,DO_NOT_TRACK=1orHYPEQUERY_TELEMETRY_DISABLED=1.
@hypequery/mcpv0.9.0Minor Minor changes
- 064661f
Expose dataset
havingconditions (HQ-329) on every consumption surface:- Serve dataset endpoints accept and forward
having. The input schema and OpenAPI enumerate each dataset's measures, and the endpoint description documents the field. - MCP
query_datasetadvertises and applieshaving. Local servers and hosted discovery gateways list identical schemas (CORE-03), so hosted execution must supporthavingonce it is wired in. - React
useDataset,useInfiniteDatasetanduseQuery('dataset:…')accepthavingthrough the Serve API types, constrained to the dataset's measures. Metric hooks do not accept it.
- Serve dataset endpoints accept and forward
@hypequery/protocolv0.19.0Minor Minor changes
- 489a658
Support composite equality keys in dataset relationships using a non-empty keys array while preserving existing from/to definitions. Compile all pairs as a single-match AND join through the key-pair form of
leftAnyJoin(@hypequery/clickhouse>= 2.13.0), preserve tenant scoping and related-measure inputs, and check uniqueness of full non-NULL target tuples. Retain all key pairs in catalogs and portable contract round-trips. Declare@hypequery/clickhouse>= 2.13.0 as an optional peer dependency of datasets. Existing{ from, to }relationships are unchanged and are not subject to the composite identifier rules. Portable contracts only carrykeysfor two or more pairs, andkeys[0]must matchfrom/to.
@hypequery/cliv1.23.0Minor Minor changes
- b5674d4
Add staged generation metrics: actual filtered table and column count buckets, known fallback type families, dataset check/diff modes and drift results, warning-code buckets, and manifest/registry count buckets. Exclude schema names, type expressions, warning text, paths, and endpoint contents. Default collection remains inactive.
- 842c4a5
Add staged dev and MCP session telemetry with one start/end pair, bucketed reload and load-failure counts, and aggregate MCP tool-kind and error counts. Preserve MCP stdout for JSON-RPC and exclude paths, client identity, names, tenants, and tool arguments. Default collection remains inactive.
- ca0de07
Add persistent telemetry preferences,
hypequery telemetry status|enable|disable, and a global--no-telemetryflag. HonorDO_NOT_TRACK=1,HYPEQUERY_TELEMETRY_DISABLED=1, and test environments. Default collection remains inactive; maintainers can activate the staged core withHYPEQUERY_TELEMETRY_DEBUG=1orHYPEQUERY_TELEMETRY_URL.Define the v1 event catalog (command completion and crash events) with strict property validation, bucketed measurements, and a generated public event reference that lists only data the CLI sends. Unknown fields and content-bearing values are rejected before a payload can be constructed.
Add pseudonymous identity, local environment context, a one-time stderr disclosure, dependency-free bounded batch delivery, debug inspection, a per-version kill switch, and centralized command exit handling. Preserve command output and exit codes when telemetry is disabled or fails. No telemetry runtime dependency is added.
Instrument the
initonboarding funnel in staged mode with progress, failure stages, scaffold choices, bucketed counts, and configuration-file outcomes. Preserve a single completion event across retries and classify early setup declines as cancellations. Honor Commander's--no-exampleoption when scaffolding.
Patch changes
- 9894390
Deliver telemetry from a detached sender process instead of a 40 ms in-process request. The command exits without waiting on the network, while the sender gets up to five seconds, so batches survive TLS handshakes and serverless cold starts. The per-version kill switch (HTTP 410) is now applied by the sender.
- fbd4613
hypequery mcp <file>andhypequery dev <file>now work from any working directory. TypeScript entries are bundled into.hypequery/tmpbeside the entry's nearestpackage.jsoninstead of the current directory, so imports like@hypequery/serveresolve from the entry's project. The entry project's.env*files are loaded before the entry runs, so a generated client finds its ClickHouse settings; variables already set in the environment or the launch directory's env files keep precedence.hypequery mcpalso loads@hypequery/mcpfrom that project, so desktop MCP clients can launchnpx -y @hypequery/cli mcp /absolute/path/to/analytics/api.tswithout changing directory first.
@hypequery/datasetsv0.23.0Minor Minor changes
- 489a658
Support composite equality keys in dataset relationships using a non-empty keys array while preserving existing from/to definitions. Compile all pairs as a single-match AND join through the key-pair form of
leftAnyJoin(@hypequery/clickhouse>= 2.13.0), preserve tenant scoping and related-measure inputs, and check uniqueness of full non-NULL target tuples. Retain all key pairs in catalogs and portable contract round-trips. Declare@hypequery/clickhouse>= 2.13.0 as an optional peer dependency of datasets. Existing{ from, to }relationships are unchanged and are not subject to the composite identifier rules. Portable contracts only carrykeysfor two or more pairs, andkeys[0]must matchfrom/to. - 064661f
Dataset queries accept
havingconditions on aggregated measure values (HQ-329):Each condition must reference a selected measure, including derived measures. Operators are
eq,neq,gt,gte,lt,lte,between,inandnotIn. Values are finite numbers bound as parameters. Conditions are applied after grouping and before ordering and limits. Queries withhavingbypass the result cache until the shared cache-key preimage covers conditions, as in the Python SDK. A dataset'slimits.maxFiltersbounds filters and having conditions together. Queries that select window or shift measures, and the deprecated semantic backend path, rejecthaving. Generated input schemas accepthavingonly when built with{ having: true }, so existing schemas and manifest hashes are unchanged. - 0d88c0e
Catalogs and semantic contracts now include each derived measure's inputs (
uses) and expression, so changing a formula changes the snapshot hash. Datasets that already declare derived measures report a new semantic contractcontentHashafter upgrading, including the one Serve's contract endpoint publishes; consumers that compare it to detect definition changes will see one change. Definitions without derived measures are unchanged, as are result-cache keys and deployment contracts. Shared fixtures now pin Python derived-measure authoring to the same deployment and semantic contract output.
Patch changes
- aada8f3
dataset()now validates filter definitions before any query can use them. A measure filter'sfieldmust be a declared dimension or filter, or a safe column identifier (optionally<relationship>.<field>), and a declared filter'sfieldmust be a declared dimension or a safe column identifier. Unsupported operators are rejected in both places. Previously these values were rendered into SQL unchecked. Definitions that put SQL text in a filterfieldnow fail at construction: declare a dimension withsqland filter on that dimension. - 03ba7f2
Fix calendar shifts (
month,quarter,year) on a partialweekbucket. When a query filter cut a week short, its lower bound was shifted on its own while its upper bound stayed anchored to the shifted week. A week starting mid-way could get an empty range and readnulleven when the prior period had rows, and a week cut on both sides could count rows from days it never covered. Both bounds are now placed inside the shifted week: a whole week still maps to its start minus the interval plus seven days, and a partial week maps to the matching slice. Shifted formulas (derived, windowed and cumulative measures under a shift) are fixed the same way.
@hypequery/servev0.21.0Minor Minor changes
- 064661f
Expose dataset
havingconditions (HQ-329) on every consumption surface:- Serve dataset endpoints accept and forward
having. The input schema and OpenAPI enumerate each dataset's measures, and the endpoint description documents the field. - MCP
query_datasetadvertises and applieshaving. Local servers and hosted discovery gateways list identical schemas (CORE-03), so hosted execution must supporthavingonce it is wired in. - React
useDataset,useInfiniteDatasetanduseQuery('dataset:…')accepthavingthrough the Serve API types, constrained to the dataset's measures. Metric hooks do not accept it.
- Serve dataset endpoints accept and forward
@hypequery/reactv0.6.4Patch Patch changes
- 9b5b523
Support one-hop relationship base measures in dataset queries through the query-builder client. Allow duplicate-insensitive aggregates through belongsTo and all base aggregates through declared hasOne relationships, preserve tenant and fixed-filter scoping, and exclude unmatched target rows from aggregate inputs. Advertise safe names and approximate metadata in runtime catalogs and input schemas, with typed projections through Serve and React.
- f30add1
Preserve dataset filter allowlist names and field-specific operators through dataset and metric queries, Serve API inputs, and React hooks. Generated filters respect
filterable: false, and one-hop relationship filters follow the target allowlist. Filter helpers retain operator literals.Prevent normal dataset execution from falling through to the legacy dynamic-query overload; explicit result-row generic calls remain supported. Fix Serve in-process execution input inference so its optional schema storage property no longer widens typed inputs to unknown.
@hypequery/datasetsv0.22.0Minor Minor changes
- 0841d1c
Add
compileDatasetto preview the same dataset compilation path used by execution, including effective row limits, pagination overfetch, measure dependencies and time-axis preflight statements. Structural diagnostics and JSON serialization omit SQL, parameter values and tenant identifiers.Add
createPortableSemanticRuntimefor provider-side compilation and execution over the same activated catalog, and expose a tested capability matrix that separates protocol representation from TS, Python and Cloud implementation support. Existing logical SQL and portable executor APIs remain available. - 9b5b523
Support one-hop relationship base measures in dataset queries through the query-builder client. Allow duplicate-insensitive aggregates through belongsTo and all base aggregates through declared hasOne relationships, preserve tenant and fixed-filter scoping, and exclude unmatched target rows from aggregate inputs. Advertise safe names and approximate metadata in runtime catalogs and input schemas, with typed projections through Serve and React.
- f30add1
Preserve dataset filter allowlist names and field-specific operators through dataset and metric queries, Serve API inputs, and React hooks. Generated filters respect
filterable: false, and one-hop relationship filters follow the target allowlist. Filter helpers retain operator literals.Prevent normal dataset execution from falling through to the legacy dynamic-query overload; explicit result-row generic calls remain supported. Fix Serve in-process execution input inference so its optional schema storage property no longer widens typed inputs to unknown.
Patch changes
- 339deef
Snapshot dataset and metric query inputs and tenant runtime before cache lookup, so caller mutations during an asynchronous store read cannot cache another tenant's result under the original tenant's key.
- 1effbb2
Add an optional datasets SQL rendering hook to query builder factories, with a ClickHouse default that preserves existing SQL. Resolve the hook from runtime builder overrides and route existing quoted identifiers through it as the foundation for subsequent dialect extraction.
- 339deef
Reject unsupported semantic filter operators and invalid sort directions at runtime, including direct SDK inputs, before compilation or cached execution. Render sort directions through a closed mapping instead of interpolating input.
@hypequery/servev0.20.0Minor Minor changes
- 0f36d1f
Add authenticated logical
/discoverywith configurable endpoint policy. The public/contractretains its version and definition identity while omitting physical and tenant-policy fields. Use localserializeSemanticContractfor trusted physical definitions. - 9b5b523
Support one-hop relationship base measures in dataset queries through the query-builder client. Allow duplicate-insensitive aggregates through belongsTo and all base aggregates through declared hasOne relationships, preserve tenant and fixed-filter scoping, and exclude unmatched target rows from aggregate inputs. Advertise safe names and approximate metadata in runtime catalogs and input schemas, with typed projections through Serve and React.
Patch changes
- e92973f
Filter unexpected fields from nested pagination, cache, and result-limit metadata in dataset and metric responses. Preserve the existing trustedDiagnostics option and response format.
- 339deef
Omit SQL and internal tenant IDs from caller-requested dataset and metric metadata by default. Public metadata remains available through includeMeta or x-include-meta. Trusted endpoints can explicitly retain diagnostics with the server-side trustedDiagnostics option; protect those endpoints with auth and roles.
- f30add1
Preserve dataset filter allowlist names and field-specific operators through dataset and metric queries, Serve API inputs, and React hooks. Generated filters respect
filterable: false, and one-hop relationship filters follow the target allowlist. Filter helpers retain operator literals.Prevent normal dataset execution from falling through to the legacy dynamic-query overload; explicit result-row generic calls remain supported. Fix Serve in-process execution input inference so its optional schema storage property no longer widens typed inputs to unknown.
@hypequery/mcpv0.8.6Patch Patch changes
- 9b5b523
Support one-hop relationship base measures in dataset queries through the query-builder client. Allow duplicate-insensitive aggregates through belongsTo and all base aggregates through declared hasOne relationships, preserve tenant and fixed-filter scoping, and exclude unmatched target rows from aggregate inputs. Advertise safe names and approximate metadata in runtime catalogs and input schemas, with typed projections through Serve and React.
@hypequery/clickhousev2.13.0Minor Minor changes
- ccb2577
Support non-empty arrays of typed column pairs in innerJoin, leftJoin, leftAnyJoin, rightJoin, and fullJoin for composite-key equality joins to schema tables and typed CTEs. Preserve existing single-pair calls, alias handling, and literal ON filters.
Patch changes
- 0d593a3
Fix the CLI declaration re-export to use an explicit
.jsextension, so importing the package root or CLI entry point passes NodeNext and Node16 type checking withskipLibCheck: falseand preserves schema-generator types.
@hypequery/protocolv0.18.0Minor Minor changes
- a8e502e
Accept RFC 0011 (query event 1 and query diagnostics 1), and align the reference validators with the accepted text.
@hypequery/protocol:validateProtocolQueryEventandvalidateProtocolQueryDiagnosticscheckkindandversionbefore the field set. A newer record that adds fields now reportsINVALID_VERSION, notUNKNOWN_FIELD, so a consumer can skip it.occurredAtmust be a real calendar instant with zero or three fractional digits.2026-02-30,24:00, and.5are rejected.- Free-text fields reject unpaired surrogates.
debugQuerymay contain tab, line feed, and carriage return, because the compiler's debug form spans lines.
@hypequery/protocol-conformance:query-events-v1andquery-diagnostics-v1gain cases for validation order, versions with added fields, calendar and precision limits, exact byte boundaries, attempts, runtime identity format, and unpaired surrogates.
@hypequery/protocol-conformancev0.15.0Minor Minor changes
- a8e502e
Accept RFC 0011 (query event 1 and query diagnostics 1), and align the reference validators with the accepted text.
@hypequery/protocol:validateProtocolQueryEventandvalidateProtocolQueryDiagnosticscheckkindandversionbefore the field set. A newer record that adds fields now reportsINVALID_VERSION, notUNKNOWN_FIELD, so a consumer can skip it.occurredAtmust be a real calendar instant with zero or three fractional digits.2026-02-30,24:00, and.5are rejected.- Free-text fields reject unpaired surrogates.
debugQuerymay contain tab, line feed, and carriage return, because the compiler's debug form spans lines.
@hypequery/protocol-conformance:query-events-v1andquery-diagnostics-v1gain cases for validation order, versions with added fields, calendar and precision limits, exact byte boundaries, attempts, runtime identity format, and unpaired surrogates.
@hypequery/cliv1.22.0Minor Minor changes
- fa2d7a2
hypequery deploynow prints where the deployment is served: the REST base URL, each dataset's URL, and the MCP URL, as reported by Cloud.--mcp-configalso prints MCP client configuration that reads the key from${HYPEQUERY_API_KEY}and never contains a credential.hypequery mcp --self-test --url <mcp-url>checks a hosted MCP endpoint without calling a tool, reading the key fromHYPEQUERY_API_KEY.hypequery mcp --self-testnow fails when@hypequery/mcpisn't installed; before, it passed and the real command then failed. - ff36939
Add
hypequery deployment:statusto show the selected Cloud target's live release and hosted REST/MCP URLs without redeploying. The command can print MCP client configuration with an environment-variable placeholder and never includes the stored deployment credential.
Patch changes
- 40ac480
Refresh production dependencies. Keep the ClickHouse adapter compatible with the client packages' bundled setting types.
@hypequery/clickhousev2.12.2Patch Patch changes
Looking for an older release?
This timeline shows the latest 60 releases. Each package page has its full history, including dependency-only updates.