@voyant-travel/reporting-contracts 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -108,6 +108,7 @@ export declare const reportDatasetDefinitionSchema: z.ZodObject<{
108
108
  }, z.core.$strict>>;
109
109
  defaultLimit: z.ZodDefault<z.ZodNumber>;
110
110
  maximumLimit: z.ZodDefault<z.ZodNumber>;
111
+ defaultDateField: z.ZodOptional<z.ZodString>;
111
112
  }, z.core.$strict>;
112
113
  export type ReportDatasetDefinition = z.infer<typeof reportDatasetDefinitionSchema>;
113
114
  export type ReportDatasetField = z.infer<typeof reportDatasetFieldSchema>;
@@ -974,12 +975,6 @@ export declare const listReportDefinitionsQuerySchema: z.ZodObject<{
974
975
  limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
975
976
  offset: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
976
977
  }, z.core.$strip>;
977
- export declare const createReportVersionSchema: z.ZodObject<{
978
- expectedRevision: z.ZodNumber;
979
- }, z.core.$strict>;
980
- export declare const executeReportVersionSchema: z.ZodObject<{
981
- parameters: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>]>>>;
982
- }, z.core.$strict>;
983
978
  export declare const previewReportQuerySchema: z.ZodObject<{
984
979
  query: z.ZodObject<{
985
980
  dataset: z.ZodObject<{
package/dist/contracts.js CHANGED
@@ -52,6 +52,11 @@ export const reportDatasetDefinitionSchema = z
52
52
  fields: z.array(reportDatasetFieldSchema).min(1).max(250),
53
53
  defaultLimit: z.number().int().positive().max(1_000).default(100),
54
54
  maximumLimit: z.number().int().positive().max(5_000).default(1_000),
55
+ // The date/datetime field a page-level date range filters on. When set, the
56
+ // reporting runtime injects `>= dateFrom` / `<= dateTo` on this field from the
57
+ // reserved `dateFrom`/`dateTo` report parameters — applying uniformly to every
58
+ // widget (preset and custom) without editing individual queries.
59
+ defaultDateField: reportingIdentifierSchema.optional(),
55
60
  })
56
61
  .strict()
57
62
  .superRefine((dataset, context) => {
@@ -272,12 +277,6 @@ export const listReportDefinitionsQuerySchema = z.object({
272
277
  limit: z.coerce.number().int().positive().max(100).default(25),
273
278
  offset: z.coerce.number().int().nonnegative().default(0),
274
279
  });
275
- export const createReportVersionSchema = z
276
- .object({ expectedRevision: z.number().int().positive() })
277
- .strict();
278
- export const executeReportVersionSchema = z
279
- .object({ parameters: reportParametersSchema.default({}) })
280
- .strict();
281
280
  export const previewReportQuerySchema = z
282
281
  .object({ query: reportQuerySchema, parameters: reportParametersSchema.default({}) })
283
282
  .strict();
@@ -3,6 +3,16 @@ import type { ReportQuery } from "./contracts.js";
3
3
  export declare class ReportQuerySyntaxError extends Error {
4
4
  constructor(message: string);
5
5
  }
6
+ /**
7
+ * Error a dataset raises when a query is well-formed but not answerable against
8
+ * that dataset (e.g. summing amounts across currencies without grouping). The
9
+ * reporting API surfaces it as a 400 so authors see the reason instead of a 500.
10
+ * Dataset packages extend this so the reporting layer can recognise their
11
+ * domain errors without importing each dataset package.
12
+ */
13
+ export declare class ReportDatasetQueryError extends Error {
14
+ constructor(message: string);
15
+ }
6
16
  /**
7
17
  * Compile the intentionally small reporting language into the public query AST.
8
18
  * It is SQL-like for familiarity but has no joins, subqueries, statements, or
@@ -18,6 +18,19 @@ export class ReportQuerySyntaxError extends Error {
18
18
  this.name = "ReportQuerySyntaxError";
19
19
  }
20
20
  }
21
+ /**
22
+ * Error a dataset raises when a query is well-formed but not answerable against
23
+ * that dataset (e.g. summing amounts across currencies without grouping). The
24
+ * reporting API surfaces it as a 400 so authors see the reason instead of a 500.
25
+ * Dataset packages extend this so the reporting layer can recognise their
26
+ * domain errors without importing each dataset package.
27
+ */
28
+ export class ReportDatasetQueryError extends Error {
29
+ constructor(message) {
30
+ super(message);
31
+ this.name = "ReportDatasetQueryError";
32
+ }
33
+ }
21
34
  /**
22
35
  * Compile the intentionally small reporting language into the public query AST.
23
36
  * It is SQL-like for familiarity but has no joins, subqueries, statements, or
@@ -86,7 +99,7 @@ function parseFilter(source) {
86
99
  operator: nullFilter[2] ? "isNotNull" : "isNull",
87
100
  };
88
101
  }
89
- const match = source.match(/^([a-z0-9][a-z0-9._/-]*)\s+(not\s+in|in|contains|>=|<=|!=|=|>|<)\s+(.+)$/i);
102
+ const match = source.match(/^([a-z0-9][a-z0-9._/-]*)\s+(not\s+in|in|between|contains|>=|<=|!=|=|>|<)\s+(.+)$/i);
90
103
  if (!match)
91
104
  throw syntax(`Unsupported filter ${JSON.stringify(source)}.`);
92
105
  const operator = {
@@ -98,6 +111,7 @@ function parseFilter(source) {
98
111
  "<=": "lessThanOrEqual",
99
112
  in: "in",
100
113
  "not in": "notIn",
114
+ between: "between",
101
115
  contains: "contains",
102
116
  };
103
117
  const operatorKey = required(match[2], "filter operator")
@@ -114,7 +128,9 @@ function parseValueReference(source) {
114
128
  if (value.startsWith("$")) {
115
129
  return { kind: "parameter", name: parseIdentifier(value.slice(1), "parameter") };
116
130
  }
117
- if (value.startsWith("[") && value.endsWith("]")) {
131
+ // Lists accept both `[...]` and SQL-style `(...)` for `in`/`not in`/`between`.
132
+ if ((value.startsWith("[") && value.endsWith("]")) ||
133
+ (value.startsWith("(") && value.endsWith(")"))) {
118
134
  const inner = value.slice(1, -1).trim();
119
135
  const values = inner ? splitList(inner).map(parseLiteral) : [];
120
136
  return { kind: "literal", value: values };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voyant-travel/reporting-contracts",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Domain-neutral reporting datasets, widgets, templates, and query contracts for Voyant.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",