@hypequery/serve 0.2.0 → 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.
- package/README.md +138 -879
- package/dist/adapters/node.d.ts.map +1 -1
- package/dist/adapters/node.js +3 -5
- package/dist/adapters/standalone.d.ts +41 -0
- package/dist/adapters/standalone.d.ts.map +1 -0
- package/dist/adapters/standalone.js +46 -0
- package/dist/auth.d.ts +59 -83
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +136 -102
- package/dist/client-config.d.ts +3 -2
- package/dist/client-config.d.ts.map +1 -1
- package/dist/client-config.js +4 -2
- package/dist/errors.js +3 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/openapi.js +1 -2
- package/dist/pipeline.d.ts.map +1 -1
- package/dist/pipeline.js +10 -22
- package/dist/query-logger.js +1 -3
- package/dist/rate-limit.js +4 -3
- package/dist/router.js +2 -1
- package/dist/semantic/datasets/dataset-endpoint.d.ts +85 -0
- package/dist/semantic/datasets/dataset-endpoint.d.ts.map +1 -0
- package/dist/semantic/datasets/dataset-endpoint.js +121 -0
- package/dist/semantic/datasets/index.d.ts +6 -0
- package/dist/semantic/datasets/index.d.ts.map +1 -0
- package/dist/semantic/datasets/index.js +5 -0
- package/dist/semantic/datasets/metric-endpoint.d.ts +82 -0
- package/dist/semantic/datasets/metric-endpoint.d.ts.map +1 -0
- package/dist/semantic/datasets/metric-endpoint.js +159 -0
- package/dist/semantic/datasets/utils/dataset-entry.d.ts +24 -0
- package/dist/semantic/datasets/utils/dataset-entry.d.ts.map +1 -0
- package/dist/semantic/datasets/utils/dataset-entry.js +15 -0
- package/dist/semantic/datasets/utils/dataset-query-metadata.d.ts +3 -0
- package/dist/semantic/datasets/utils/dataset-query-metadata.d.ts.map +1 -0
- package/dist/semantic/datasets/utils/dataset-query-metadata.js +12 -0
- package/dist/semantic/datasets/utils/semantic-input-schema.d.ts +107 -0
- package/dist/semantic/datasets/utils/semantic-input-schema.d.ts.map +1 -0
- package/dist/semantic/datasets/utils/semantic-input-schema.js +87 -0
- package/dist/semantic/index.d.ts +2 -0
- package/dist/semantic/index.d.ts.map +1 -0
- package/dist/semantic/index.js +1 -0
- package/dist/semantic/query-builder-context.d.ts +20 -0
- package/dist/semantic/query-builder-context.d.ts.map +1 -0
- package/dist/semantic/query-builder-context.js +66 -0
- package/dist/semantic/utils/tenant-runtime.d.ts +11 -0
- package/dist/semantic/utils/tenant-runtime.d.ts.map +1 -0
- package/dist/semantic/utils/tenant-runtime.js +48 -0
- package/dist/serve.d.ts +2 -2
- package/dist/serve.d.ts.map +1 -1
- package/dist/server/api-builder.d.ts +5 -0
- package/dist/server/api-builder.d.ts.map +1 -0
- package/dist/server/api-builder.js +76 -0
- package/dist/server/builder.d.ts.map +1 -1
- package/dist/server/builder.js +11 -1
- package/dist/server/create-api.d.ts +32 -0
- package/dist/server/create-api.d.ts.map +1 -0
- package/dist/server/create-api.js +211 -0
- package/dist/server/define-serve.d.ts +21 -2
- package/dist/server/define-serve.d.ts.map +1 -1
- package/dist/server/define-serve.js +53 -84
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -0
- package/dist/server/init-serve.d.ts +1 -1
- package/dist/server/init-serve.d.ts.map +1 -1
- package/dist/server/init-serve.js +7 -2
- package/dist/type-tests/builder.test-d.d.ts +4 -0
- package/dist/type-tests/builder.test-d.d.ts.map +1 -1
- package/dist/type-tests/builder.test-d.js +16 -1
- package/dist/type-tests/semantic.test-d.d.ts +2 -0
- package/dist/type-tests/semantic.test-d.d.ts.map +1 -0
- package/dist/type-tests/semantic.test-d.js +59 -0
- package/dist/types.d.ts +227 -6
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -3
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a MetricRef into a standard ServeEndpoint.
|
|
3
|
+
*
|
|
4
|
+
* The generated endpoint is a POST handler that:
|
|
5
|
+
* - Validates dimensions/filters against the metric's contract
|
|
6
|
+
* - Calls DatasetClient.execute() with the parsed query + tenant context
|
|
7
|
+
* - Returns { data } or { data, meta } based on headers
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { ServeHttpError } from '../../errors.js';
|
|
11
|
+
import { resolveSemanticExecutionRuntime, resolveSemanticQueryBuilder, } from '../query-builder-context.js';
|
|
12
|
+
import { buildMetricInputSchema } from './utils/semantic-input-schema.js';
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Zod schemas for metric query input / output
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
const metricResultMetaSchema = z.object({
|
|
17
|
+
timingMs: z.number().optional(),
|
|
18
|
+
sql: z.string().optional(),
|
|
19
|
+
tenant: z.string().optional(),
|
|
20
|
+
rowCount: z.number().optional(),
|
|
21
|
+
pagination: z.object({
|
|
22
|
+
limit: z.number(),
|
|
23
|
+
offset: z.number(),
|
|
24
|
+
hasMore: z.boolean(),
|
|
25
|
+
}).optional(),
|
|
26
|
+
}).optional();
|
|
27
|
+
const metricResultSchema = z.object({
|
|
28
|
+
data: z.array(z.record(z.unknown())),
|
|
29
|
+
meta: metricResultMetaSchema,
|
|
30
|
+
});
|
|
31
|
+
function isMetricHandleEntry(entry) {
|
|
32
|
+
return (!!entry &&
|
|
33
|
+
typeof entry === 'object' &&
|
|
34
|
+
'__type' in entry &&
|
|
35
|
+
(entry.__type === 'metric_ref' || entry.__type === 'grained_metric_ref'));
|
|
36
|
+
}
|
|
37
|
+
function isMetricEntryOptions(entry) {
|
|
38
|
+
return !!entry && typeof entry === 'object' && 'metric' in entry;
|
|
39
|
+
}
|
|
40
|
+
function resolveMetricEntry(entry) {
|
|
41
|
+
if (isMetricHandleEntry(entry)) {
|
|
42
|
+
return { metric: entry };
|
|
43
|
+
}
|
|
44
|
+
if (isMetricEntryOptions(entry)) {
|
|
45
|
+
return entry;
|
|
46
|
+
}
|
|
47
|
+
throw new Error('Invalid metric entry.');
|
|
48
|
+
}
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// Factory
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
export function createMetricEndpoint(name, entry, analytics, defaultBuilderFactory) {
|
|
53
|
+
const resolved = resolveMetricEntry(entry);
|
|
54
|
+
const metricRef = resolved.metric;
|
|
55
|
+
const contract = metricRef.contract();
|
|
56
|
+
// The metric's underlying dataset, used to enumerate valid query fields and
|
|
57
|
+
// page-size defaults.
|
|
58
|
+
const ds = (metricRef.__type === 'metric_ref' ? metricRef.dataset : metricRef.metric.dataset);
|
|
59
|
+
const metricQueryInputSchema = buildMetricInputSchema(ds, contract.name);
|
|
60
|
+
// Page-size cap, mirroring datasets: clamp (don't reject) and apply a default
|
|
61
|
+
// so a metric query is never unbounded.
|
|
62
|
+
const effectiveMaxLimit = resolved.maxLimit ?? ds.limits?.maxResultSize ?? 1000;
|
|
63
|
+
const metadata = {
|
|
64
|
+
path: '', // filled by router.register
|
|
65
|
+
method: 'POST',
|
|
66
|
+
name: contract.label ?? name,
|
|
67
|
+
summary: `Query the "${name}" metric`,
|
|
68
|
+
description: buildDescription(contract, effectiveMaxLimit),
|
|
69
|
+
tags: ['metrics'],
|
|
70
|
+
requiresAuth: resolved.auth !== null ? undefined : false,
|
|
71
|
+
requiredRoles: resolved.requiredRoles,
|
|
72
|
+
requiredScopes: resolved.requiredScopes,
|
|
73
|
+
cacheTtlMs: resolved.cache,
|
|
74
|
+
visibility: 'public',
|
|
75
|
+
custom: {
|
|
76
|
+
usesServeTenantRuntime: true,
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
const handler = async (ctx) => {
|
|
80
|
+
const semanticContext = ctx;
|
|
81
|
+
const input = ctx.input ?? {};
|
|
82
|
+
const runtime = resolveSemanticExecutionRuntime(semanticContext);
|
|
83
|
+
const runtimeBuilderFactory = resolveSemanticQueryBuilder(semanticContext, defaultBuilderFactory);
|
|
84
|
+
// Build the metric query
|
|
85
|
+
const query = {
|
|
86
|
+
dimensions: input.dimensions,
|
|
87
|
+
filters: input.filters,
|
|
88
|
+
orderBy: input.orderBy,
|
|
89
|
+
limit: Math.min(input.limit ?? effectiveMaxLimit, effectiveMaxLimit),
|
|
90
|
+
offset: input.offset,
|
|
91
|
+
by: input.by,
|
|
92
|
+
};
|
|
93
|
+
if (ctx.tenantId && !runtime?.tenant) {
|
|
94
|
+
throw new ServeHttpError(500, 'INTERNAL_SERVER_ERROR', `Metric endpoint "${name}" requires serve tenant runtime when tenant isolation is enabled.`);
|
|
95
|
+
}
|
|
96
|
+
const validationContext = ctx.tenantId && runtime?.tenant
|
|
97
|
+
? {
|
|
98
|
+
runtime: {
|
|
99
|
+
tenant: runtime.tenant,
|
|
100
|
+
},
|
|
101
|
+
}
|
|
102
|
+
: undefined;
|
|
103
|
+
const validation = analytics.validate(metricRef, query, validationContext);
|
|
104
|
+
if (!validation.valid) {
|
|
105
|
+
throw new ServeHttpError(400, 'VALIDATION_ERROR', validation.errors.join('; '));
|
|
106
|
+
}
|
|
107
|
+
// Execute with tenant context
|
|
108
|
+
const result = await analytics.execute(metricRef, query, {
|
|
109
|
+
runtime: {
|
|
110
|
+
...runtime,
|
|
111
|
+
builderFactory: runtimeBuilderFactory,
|
|
112
|
+
tenant: runtime?.tenant,
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
// Decide whether to include meta — `includeMeta` input field or x-include-meta header.
|
|
116
|
+
const includeMeta = input.includeMeta === true
|
|
117
|
+
|| ctx.request?.headers?.['x-include-meta'] === 'true';
|
|
118
|
+
return {
|
|
119
|
+
data: result.data,
|
|
120
|
+
meta: includeMeta ? result.meta : undefined,
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
return {
|
|
124
|
+
key: name,
|
|
125
|
+
method: 'POST',
|
|
126
|
+
inputSchema: metricQueryInputSchema,
|
|
127
|
+
outputSchema: metricResultSchema,
|
|
128
|
+
handler,
|
|
129
|
+
query: undefined,
|
|
130
|
+
middlewares: (resolved.middlewares ?? []),
|
|
131
|
+
auth: resolved.auth ?? null,
|
|
132
|
+
tenant: resolved.tenant,
|
|
133
|
+
metadata,
|
|
134
|
+
cacheTtlMs: resolved.cache ?? null,
|
|
135
|
+
defaultHeaders: undefined,
|
|
136
|
+
requiredRoles: resolved.requiredRoles,
|
|
137
|
+
requiredScopes: resolved.requiredScopes,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
function buildDescription(contract, maxLimit) {
|
|
141
|
+
const lines = [
|
|
142
|
+
contract.description ?? `${contract.name} metric on the ${contract.dataset} dataset.`,
|
|
143
|
+
'',
|
|
144
|
+
`**Type:** ${contract.kind}`,
|
|
145
|
+
`**Dataset:** ${contract.dataset}`,
|
|
146
|
+
`**Dimensions:** ${contract.dimensions.join(', ') || 'none'}`,
|
|
147
|
+
`**Max limit:** ${maxLimit}`,
|
|
148
|
+
];
|
|
149
|
+
if (contract.grains.length > 0) {
|
|
150
|
+
lines.push(`**Time grains:** ${contract.grains.join(', ')}`);
|
|
151
|
+
}
|
|
152
|
+
if (contract.requires && contract.requires.length > 0) {
|
|
153
|
+
lines.push(`**Requires:** ${contract.requires.join(', ')}`);
|
|
154
|
+
}
|
|
155
|
+
if (contract.tenantScoped) {
|
|
156
|
+
lines.push('**Tenant scoped:** yes');
|
|
157
|
+
}
|
|
158
|
+
return lines.join('\n');
|
|
159
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { AuthContext, AuthStrategy, ServeMiddleware, TenantConfigOverride } from '../../../types.js';
|
|
2
|
+
import type { AnyDatasetInstance } from '@hypequery/datasets';
|
|
3
|
+
export type DatasetEntry<TAuth extends AuthContext = AuthContext> = AnyDatasetInstance | {
|
|
4
|
+
dataset: AnyDatasetInstance;
|
|
5
|
+
auth?: AuthStrategy<TAuth> | null;
|
|
6
|
+
tenant?: TenantConfigOverride<TAuth>;
|
|
7
|
+
cache?: number | null;
|
|
8
|
+
requiredRoles?: string[];
|
|
9
|
+
requiredScopes?: string[];
|
|
10
|
+
/** Middleware applied to this dataset endpoint. */
|
|
11
|
+
middlewares?: ServeMiddleware<any, any, any, TAuth>[];
|
|
12
|
+
maxLimit?: number;
|
|
13
|
+
};
|
|
14
|
+
export declare function resolveDatasetEntry<TAuth extends AuthContext>(entry: DatasetEntry<TAuth>): {
|
|
15
|
+
dataset: AnyDatasetInstance;
|
|
16
|
+
auth?: AuthStrategy<TAuth> | null;
|
|
17
|
+
tenant?: TenantConfigOverride<TAuth>;
|
|
18
|
+
cache?: number | null;
|
|
19
|
+
requiredRoles?: string[];
|
|
20
|
+
requiredScopes?: string[];
|
|
21
|
+
middlewares?: ServeMiddleware<any, any, any, TAuth>[];
|
|
22
|
+
maxLimit?: number;
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=dataset-entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataset-entry.d.ts","sourceRoot":"","sources":["../../../../src/semantic/datasets/utils/dataset-entry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,eAAe,EACf,oBAAoB,EACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,MAAM,MAAM,YAAY,CAAC,KAAK,SAAS,WAAW,GAAG,WAAW,IAC5D,kBAAkB,GAClB;IACE,OAAO,EAAE,kBAAkB,CAAC;IAC5B,IAAI,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,oBAAoB,CAAC,KAAK,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,mDAAmD;IACnD,WAAW,CAAC,EAAE,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAgBN,wBAAgB,mBAAmB,CAAC,KAAK,SAAS,WAAW,EAC3D,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,GACzB;IACD,OAAO,EAAE,kBAAkB,CAAC;IAC5B,IAAI,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,oBAAoB,CAAC,KAAK,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,WAAW,CAAC,EAAE,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAUA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
function isDatasetInstance(entry) {
|
|
2
|
+
return !!entry && typeof entry === 'object' && '__type' in entry && entry.__type === 'dataset';
|
|
3
|
+
}
|
|
4
|
+
function isDatasetEntryOptions(entry) {
|
|
5
|
+
return !!entry && typeof entry === 'object' && 'dataset' in entry;
|
|
6
|
+
}
|
|
7
|
+
export function resolveDatasetEntry(entry) {
|
|
8
|
+
if (isDatasetInstance(entry)) {
|
|
9
|
+
return { dataset: entry };
|
|
10
|
+
}
|
|
11
|
+
if (isDatasetEntryOptions(entry)) {
|
|
12
|
+
return entry;
|
|
13
|
+
}
|
|
14
|
+
throw new Error('Invalid dataset entry.');
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataset-query-metadata.d.ts","sourceRoot":"","sources":["../../../../src/semantic/datasets/utils/dataset-query-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,wBAAgB,4BAA4B,CAC1C,EAAE,EAAE,kBAAkB,EACtB,QAAQ,EAAE,MAAM,GACf,MAAM,CAYR"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function buildDatasetQueryDescription(ds, maxLimit) {
|
|
2
|
+
const dimensionNames = Object.keys(ds.dimensions);
|
|
3
|
+
const measureNames = Object.keys(ds.measures);
|
|
4
|
+
const lines = [
|
|
5
|
+
`Query the ${ds.name} semantic dataset (source: ${ds.source}).`,
|
|
6
|
+
'',
|
|
7
|
+
`**Dimensions:** ${dimensionNames.join(', ') || 'none'}`,
|
|
8
|
+
`**Measures:** ${measureNames.join(', ') || 'none'}`,
|
|
9
|
+
`**Max limit:** ${maxLimit}`,
|
|
10
|
+
];
|
|
11
|
+
return lines.join('\n');
|
|
12
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds per-dataset / per-metric Zod input schemas whose dimension, measure,
|
|
3
|
+
* filter, and orderBy fields are constrained to the names the semantic
|
|
4
|
+
* validators accept. This upgrades the generated OpenAPI/docs from "array of
|
|
5
|
+
* arbitrary strings" to enumerated fields and enables typed client codegen.
|
|
6
|
+
*
|
|
7
|
+
* The enums are deliberately a *superset-safe* mirror of the runtime validators
|
|
8
|
+
* (`validateDatasetQueryInput` / the metric `validateQuery`): they never reject
|
|
9
|
+
* a field the validator would accept. Where a list would be empty (e.g. a
|
|
10
|
+
* dataset with no declared filters) we fall back to `z.string()` and let the
|
|
11
|
+
* validator produce the precise error, rather than emitting an empty enum.
|
|
12
|
+
*/
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
import type { AnyDatasetInstance } from '@hypequery/datasets';
|
|
15
|
+
/**
|
|
16
|
+
* Input schema for a dataset query endpoint, mirroring
|
|
17
|
+
* `validateDatasetQueryInput`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function buildDatasetInputSchema(ds: AnyDatasetInstance): z.ZodObject<{
|
|
20
|
+
dimensions: z.ZodOptional<z.ZodArray<z.ZodTypeAny, "many">>;
|
|
21
|
+
measures: z.ZodOptional<z.ZodArray<z.ZodTypeAny, "many">>;
|
|
22
|
+
filters: z.ZodOptional<z.ZodArray<z.ZodTypeAny, "many">>;
|
|
23
|
+
orderBy: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
24
|
+
field: z.ZodTypeAny;
|
|
25
|
+
direction: z.ZodEnum<["asc", "desc"]>;
|
|
26
|
+
}, "strip", z.ZodTypeAny, {
|
|
27
|
+
direction: "asc" | "desc";
|
|
28
|
+
field?: any;
|
|
29
|
+
}, {
|
|
30
|
+
direction: "asc" | "desc";
|
|
31
|
+
field?: any;
|
|
32
|
+
}>, "many">>;
|
|
33
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
34
|
+
offset: z.ZodOptional<z.ZodNumber>;
|
|
35
|
+
by: z.ZodOptional<z.ZodEnum<["day", "week", "month", "quarter", "year"]>>;
|
|
36
|
+
includeMeta: z.ZodOptional<z.ZodBoolean>;
|
|
37
|
+
}, "strict", z.ZodTypeAny, {
|
|
38
|
+
dimensions?: any[] | undefined;
|
|
39
|
+
measures?: any[] | undefined;
|
|
40
|
+
filters?: any[] | undefined;
|
|
41
|
+
orderBy?: {
|
|
42
|
+
direction: "asc" | "desc";
|
|
43
|
+
field?: any;
|
|
44
|
+
}[] | undefined;
|
|
45
|
+
limit?: number | undefined;
|
|
46
|
+
offset?: number | undefined;
|
|
47
|
+
by?: "day" | "week" | "month" | "quarter" | "year" | undefined;
|
|
48
|
+
includeMeta?: boolean | undefined;
|
|
49
|
+
}, {
|
|
50
|
+
dimensions?: any[] | undefined;
|
|
51
|
+
measures?: any[] | undefined;
|
|
52
|
+
filters?: any[] | undefined;
|
|
53
|
+
orderBy?: {
|
|
54
|
+
direction: "asc" | "desc";
|
|
55
|
+
field?: any;
|
|
56
|
+
}[] | undefined;
|
|
57
|
+
limit?: number | undefined;
|
|
58
|
+
offset?: number | undefined;
|
|
59
|
+
by?: "day" | "week" | "month" | "quarter" | "year" | undefined;
|
|
60
|
+
includeMeta?: boolean | undefined;
|
|
61
|
+
}>;
|
|
62
|
+
/**
|
|
63
|
+
* Input schema for a metric query endpoint, mirroring the metric `validateQuery`.
|
|
64
|
+
* Metrics select a single value, so there is no `measures` field; `orderBy` may
|
|
65
|
+
* reference the metric's own output column (`metricName`).
|
|
66
|
+
*/
|
|
67
|
+
export declare function buildMetricInputSchema(ds: AnyDatasetInstance, metricName: string): z.ZodObject<{
|
|
68
|
+
dimensions: z.ZodOptional<z.ZodArray<z.ZodTypeAny, "many">>;
|
|
69
|
+
filters: z.ZodOptional<z.ZodArray<z.ZodTypeAny, "many">>;
|
|
70
|
+
orderBy: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
71
|
+
field: z.ZodTypeAny;
|
|
72
|
+
direction: z.ZodEnum<["asc", "desc"]>;
|
|
73
|
+
}, "strip", z.ZodTypeAny, {
|
|
74
|
+
direction: "asc" | "desc";
|
|
75
|
+
field?: any;
|
|
76
|
+
}, {
|
|
77
|
+
direction: "asc" | "desc";
|
|
78
|
+
field?: any;
|
|
79
|
+
}>, "many">>;
|
|
80
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
81
|
+
offset: z.ZodOptional<z.ZodNumber>;
|
|
82
|
+
by: z.ZodOptional<z.ZodEnum<["day", "week", "month", "quarter", "year"]>>;
|
|
83
|
+
includeMeta: z.ZodOptional<z.ZodBoolean>;
|
|
84
|
+
}, "strip", z.ZodTypeAny, {
|
|
85
|
+
dimensions?: any[] | undefined;
|
|
86
|
+
filters?: any[] | undefined;
|
|
87
|
+
orderBy?: {
|
|
88
|
+
direction: "asc" | "desc";
|
|
89
|
+
field?: any;
|
|
90
|
+
}[] | undefined;
|
|
91
|
+
limit?: number | undefined;
|
|
92
|
+
offset?: number | undefined;
|
|
93
|
+
by?: "day" | "week" | "month" | "quarter" | "year" | undefined;
|
|
94
|
+
includeMeta?: boolean | undefined;
|
|
95
|
+
}, {
|
|
96
|
+
dimensions?: any[] | undefined;
|
|
97
|
+
filters?: any[] | undefined;
|
|
98
|
+
orderBy?: {
|
|
99
|
+
direction: "asc" | "desc";
|
|
100
|
+
field?: any;
|
|
101
|
+
}[] | undefined;
|
|
102
|
+
limit?: number | undefined;
|
|
103
|
+
offset?: number | undefined;
|
|
104
|
+
by?: "day" | "week" | "month" | "quarter" | "year" | undefined;
|
|
105
|
+
includeMeta?: boolean | undefined;
|
|
106
|
+
}>;
|
|
107
|
+
//# sourceMappingURL=semantic-input-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semantic-input-schema.d.ts","sourceRoot":"","sources":["../../../../src/semantic/datasets/utils/semantic-input-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAqC9D;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmB7D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiBhF"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds per-dataset / per-metric Zod input schemas whose dimension, measure,
|
|
3
|
+
* filter, and orderBy fields are constrained to the names the semantic
|
|
4
|
+
* validators accept. This upgrades the generated OpenAPI/docs from "array of
|
|
5
|
+
* arbitrary strings" to enumerated fields and enables typed client codegen.
|
|
6
|
+
*
|
|
7
|
+
* The enums are deliberately a *superset-safe* mirror of the runtime validators
|
|
8
|
+
* (`validateDatasetQueryInput` / the metric `validateQuery`): they never reject
|
|
9
|
+
* a field the validator would accept. Where a list would be empty (e.g. a
|
|
10
|
+
* dataset with no declared filters) we fall back to `z.string()` and let the
|
|
11
|
+
* validator produce the precise error, rather than emitting an empty enum.
|
|
12
|
+
*/
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
const OPERATORS = [
|
|
15
|
+
'eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'in', 'notIn', 'between', 'like',
|
|
16
|
+
];
|
|
17
|
+
const GRAINS = ['day', 'week', 'month', 'quarter', 'year'];
|
|
18
|
+
/** An enum over the given field names, or a plain string when none are known. */
|
|
19
|
+
function fieldEnum(values) {
|
|
20
|
+
const unique = Array.from(new Set(values));
|
|
21
|
+
return unique.length > 0
|
|
22
|
+
? z.enum(unique)
|
|
23
|
+
: z.string();
|
|
24
|
+
}
|
|
25
|
+
function filterSchema(fieldNames) {
|
|
26
|
+
return z.object({
|
|
27
|
+
field: fieldEnum(fieldNames),
|
|
28
|
+
operator: z.enum(OPERATORS),
|
|
29
|
+
value: z.unknown(),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function orderBySchema(fieldNames) {
|
|
33
|
+
return z.object({
|
|
34
|
+
field: fieldEnum(fieldNames),
|
|
35
|
+
direction: z.enum(['asc', 'desc']),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/** Apply a `.max()` bound only when the dataset declares one. */
|
|
39
|
+
function boundedArray(item, max) {
|
|
40
|
+
const arr = z.array(item);
|
|
41
|
+
return (max != null ? arr.max(max) : arr).optional();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Input schema for a dataset query endpoint, mirroring
|
|
45
|
+
* `validateDatasetQueryInput`.
|
|
46
|
+
*/
|
|
47
|
+
export function buildDatasetInputSchema(ds) {
|
|
48
|
+
const dimensionNames = Object.keys(ds.dimensions);
|
|
49
|
+
const measureNames = Object.keys(ds.measures);
|
|
50
|
+
// Dataset filters are keyed by filter-definition name (no dimension fallback).
|
|
51
|
+
const filterNames = Object.keys(ds.filters);
|
|
52
|
+
// orderBy is query-dependent at runtime; the static superset is every
|
|
53
|
+
// dimension/measure plus the synthetic `period` column when grained.
|
|
54
|
+
const orderableNames = [...dimensionNames, ...measureNames, 'period'];
|
|
55
|
+
return z.object({
|
|
56
|
+
dimensions: boundedArray(fieldEnum(dimensionNames), ds.limits?.maxDimensions),
|
|
57
|
+
measures: boundedArray(fieldEnum(measureNames), ds.limits?.maxMeasures),
|
|
58
|
+
filters: boundedArray(filterSchema(filterNames), ds.limits?.maxFilters),
|
|
59
|
+
orderBy: z.array(orderBySchema(orderableNames)).optional(),
|
|
60
|
+
limit: z.number().int().positive().optional(),
|
|
61
|
+
offset: z.number().int().nonnegative().optional(),
|
|
62
|
+
by: z.enum(GRAINS).optional(),
|
|
63
|
+
includeMeta: z.boolean().optional(),
|
|
64
|
+
}).strict();
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Input schema for a metric query endpoint, mirroring the metric `validateQuery`.
|
|
68
|
+
* Metrics select a single value, so there is no `measures` field; `orderBy` may
|
|
69
|
+
* reference the metric's own output column (`metricName`).
|
|
70
|
+
*/
|
|
71
|
+
export function buildMetricInputSchema(ds, metricName) {
|
|
72
|
+
const dimensionNames = Object.keys(ds.dimensions);
|
|
73
|
+
// Metric validator falls back to dimension names when no filters are declared.
|
|
74
|
+
const filterNames = Object.keys(ds.filters).length > 0
|
|
75
|
+
? Object.keys(ds.filters)
|
|
76
|
+
: dimensionNames;
|
|
77
|
+
const orderableNames = [...dimensionNames, metricName, 'period'];
|
|
78
|
+
return z.object({
|
|
79
|
+
dimensions: boundedArray(fieldEnum(dimensionNames), ds.limits?.maxDimensions),
|
|
80
|
+
filters: boundedArray(filterSchema(filterNames), ds.limits?.maxFilters),
|
|
81
|
+
orderBy: z.array(orderBySchema(orderableNames)).optional(),
|
|
82
|
+
limit: z.number().int().positive().optional(),
|
|
83
|
+
offset: z.number().int().nonnegative().optional(),
|
|
84
|
+
by: z.enum(GRAINS).optional(),
|
|
85
|
+
includeMeta: z.boolean().optional(),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/semantic/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './datasets/index.js';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { QueryBuilderFactoryLike, SemanticExecutionRuntime } from "@hypequery/datasets";
|
|
2
|
+
export declare const INTERNAL_SEMANTIC_RUNTIME_KEY = "__hypequerySemanticRuntime";
|
|
3
|
+
/**
|
|
4
|
+
* Type guard to check if a value is a QueryBuilderFactoryLike.
|
|
5
|
+
* Uses duck-typing to detect the required methods.
|
|
6
|
+
*/
|
|
7
|
+
export declare function isQueryBuilderFactoryLike(value: unknown): value is QueryBuilderFactoryLike;
|
|
8
|
+
/**
|
|
9
|
+
* Extract queryBuilder from context.db if available.
|
|
10
|
+
* This allows users to pass queryBuilder via context instead of top-level config.
|
|
11
|
+
*/
|
|
12
|
+
export declare function extractQueryBuilderFromContext(context: Record<string, unknown>): QueryBuilderFactoryLike | undefined;
|
|
13
|
+
export declare function attachSemanticQueryBuilder<TContext extends Record<string, unknown>>(context: TContext, builderFactory: QueryBuilderFactoryLike | undefined): TContext;
|
|
14
|
+
export declare function attachSemanticRuntime<TContext extends Record<string, unknown>>(context: TContext, runtime: SemanticExecutionRuntime): TContext;
|
|
15
|
+
export declare function resolveSemanticExecutionRuntime(context: Record<string, unknown>): SemanticExecutionRuntime | undefined;
|
|
16
|
+
export declare function resolveSemanticQueryBuilder(context: Record<string, unknown>, fallback: QueryBuilderFactoryLike): QueryBuilderFactoryLike;
|
|
17
|
+
export declare function attachSemanticTenantRuntime<TContext extends Record<string, unknown>>(context: TContext, options: {
|
|
18
|
+
tenantId: string;
|
|
19
|
+
}): TContext;
|
|
20
|
+
//# sourceMappingURL=query-builder-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-builder-context.d.ts","sourceRoot":"","sources":["../../src/semantic/query-builder-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAE7F,eAAO,MAAM,6BAA6B,+BAA+B,CAAC;AAM1E;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,uBAAuB,CAS1F;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,uBAAuB,GAAG,SAAS,CAarC;AAED,wBAAgB,0BAA0B,CACxC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAExC,OAAO,EAAE,QAAQ,EACjB,cAAc,EAAE,uBAAuB,GAAG,SAAS,GAClD,QAAQ,CAMV;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5E,OAAO,EAAE,QAAQ,EACjB,OAAO,EAAE,wBAAwB,GAChC,QAAQ,CAUV;AAED,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,wBAAwB,GAAG,SAAS,CAMtC;AAED,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,QAAQ,EAAE,uBAAuB,GAChC,uBAAuB,CAEzB;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClF,OAAO,EAAE,QAAQ,EACjB,OAAO,EAAE;IACP,QAAQ,EAAE,MAAM,CAAC;CAClB,GACA,QAAQ,CAMV"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export const INTERNAL_SEMANTIC_RUNTIME_KEY = "__hypequerySemanticRuntime";
|
|
2
|
+
function isSemanticExecutionRuntime(value) {
|
|
3
|
+
return typeof value === 'object' && value !== null;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Type guard to check if a value is a QueryBuilderFactoryLike.
|
|
7
|
+
* Uses duck-typing to detect the required methods.
|
|
8
|
+
*/
|
|
9
|
+
export function isQueryBuilderFactoryLike(value) {
|
|
10
|
+
return (typeof value === 'object' &&
|
|
11
|
+
value !== null &&
|
|
12
|
+
'table' in value &&
|
|
13
|
+
typeof value.table === 'function' &&
|
|
14
|
+
'rawQuery' in value &&
|
|
15
|
+
typeof value.rawQuery === 'function');
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Extract queryBuilder from context.db if available.
|
|
19
|
+
* This allows users to pass queryBuilder via context instead of top-level config.
|
|
20
|
+
*/
|
|
21
|
+
export function extractQueryBuilderFromContext(context) {
|
|
22
|
+
// Check if context.db is a queryBuilder
|
|
23
|
+
if ('db' in context && isQueryBuilderFactoryLike(context.db)) {
|
|
24
|
+
return context.db;
|
|
25
|
+
}
|
|
26
|
+
// Check if it's already in the semantic runtime
|
|
27
|
+
const runtime = resolveSemanticExecutionRuntime(context);
|
|
28
|
+
if (runtime?.builderFactory) {
|
|
29
|
+
return runtime.builderFactory;
|
|
30
|
+
}
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
export function attachSemanticQueryBuilder(context, builderFactory) {
|
|
34
|
+
if (!builderFactory) {
|
|
35
|
+
return context;
|
|
36
|
+
}
|
|
37
|
+
return attachSemanticRuntime(context, { builderFactory });
|
|
38
|
+
}
|
|
39
|
+
export function attachSemanticRuntime(context, runtime) {
|
|
40
|
+
const current = resolveSemanticExecutionRuntime(context);
|
|
41
|
+
return {
|
|
42
|
+
...context,
|
|
43
|
+
[INTERNAL_SEMANTIC_RUNTIME_KEY]: {
|
|
44
|
+
...(current ?? {}),
|
|
45
|
+
...runtime,
|
|
46
|
+
tenant: runtime.tenant ?? current?.tenant,
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export function resolveSemanticExecutionRuntime(context) {
|
|
51
|
+
const candidate = context[INTERNAL_SEMANTIC_RUNTIME_KEY];
|
|
52
|
+
if (!isSemanticExecutionRuntime(candidate)) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
return candidate;
|
|
56
|
+
}
|
|
57
|
+
export function resolveSemanticQueryBuilder(context, fallback) {
|
|
58
|
+
return resolveSemanticExecutionRuntime(context)?.builderFactory ?? fallback;
|
|
59
|
+
}
|
|
60
|
+
export function attachSemanticTenantRuntime(context, options) {
|
|
61
|
+
return attachSemanticRuntime(context, {
|
|
62
|
+
tenant: {
|
|
63
|
+
id: options.tenantId,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { EndpointMetadata } from '../../types.js';
|
|
2
|
+
export declare function applySemanticTenantRuntime<TContext extends Record<string, unknown>>(context: TContext & {
|
|
3
|
+
tenantId?: string;
|
|
4
|
+
}, options: {
|
|
5
|
+
queryKey: string;
|
|
6
|
+
metadata: EndpointMetadata;
|
|
7
|
+
tenantId: string;
|
|
8
|
+
mode: 'manual' | 'auto-inject';
|
|
9
|
+
column?: string;
|
|
10
|
+
}): void;
|
|
11
|
+
//# sourceMappingURL=tenant-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-runtime.d.ts","sourceRoot":"","sources":["../../../src/semantic/utils/tenant-runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAyBvD,wBAAgB,0BAA0B,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjF,OAAO,EAAE,QAAQ,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,EACzC,OAAO,EAAE;IACP,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,QAAQ,GAAG,aAAa,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACA,IAAI,CAyCN"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { createTenantScope, warnTenantMisconfiguration } from '../../tenant.js';
|
|
2
|
+
import { attachSemanticRuntime, attachSemanticTenantRuntime, resolveSemanticExecutionRuntime, } from '../query-builder-context.js';
|
|
3
|
+
function usesServeTenantRuntimeMetadata(metadata) {
|
|
4
|
+
return Boolean(metadata.custom
|
|
5
|
+
&& typeof metadata.custom === 'object'
|
|
6
|
+
&& metadata.custom !== null
|
|
7
|
+
&& 'usesServeTenantRuntime' in metadata.custom
|
|
8
|
+
&& metadata.custom.usesServeTenantRuntime === true);
|
|
9
|
+
}
|
|
10
|
+
function hasTableFactory(value) {
|
|
11
|
+
return !!value && typeof value === 'object' && 'table' in value && typeof value.table === 'function';
|
|
12
|
+
}
|
|
13
|
+
export function applySemanticTenantRuntime(context, options) {
|
|
14
|
+
const mutableContext = context;
|
|
15
|
+
const usesServeTenantRuntime = usesServeTenantRuntimeMetadata(options.metadata);
|
|
16
|
+
const semanticRuntime = resolveSemanticExecutionRuntime(context);
|
|
17
|
+
if (options.mode === 'auto-inject' && options.column && semanticRuntime?.builderFactory) {
|
|
18
|
+
Object.assign(context, attachSemanticRuntime(context, {
|
|
19
|
+
tenant: {
|
|
20
|
+
id: options.tenantId,
|
|
21
|
+
},
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
Object.assign(context, attachSemanticTenantRuntime(context, {
|
|
26
|
+
tenantId: options.tenantId,
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
if (options.mode === 'auto-inject' && options.column) {
|
|
30
|
+
for (const key of Object.keys(mutableContext)) {
|
|
31
|
+
const value = mutableContext[key];
|
|
32
|
+
if (hasTableFactory(value)) {
|
|
33
|
+
mutableContext[key] = createTenantScope(value, {
|
|
34
|
+
tenantId: options.tenantId,
|
|
35
|
+
column: options.column,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else if (options.mode === 'manual' && !usesServeTenantRuntime) {
|
|
41
|
+
warnTenantMisconfiguration({
|
|
42
|
+
queryKey: options.queryKey,
|
|
43
|
+
hasTenantConfig: true,
|
|
44
|
+
hasTenantId: true,
|
|
45
|
+
mode: 'manual',
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
package/dist/serve.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AuthContext, QueryObjectConfig, SchemaOutput, ServeBuilder, ServeConfig, ServeContextFactory, ServeEndpointMap, ServeQueriesMap, StandaloneQueryDefinition } from "./types.js";
|
|
1
|
+
import type { AuthContext, QueryObjectConfig, SchemaOutput, ServeBuilder, ServeConfig, ServeContextFactory, ServeEndpointMap, ServeSemanticEndpointMap, ServeQueriesMap, StandaloneQueryDefinition, MetricsConfig, DatasetsConfig } from "./types.js";
|
|
2
2
|
import type { ZodTypeAny } from "zod";
|
|
3
3
|
export declare const createQueryFactory: <TContext extends Record<string, unknown> = Record<string, unknown>, TAuth extends AuthContext = AuthContext>(contextFactory?: ServeContextFactory<TContext, TAuth>) => <TInputSchema extends ZodTypeAny | undefined = undefined, TOutputSchema extends ZodTypeAny | undefined = undefined, TResult = TOutputSchema extends ZodTypeAny ? SchemaOutput<TOutputSchema> : unknown>(config: QueryObjectConfig<TInputSchema, TOutputSchema, TContext, TAuth, TResult>) => StandaloneQueryDefinition<TInputSchema, TOutputSchema extends ZodTypeAny ? TOutputSchema : ZodTypeAny, TContext, TAuth, TResult>;
|
|
4
4
|
/**
|
|
@@ -12,5 +12,5 @@ export declare const query: <TInputSchema extends ZodTypeAny | undefined = undef
|
|
|
12
12
|
*
|
|
13
13
|
* This is the unbound version. Use `initServe().serve(...)` when you want shared context and config.
|
|
14
14
|
*/
|
|
15
|
-
export declare function serve<TContext extends Record<string, unknown> = Record<string, unknown>, TAuth extends AuthContext = AuthContext, TQueries extends ServeQueriesMap<TContext, TAuth> =
|
|
15
|
+
export declare function serve<TContext extends Record<string, unknown> = Record<string, unknown>, TAuth extends AuthContext = AuthContext, TQueries extends ServeQueriesMap<TContext, TAuth> = Record<never, never>, TMetrics extends MetricsConfig<TAuth> = Record<never, never>, TDatasets extends DatasetsConfig<TAuth> = Record<never, never>>(config: ServeConfig<TContext, TAuth, TQueries, TMetrics, TDatasets>): ServeBuilder<ServeEndpointMap<TQueries, TContext, TAuth> & ServeSemanticEndpointMap<TMetrics, TDatasets, TContext, TAuth>, TContext, TAuth>;
|
|
16
16
|
//# sourceMappingURL=serve.d.ts.map
|
package/dist/serve.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EAEX,iBAAiB,EAGjB,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EAEf,yBAAyB,
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EAEX,iBAAiB,EAGjB,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,wBAAwB,EACxB,eAAe,EAEf,yBAAyB,EACzB,aAAa,EACb,cAAc,EACf,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAgGtC,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,KAAK,SAAS,WAAW,GAAG,WAAW,EAEvC,iBAAiB,mBAAmB,CAAC,QAAQ,EAAE,KAAK,CAAC,MAGnD,YAAY,SAAS,UAAU,GAAG,SAAS,GAAG,SAAS,EACvD,aAAa,SAAS,UAAU,GAAG,SAAS,GAAG,SAAS,EACxD,OAAO,GAAG,aAAa,SAAS,UAAU,GAAG,YAAY,CAAC,aAAa,CAAC,GAAG,OAAO,EAElF,QAAQ,iBAAiB,CAAC,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,KAC/E,yBAAyB,CAC1B,YAAY,EACZ,aAAa,SAAS,UAAU,GAAG,aAAa,GAAG,UAAU,EAC7D,QAAQ,EACR,KAAK,EACL,OAAO,CAIV,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,KAAK,GArBd,YAAY,SAAS,UAAU,GAAG,SAAS,cAC3C,aAAa,SAAS,UAAU,GAAG,SAAS,cAC5C,OAAO,4UAmB8B,CAAC;AAE1C;;;;GAIG;AACH,wBAAgB,KAAK,CACnB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,KAAK,SAAS,WAAW,GAAG,WAAW,EACvC,QAAQ,SAAS,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EACxE,QAAQ,SAAS,aAAa,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAC5D,SAAS,SAAS,cAAc,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAE9D,MAAM,EAAE,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,GAClE,YAAY,CACb,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,GACvC,wBAAwB,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,EAClE,QAAQ,EACR,KAAK,CACN,CAEA"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AuthContext, AuthStrategy, HypeQueryAPI, ServeEndpointMap, ServeMiddleware, ServeQueriesMap, ServeHandler, ExecuteQueryFunction } from "../types.js";
|
|
2
|
+
import type { ServeRouter } from "../router.js";
|
|
3
|
+
import { ServeQueryLogger } from "../query-logger.js";
|
|
4
|
+
export declare const createAPImethods: <TQueries extends ServeQueriesMap<TContext, TAuth>, TContext extends Record<string, unknown>, TAuth extends AuthContext>(queryEntries: ServeEndpointMap<TQueries, TContext, TAuth>, queryLogger: ServeQueryLogger, router: ServeRouter, authStrategies: AuthStrategy<TAuth>[], globalMiddlewares: ServeMiddleware<any, any, TContext, TAuth>[], executeQuery: ExecuteQueryFunction<ServeEndpointMap<TQueries, TContext, TAuth>, TContext>, handler: ServeHandler, basePath: string) => HypeQueryAPI<ServeEndpointMap<TQueries, TContext, TAuth>, TContext, TAuth>;
|
|
5
|
+
//# sourceMappingURL=api-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-builder.d.ts","sourceRoot":"","sources":["../../src/server/api-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,YAAY,EAIZ,gBAAgB,EAChB,eAAe,EAEf,eAAe,EACf,YAAY,EACZ,oBAAoB,EAErB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAKtD,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,SAAS,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,EACjD,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,KAAK,SAAS,WAAW,EAEzB,cAAc,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,EACzD,aAAa,gBAAgB,EAC7B,QAAQ,WAAW,EACnB,gBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE,EACrC,mBAAmB,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,EAC/D,cAAc,oBAAoB,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,EACzF,SAAS,YAAY,EACrB,UAAU,MAAM,KACf,YAAY,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,QAAQ,EAAE,KAAK,CA0F3E,CAAC"}
|