@danceroutine/tango-resources 1.11.3 → 1.11.5

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.
Files changed (49) hide show
  1. package/README.md +2 -2
  2. package/dist/CursorPaginator-B_8MhYZY.js +195 -0
  3. package/dist/CursorPaginator-B_8MhYZY.js.map +1 -0
  4. package/dist/CursorPaginator-CfeMQCdJ.d.ts +177 -0
  5. package/dist/OffsetPaginator-CaycvxJU.js +188 -0
  6. package/dist/OffsetPaginator-CaycvxJU.js.map +1 -0
  7. package/dist/context/index.d.ts +2 -0
  8. package/dist/context/index.js +2 -0
  9. package/dist/context-euBQvNRT.js +65 -0
  10. package/dist/context-euBQvNRT.js.map +1 -0
  11. package/dist/filters/index.d.ts +2 -0
  12. package/dist/filters/index.js +2 -0
  13. package/dist/filters-46d2Nr5C.js +287 -0
  14. package/dist/filters-46d2Nr5C.js.map +1 -0
  15. package/dist/index-Ac94YL5S.d.ts +24 -0
  16. package/dist/index-BJJalUDB.d.ts +54 -0
  17. package/dist/index-Bg6TtnmQ.d.ts +175 -0
  18. package/dist/index-C55GDIOn.d.ts +222 -0
  19. package/dist/index-CiIB-1Ac.d.ts +123 -0
  20. package/dist/index-DkJtxvKu.d.ts +164 -0
  21. package/dist/index.d.ts +10 -12
  22. package/dist/index.js +10 -1013
  23. package/dist/inferModelFieldParsers-2irv7j1T.js +70 -0
  24. package/dist/inferModelFieldParsers-2irv7j1T.js.map +1 -0
  25. package/dist/pagination/index.d.ts +3 -0
  26. package/dist/pagination/index.js +15 -0
  27. package/dist/pagination/index.js.map +1 -0
  28. package/dist/paginators/index.d.ts +9 -0
  29. package/dist/paginators/index.js +12 -0
  30. package/dist/paginators/index.js.map +1 -0
  31. package/dist/resource/index.d.ts +3 -0
  32. package/dist/resource/index.js +7 -0
  33. package/dist/resource/index.js.map +1 -0
  34. package/dist/serializer/index.d.ts +2 -0
  35. package/dist/serializer/index.js +2 -0
  36. package/dist/serializer-RSwlXWls.js +305 -0
  37. package/dist/serializer-RSwlXWls.js.map +1 -0
  38. package/dist/view/index.d.ts +2 -1
  39. package/dist/view/index.js +1 -1
  40. package/dist/{view-C9B5Lln3.js → view-CYdJAO4t.js} +7 -314
  41. package/dist/view-CYdJAO4t.js.map +1 -0
  42. package/dist/viewset/index.d.ts +9 -0
  43. package/dist/viewset/index.js +2 -0
  44. package/dist/viewset-C9j-2U29.js +227 -0
  45. package/dist/viewset-C9j-2U29.js.map +1 -0
  46. package/package.json +21 -17
  47. package/dist/index-D6sfTSEj.d.ts +0 -902
  48. package/dist/index.js.map +0 -1
  49. package/dist/view-C9B5Lln3.js.map +0 -1
@@ -0,0 +1,65 @@
1
+ import { t as __exportAll } from "./chunk-D7D4PA-g.js";
2
+ import { TangoRequest } from "@danceroutine/tango-core";
3
+ //#region src/context/RequestContext.ts
4
+ /**
5
+ * Normalized request context passed through the framework adapter into viewset methods.
6
+ * Generic over the user type so consumers can plug in their own auth infrastructure.
7
+ */
8
+ var RequestContext = class RequestContext {
9
+ request;
10
+ user;
11
+ params;
12
+ static BRAND = "tango.resources.request_context";
13
+ __tangoBrand = RequestContext.BRAND;
14
+ state = /* @__PURE__ */ new Map();
15
+ constructor(request, user = null, params = {}) {
16
+ this.request = request;
17
+ this.user = user;
18
+ this.params = params;
19
+ }
20
+ /**
21
+ * Narrow an unknown value to `RequestContext`.
22
+ */
23
+ static isRequestContext(value) {
24
+ return typeof value === "object" && value !== null && value.__tangoBrand === RequestContext.BRAND;
25
+ }
26
+ /**
27
+ * Construct a context with optional user payload.
28
+ */
29
+ static create(request, user) {
30
+ return new RequestContext(TangoRequest.isTangoRequest(request) ? request : new TangoRequest(request), user ?? null);
31
+ }
32
+ /**
33
+ * Store arbitrary per-request state for downstream middleware/handlers.
34
+ */
35
+ setState(key, value) {
36
+ this.state.set(key, value);
37
+ }
38
+ /**
39
+ * Retrieve previously stored request state.
40
+ */
41
+ getState(key) {
42
+ return this.state.get(key);
43
+ }
44
+ /**
45
+ * Check whether a state key has been set.
46
+ */
47
+ hasState(key) {
48
+ return this.state.has(key);
49
+ }
50
+ /**
51
+ * Clone the context, including route params and request-local state.
52
+ */
53
+ clone() {
54
+ const cloned = new RequestContext(this.request, this.user, { ...this.params });
55
+ cloned.state = new Map(this.state);
56
+ return cloned;
57
+ }
58
+ };
59
+ //#endregion
60
+ //#region src/context/index.ts
61
+ var context_exports = /* @__PURE__ */ __exportAll({ RequestContext: () => RequestContext });
62
+ //#endregion
63
+ export { RequestContext as n, context_exports as t };
64
+
65
+ //# sourceMappingURL=context-euBQvNRT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-euBQvNRT.js","names":[],"sources":["../src/context/RequestContext.ts","../src/context/index.ts"],"sourcesContent":["import { TangoRequest } from '@danceroutine/tango-core';\n\n/**\n * Default user shape for RequestContext.\n * Consumers can provide their own user type via the TUser generic parameter.\n */\nexport interface BaseUser {\n id: string | number;\n roles?: string[];\n}\n\n/**\n * Normalized request context passed through the framework adapter into viewset methods.\n * Generic over the user type so consumers can plug in their own auth infrastructure.\n */\nexport class RequestContext<TUser = BaseUser> {\n static readonly BRAND = 'tango.resources.request_context' as const;\n readonly __tangoBrand: typeof RequestContext.BRAND = RequestContext.BRAND;\n private state: Map<string | symbol, unknown> = new Map();\n\n constructor(\n public readonly request: TangoRequest,\n public user: TUser | null = null,\n public params: Record<string, string> = {}\n ) {}\n\n /**\n * Narrow an unknown value to `RequestContext`.\n */\n static isRequestContext<TUser = BaseUser>(value: unknown): value is RequestContext<TUser> {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === RequestContext.BRAND\n );\n }\n\n /**\n * Construct a context with optional user payload.\n */\n static create<TUser = BaseUser>(request: Request, user?: TUser | null): RequestContext<TUser> {\n return new RequestContext<TUser>(\n TangoRequest.isTangoRequest(request) ? request : new TangoRequest(request),\n user ?? null\n );\n }\n\n /**\n * Store arbitrary per-request state for downstream middleware/handlers.\n */\n setState<T>(key: string | symbol, value: T): void {\n this.state.set(key, value);\n }\n\n /**\n * Retrieve previously stored request state.\n */\n getState<T>(key: string | symbol): T | undefined {\n return this.state.get(key) as T | undefined;\n }\n\n /**\n * Check whether a state key has been set.\n */\n hasState(key: string | symbol): boolean {\n return this.state.has(key);\n }\n\n /**\n * Clone the context, including route params and request-local state.\n */\n clone(): RequestContext<TUser> {\n const cloned = new RequestContext<TUser>(this.request, this.user, { ...this.params });\n cloned.state = new Map(this.state);\n return cloned;\n }\n}\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport type { BaseUser } from './RequestContext';\nexport { RequestContext } from './RequestContext';\n"],"mappings":";;;;;;;AAeA,IAAa,iBAAb,MAAa,eAAiC;CAMtB;CACT;CACA;CAPX,OAAgB,QAAQ;CACxB,eAAqD,eAAe;CACpE,wBAA+C,IAAI,IAAI;CAEvD,YACI,SACA,OAA4B,MAC5B,SAAwC,CAAC,GAC3C;EAHkB,KAAA,UAAA;EACT,KAAA,OAAA;EACA,KAAA,SAAA;CACR;;;;CAKH,OAAO,iBAAmC,OAAgD;EACtF,OACI,OAAO,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB,eAAe;CAE9E;;;;CAKA,OAAO,OAAyB,SAAkB,MAA4C;EAC1F,OAAO,IAAI,eACP,aAAa,eAAe,OAAO,IAAI,UAAU,IAAI,aAAa,OAAO,GACzE,QAAQ,IACZ;CACJ;;;;CAKA,SAAY,KAAsB,OAAgB;EAC9C,KAAK,MAAM,IAAI,KAAK,KAAK;CAC7B;;;;CAKA,SAAY,KAAqC;EAC7C,OAAO,KAAK,MAAM,IAAI,GAAG;CAC7B;;;;CAKA,SAAS,KAA+B;EACpC,OAAO,KAAK,MAAM,IAAI,GAAG;CAC7B;;;;CAKA,QAA+B;EAC3B,MAAM,SAAS,IAAI,eAAsB,KAAK,SAAS,KAAK,MAAM,EAAE,GAAG,KAAK,OAAO,CAAC;EACpF,OAAO,QAAQ,IAAI,IAAI,KAAK,KAAK;EACjC,OAAO;CACX;AACJ"}
@@ -0,0 +1,2 @@
1
+ import { a as FilterResolver, c as FilterValueParser, i as FilterLookup, l as RangeOperator, n as AliasFilterDeclaration, o as FilterSet, r as FieldFilterDeclaration, s as FilterSetDefineConfig, u as FilterType } from "../index-CiIB-1Ac.js";
2
+ export { type AliasFilterDeclaration, type FieldFilterDeclaration, type FilterLookup, type FilterResolver, FilterSet, type FilterSetDefineConfig, type FilterType, type FilterValueParser, type RangeOperator };
@@ -0,0 +1,2 @@
1
+ import { n as FilterSet } from "../filters-46d2Nr5C.js";
2
+ export { FilterSet };
@@ -0,0 +1,287 @@
1
+ import { t as __exportAll } from "./chunk-D7D4PA-g.js";
2
+ import "@danceroutine/tango-core";
3
+ //#region src/filters/internal/InternalFilterType.ts
4
+ const InternalFilterType = {
5
+ SCALAR: "scalar",
6
+ ILIKE: "ilike",
7
+ RANGE: "range",
8
+ IN: "in",
9
+ CUSTOM: "custom"
10
+ };
11
+ //#endregion
12
+ //#region src/filters/internal/InternalFilterLookup.ts
13
+ const InternalFilterLookup = {
14
+ EXACT: "exact",
15
+ LT: "lt",
16
+ LTE: "lte",
17
+ GT: "gt",
18
+ GTE: "gte",
19
+ IN: "in",
20
+ ISNULL: "isnull",
21
+ CONTAINS: "contains",
22
+ ICONTAINS: "icontains",
23
+ STARTSWITH: "startswith",
24
+ ISTARTSWITH: "istartswith",
25
+ ENDSWITH: "endswith",
26
+ IENDSWITH: "iendswith"
27
+ };
28
+ //#endregion
29
+ //#region src/filters/FilterSet.ts
30
+ const FILTER_LOOKUPS = Object.values(InternalFilterLookup);
31
+ function isFilterLookup(value) {
32
+ return FILTER_LOOKUPS.includes(value);
33
+ }
34
+ /**
35
+ * Declarative query-param to filter translation.
36
+ *
37
+ * A `FilterSet` lets viewsets expose safe, explicit filtering behavior
38
+ * without leaking raw ORM filter syntax to request handlers.
39
+ */
40
+ var FilterSet = class FilterSet {
41
+ spec;
42
+ allowAllParams;
43
+ static BRAND = "tango.resources.filter_set";
44
+ __tangoBrand = FilterSet.BRAND;
45
+ /**
46
+ * Resolve matching query parameters into ORM filter inputs.
47
+ */
48
+ constructor(spec, allowAllParams = false) {
49
+ this.spec = spec;
50
+ this.allowAllParams = allowAllParams;
51
+ }
52
+ /**
53
+ * Build a filter set from Django-style field declarations.
54
+ */
55
+ static define(config) {
56
+ return new FilterSet(FilterSet.normalizeDefineConfig(config), config.all === "__all__");
57
+ }
58
+ /**
59
+ * Narrow an unknown value to `FilterSet`.
60
+ */
61
+ static isFilterSet(value) {
62
+ return typeof value === "object" && value !== null && value.__tangoBrand === FilterSet.BRAND;
63
+ }
64
+ static normalizeDefineConfig(config) {
65
+ const spec = {};
66
+ const fieldDeclarations = config.fields ?? {};
67
+ const fieldParsers = config.parsers ?? {};
68
+ for (const rawField of Object.keys(fieldDeclarations)) {
69
+ const declaration = fieldDeclarations[rawField];
70
+ if (declaration === void 0) continue;
71
+ const parser = fieldParsers[rawField];
72
+ FilterSet.addFieldDeclaration(spec, rawField, declaration, parser);
73
+ }
74
+ const aliases = config.aliases ?? {};
75
+ for (const [param, declaration] of Object.entries(aliases)) spec[param] = FilterSet.normalizeAliasDeclaration(declaration);
76
+ return spec;
77
+ }
78
+ static addFieldDeclaration(spec, field, declaration, parser) {
79
+ if (declaration === true) {
80
+ spec[String(field)] = FilterSet.createLookupResolver(field, InternalFilterLookup.EXACT, parser);
81
+ return;
82
+ }
83
+ if (FilterSet.isLookupArray(declaration)) {
84
+ for (const lookup of declaration) {
85
+ const param = FilterSet.resolveLookupParam(String(field), lookup);
86
+ spec[param] = FilterSet.createLookupResolver(field, lookup, parser);
87
+ }
88
+ return;
89
+ }
90
+ const lookups = declaration.lookups ?? [InternalFilterLookup.EXACT];
91
+ const baseParam = declaration.param ?? String(field);
92
+ const effectiveParser = declaration.parse ?? parser;
93
+ for (const lookup of lookups) {
94
+ const param = FilterSet.resolveLookupParam(baseParam, lookup);
95
+ spec[param] = FilterSet.createLookupResolver(field, lookup, effectiveParser);
96
+ }
97
+ }
98
+ static isLookupArray(value) {
99
+ return Array.isArray(value);
100
+ }
101
+ static normalizeAliasDeclaration(declaration) {
102
+ if (FilterSet.isFilterResolverDeclaration(declaration)) return declaration;
103
+ if ("fields" in declaration) {
104
+ const lookup = declaration.lookup ?? InternalFilterLookup.ICONTAINS;
105
+ return FilterSet.createMultiFieldResolver(declaration.fields, lookup, declaration.parse);
106
+ }
107
+ return FilterSet.createLookupResolver(declaration.field, declaration.lookup ?? InternalFilterLookup.EXACT, declaration.parse);
108
+ }
109
+ static isFilterResolverDeclaration(value) {
110
+ if (typeof value !== "object" || value === null || !("type" in value)) return false;
111
+ return [
112
+ InternalFilterType.SCALAR,
113
+ InternalFilterType.ILIKE,
114
+ InternalFilterType.RANGE,
115
+ InternalFilterType.IN,
116
+ InternalFilterType.CUSTOM
117
+ ].includes(value.type);
118
+ }
119
+ static createMultiFieldResolver(fields, lookup, parser) {
120
+ if (lookup === InternalFilterLookup.ICONTAINS && parser === void 0) return {
121
+ type: InternalFilterType.ILIKE,
122
+ columns: [...fields]
123
+ };
124
+ return {
125
+ type: InternalFilterType.CUSTOM,
126
+ apply: (raw) => {
127
+ const parsed = FilterSet.resolveParserValue(raw, parser);
128
+ if (parsed === void 0) return void 0;
129
+ const composed = {};
130
+ for (const field of fields) {
131
+ const segment = FilterSet.resolveLookupFilter(field, lookup, parsed);
132
+ if (!segment) continue;
133
+ Object.assign(composed, segment);
134
+ }
135
+ return Object.keys(composed).length > 0 ? composed : void 0;
136
+ }
137
+ };
138
+ }
139
+ static createLookupResolver(field, lookup, parser) {
140
+ if (parser !== void 0) return {
141
+ type: InternalFilterType.CUSTOM,
142
+ apply: (raw) => {
143
+ const parsed = FilterSet.resolveParserValue(raw, parser);
144
+ if (parsed === void 0) return void 0;
145
+ return FilterSet.resolveLookupFilter(field, lookup, parsed);
146
+ }
147
+ };
148
+ switch (lookup) {
149
+ case "exact": return {
150
+ type: InternalFilterType.SCALAR,
151
+ column: field
152
+ };
153
+ case "in": return {
154
+ type: InternalFilterType.IN,
155
+ column: field
156
+ };
157
+ case "lt":
158
+ case "lte":
159
+ case "gt":
160
+ case "gte": return {
161
+ type: InternalFilterType.RANGE,
162
+ column: field,
163
+ op: lookup
164
+ };
165
+ case "icontains": return {
166
+ type: InternalFilterType.ILIKE,
167
+ columns: [field]
168
+ };
169
+ default: return {
170
+ type: InternalFilterType.CUSTOM,
171
+ apply: (raw) => FilterSet.resolveLookupFilter(field, lookup, raw)
172
+ };
173
+ }
174
+ }
175
+ static resolveLookupFilter(field, lookup, value) {
176
+ if (value === void 0) return void 0;
177
+ if (lookup === "exact") return { [field]: value };
178
+ if (lookup === "in") {
179
+ const arr = Array.isArray(value) ? value : String(value).split(",");
180
+ return { [`${String(field)}__in`]: arr };
181
+ }
182
+ if (lookup === "icontains") return { [`${String(field)}__icontains`]: FilterSet.toScalarString(value) };
183
+ return { [`${String(field)}__${lookup}`]: value };
184
+ }
185
+ static resolveLookupParam(baseParam, lookup) {
186
+ if (lookup === "exact") return baseParam;
187
+ return `${baseParam}__${lookup}`;
188
+ }
189
+ static resolveParserValue(value, parser) {
190
+ if (value === void 0) return;
191
+ if (parser === void 0) return value;
192
+ return parser(value);
193
+ }
194
+ static toScalarString(value) {
195
+ if (Array.isArray(value)) return value.join(",");
196
+ return String(value);
197
+ }
198
+ /**
199
+ * Return a new filter set with parser-aware scalar/range/in resolvers for matching fields.
200
+ */
201
+ withFieldParsers(parsers) {
202
+ if (Object.keys(parsers).length === 0) return this;
203
+ let changed = false;
204
+ const nextSpec = Object.fromEntries(Object.entries(this.spec).map(([param, resolver]) => {
205
+ const nextResolver = this.applyFieldParserOverride(resolver, parsers);
206
+ if (nextResolver !== resolver) changed = true;
207
+ return [param, nextResolver];
208
+ }));
209
+ return changed ? new FilterSet(nextSpec, this.allowAllParams) : this;
210
+ }
211
+ /**
212
+ * Apply all configured resolvers against query params.
213
+ */
214
+ apply(params) {
215
+ const filters = [];
216
+ const keys = /* @__PURE__ */ new Set();
217
+ for (const [key] of params.entries()) keys.add(key);
218
+ for (const key of keys) {
219
+ const resolver = this.spec[key] ?? (this.allowAllParams ? this.buildAllResolver(key) : void 0);
220
+ if (!resolver) continue;
221
+ const rawValue = params.getAll(key);
222
+ const value = rawValue.length > 1 ? rawValue : rawValue[0];
223
+ if (value === void 0) continue;
224
+ const filter = this.resolveFilter(resolver, value);
225
+ if (filter) filters.push(filter);
226
+ }
227
+ return filters;
228
+ }
229
+ buildAllResolver(param) {
230
+ const segments = param.split("__").filter(Boolean);
231
+ if (segments.length === 0) return;
232
+ const lastSegment = segments.at(-1);
233
+ const lookup = isFilterLookup(lastSegment) ? lastSegment : "exact";
234
+ const field = (lookup === "exact" ? segments : segments.slice(0, -1)).join("__");
235
+ if (!field) return;
236
+ if (lookup === "exact") return {
237
+ type: InternalFilterType.SCALAR,
238
+ column: field
239
+ };
240
+ return FilterSet.createLookupResolver(field, lookup);
241
+ }
242
+ resolveFilter(resolver, value) {
243
+ if (value === void 0) return void 0;
244
+ switch (resolver.type) {
245
+ case InternalFilterType.SCALAR: return { [resolver.column]: value };
246
+ case InternalFilterType.ILIKE: {
247
+ const pattern = FilterSet.toScalarString(value);
248
+ const filter = {};
249
+ resolver.columns.forEach((col) => {
250
+ filter[`${String(col)}__icontains`] = pattern;
251
+ });
252
+ return filter;
253
+ }
254
+ case InternalFilterType.RANGE: return { [`${String(resolver.column)}__${resolver.op}`]: value };
255
+ case InternalFilterType.IN: {
256
+ const arr = Array.isArray(value) ? value : String(value).split(",");
257
+ return { [`${String(resolver.column)}__in`]: arr };
258
+ }
259
+ case InternalFilterType.CUSTOM: return resolver.apply(value);
260
+ default: return;
261
+ }
262
+ }
263
+ applyFieldParserOverride(resolver, parsers) {
264
+ switch (resolver.type) {
265
+ case InternalFilterType.SCALAR: {
266
+ const parser = parsers[resolver.column];
267
+ return parser ? FilterSet.createLookupResolver(resolver.column, "exact", parser) : resolver;
268
+ }
269
+ case InternalFilterType.RANGE: {
270
+ const parser = parsers[resolver.column];
271
+ return parser ? FilterSet.createLookupResolver(resolver.column, resolver.op, parser) : resolver;
272
+ }
273
+ case InternalFilterType.IN: {
274
+ const parser = parsers[resolver.column];
275
+ return parser ? FilterSet.createLookupResolver(resolver.column, "in", parser) : resolver;
276
+ }
277
+ default: return resolver;
278
+ }
279
+ }
280
+ };
281
+ //#endregion
282
+ //#region src/filters/index.ts
283
+ var filters_exports = /* @__PURE__ */ __exportAll({ FilterSet: () => FilterSet });
284
+ //#endregion
285
+ export { FilterSet as n, filters_exports as t };
286
+
287
+ //# sourceMappingURL=filters-46d2Nr5C.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filters-46d2Nr5C.js","names":[],"sources":["../src/filters/internal/InternalFilterType.ts","../src/filters/internal/InternalFilterLookup.ts","../src/filters/FilterSet.ts","../src/filters/index.ts"],"sourcesContent":["export const InternalFilterType = {\n SCALAR: 'scalar',\n ILIKE: 'ilike',\n RANGE: 'range',\n IN: 'in',\n CUSTOM: 'custom',\n} as const;\n","export const InternalFilterLookup = {\n EXACT: 'exact',\n LT: 'lt',\n LTE: 'lte',\n GT: 'gt',\n GTE: 'gte',\n IN: 'in',\n ISNULL: 'isnull',\n CONTAINS: 'contains',\n ICONTAINS: 'icontains',\n STARTSWITH: 'startswith',\n ISTARTSWITH: 'istartswith',\n ENDSWITH: 'endswith',\n IENDSWITH: 'iendswith',\n} as const;\n","import { TangoQueryParams } from '@danceroutine/tango-core';\nimport type { FilterInput, FilterKey, FilterValue, LookupType } from '@danceroutine/tango-orm';\nimport { InternalFilterType } from './internal/InternalFilterType';\nimport { InternalFilterLookup } from './internal/InternalFilterLookup';\nimport type { RangeOperator } from './RangeOperator';\n\nconst FILTER_LOOKUPS = Object.values(InternalFilterLookup) as readonly LookupType[];\n\ntype FilterFieldRef<T extends Record<string, unknown>> = Extract<keyof T, string> | string;\n\nfunction isFilterLookup(value: string): value is LookupType {\n return (FILTER_LOOKUPS as readonly string[]).includes(value);\n}\n\n/**\n * Configuration for how a query parameter should be resolved into a filter.\n * Supports scalar equality, case-insensitive search, range comparisons, IN queries, and custom logic.\n */\nexport type FilterResolver<T extends Record<string, unknown>> =\n | { type: typeof InternalFilterType.SCALAR; column: FilterFieldRef<T> }\n | { type: typeof InternalFilterType.ILIKE; columns: FilterFieldRef<T>[] }\n | { type: typeof InternalFilterType.RANGE; column: FilterFieldRef<T>; op: RangeOperator }\n | { type: typeof InternalFilterType.IN; column: FilterFieldRef<T> }\n | {\n type: typeof InternalFilterType.CUSTOM;\n apply: (value: string | string[] | undefined) => FilterInput<T> | undefined;\n };\n\nexport type FilterLookup = LookupType;\n\nexport type FilterValueParser = (raw: string | string[]) => FilterValue | FilterValue[] | undefined;\n\nexport type FieldFilterDeclaration =\n | true\n | readonly FilterLookup[]\n | {\n lookups?: readonly FilterLookup[];\n param?: string;\n parse?: FilterValueParser;\n };\n\nexport type AliasFilterDeclaration<T extends Record<string, unknown>> =\n | FilterResolver<T>\n | {\n field: FilterFieldRef<T>;\n lookup?: FilterLookup;\n parse?: FilterValueParser;\n }\n | {\n fields: readonly FilterFieldRef<T>[];\n lookup?: FilterLookup;\n parse?: FilterValueParser;\n };\n\nexport interface FilterSetDefineConfig<T extends Record<string, unknown>> {\n fields?: Partial<Record<string, FieldFilterDeclaration>>;\n aliases?: Record<string, AliasFilterDeclaration<T>>;\n parsers?: Partial<Record<string, FilterValueParser>>;\n all?: '__all__';\n}\n\ntype ResolvedFilterValue = string | string[] | FilterValue | FilterValue[];\n\n/**\n * Declarative query-param to filter translation.\n *\n * A `FilterSet` lets viewsets expose safe, explicit filtering behavior\n * without leaking raw ORM filter syntax to request handlers.\n */\nexport class FilterSet<T extends Record<string, unknown>> {\n static readonly BRAND = 'tango.resources.filter_set' as const;\n readonly __tangoBrand: typeof FilterSet.BRAND = FilterSet.BRAND;\n\n /**\n * Resolve matching query parameters into ORM filter inputs.\n */\n constructor(\n private readonly spec: Record<string, FilterResolver<T>>,\n private readonly allowAllParams: boolean = false\n ) {}\n\n /**\n * Build a filter set from Django-style field declarations.\n */\n static define<T extends Record<string, unknown>>(config: FilterSetDefineConfig<T>): FilterSet<T> {\n const spec = FilterSet.normalizeDefineConfig(config);\n return new FilterSet(spec, config.all === '__all__');\n }\n\n /**\n * Narrow an unknown value to `FilterSet`.\n */\n static isFilterSet<T extends Record<string, unknown>>(value: unknown): value is FilterSet<T> {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === FilterSet.BRAND\n );\n }\n\n private static normalizeDefineConfig<T extends Record<string, unknown>>(\n config: FilterSetDefineConfig<T>\n ): Record<string, FilterResolver<T>> {\n const spec: Record<string, FilterResolver<T>> = {};\n const fieldDeclarations: Partial<Record<string, FieldFilterDeclaration>> = config.fields ?? {};\n const fieldParsers: Partial<Record<string, FilterValueParser>> = config.parsers ?? {};\n\n for (const rawField of Object.keys(fieldDeclarations) as Array<FilterFieldRef<T>>) {\n const declaration = fieldDeclarations[rawField];\n if (declaration === undefined) continue;\n const parser = fieldParsers[rawField];\n FilterSet.addFieldDeclaration(spec, rawField, declaration, parser);\n }\n\n const aliases = config.aliases ?? {};\n for (const [param, declaration] of Object.entries(aliases)) {\n spec[param] = FilterSet.normalizeAliasDeclaration(declaration);\n }\n\n return spec;\n }\n\n private static addFieldDeclaration<T extends Record<string, unknown>>(\n spec: Record<string, FilterResolver<T>>,\n field: FilterFieldRef<T>,\n declaration: FieldFilterDeclaration,\n parser: FilterValueParser | undefined\n ): void {\n if (declaration === true) {\n spec[String(field)] = FilterSet.createLookupResolver(field, InternalFilterLookup.EXACT, parser);\n return;\n }\n\n if (FilterSet.isLookupArray(declaration)) {\n for (const lookup of declaration) {\n const param = FilterSet.resolveLookupParam(String(field), lookup);\n spec[param] = FilterSet.createLookupResolver(field, lookup, parser);\n }\n return;\n }\n\n const lookups = declaration.lookups ?? [InternalFilterLookup.EXACT];\n const baseParam = declaration.param ?? String(field);\n const effectiveParser = declaration.parse ?? parser;\n\n for (const lookup of lookups) {\n const param = FilterSet.resolveLookupParam(baseParam, lookup);\n spec[param] = FilterSet.createLookupResolver(field, lookup, effectiveParser);\n }\n }\n\n private static isLookupArray(value: FieldFilterDeclaration): value is readonly FilterLookup[] {\n return Array.isArray(value);\n }\n\n private static normalizeAliasDeclaration<T extends Record<string, unknown>>(\n declaration: AliasFilterDeclaration<T>\n ): FilterResolver<T> {\n if (FilterSet.isFilterResolverDeclaration(declaration)) {\n return declaration;\n }\n\n if ('fields' in declaration) {\n const lookup = declaration.lookup ?? InternalFilterLookup.ICONTAINS;\n return FilterSet.createMultiFieldResolver(declaration.fields, lookup, declaration.parse);\n }\n\n return FilterSet.createLookupResolver(\n declaration.field,\n declaration.lookup ?? InternalFilterLookup.EXACT,\n declaration.parse\n );\n }\n\n private static isFilterResolverDeclaration<T extends Record<string, unknown>>(\n value: AliasFilterDeclaration<T>\n ): value is FilterResolver<T> {\n if (typeof value !== 'object' || value === null || !('type' in value)) {\n return false;\n }\n\n return [\n InternalFilterType.SCALAR,\n InternalFilterType.ILIKE,\n InternalFilterType.RANGE,\n InternalFilterType.IN,\n InternalFilterType.CUSTOM,\n ].includes(value.type);\n }\n\n private static createMultiFieldResolver<T extends Record<string, unknown>>(\n fields: readonly FilterFieldRef<T>[],\n lookup: FilterLookup,\n parser?: FilterValueParser\n ): FilterResolver<T> {\n if (lookup === InternalFilterLookup.ICONTAINS && parser === undefined) {\n return { type: InternalFilterType.ILIKE, columns: [...fields] };\n }\n\n return {\n type: InternalFilterType.CUSTOM,\n apply: (raw) => {\n const parsed = FilterSet.resolveParserValue(raw, parser);\n if (parsed === undefined) return undefined;\n\n const composed: Partial<Record<FilterKey<T>, FilterValue>> = {};\n for (const field of fields) {\n const segment = FilterSet.resolveLookupFilter(field, lookup, parsed);\n if (!segment) continue;\n Object.assign(composed, segment);\n }\n\n return Object.keys(composed).length > 0 ? (composed as FilterInput<T>) : undefined;\n },\n };\n }\n\n private static createLookupResolver<T extends Record<string, unknown>>(\n field: FilterFieldRef<T>,\n lookup: FilterLookup,\n parser?: FilterValueParser\n ): FilterResolver<T> {\n if (parser !== undefined) {\n return {\n type: InternalFilterType.CUSTOM,\n apply: (raw) => {\n const parsed = FilterSet.resolveParserValue(raw, parser);\n if (parsed === undefined) return undefined;\n return FilterSet.resolveLookupFilter(field, lookup, parsed);\n },\n };\n }\n\n switch (lookup) {\n case 'exact':\n return { type: InternalFilterType.SCALAR, column: field };\n case 'in':\n return { type: InternalFilterType.IN, column: field };\n case 'lt':\n case 'lte':\n case 'gt':\n case 'gte':\n return { type: InternalFilterType.RANGE, column: field, op: lookup };\n case 'icontains':\n return { type: InternalFilterType.ILIKE, columns: [field] };\n default:\n return {\n type: InternalFilterType.CUSTOM,\n apply: (raw) => FilterSet.resolveLookupFilter(field, lookup, raw),\n };\n }\n }\n\n private static resolveLookupFilter<T extends Record<string, unknown>>(\n field: FilterFieldRef<T>,\n lookup: FilterLookup,\n value: ResolvedFilterValue | undefined\n ): FilterInput<T> | undefined {\n if (value === undefined) return undefined;\n\n if (lookup === 'exact') {\n return { [field]: value } as FilterInput<T>;\n }\n\n if (lookup === 'in') {\n const arr = Array.isArray(value) ? value : String(value).split(',');\n const lookupKey = `${String(field)}__in` as FilterKey<T>;\n return { [lookupKey]: arr } as FilterInput<T>;\n }\n\n if (lookup === 'icontains') {\n const lookupKey = `${String(field)}__icontains` as FilterKey<T>;\n return { [lookupKey]: FilterSet.toScalarString(value) } as FilterInput<T>;\n }\n\n const lookupKey = `${String(field)}__${lookup}` as FilterKey<T>;\n return { [lookupKey]: value as FilterValue } as FilterInput<T>;\n }\n\n private static resolveLookupParam(baseParam: string, lookup: FilterLookup): string {\n if (lookup === 'exact') {\n return baseParam;\n }\n return `${baseParam}__${lookup}`;\n }\n\n private static resolveParserValue(\n value: string | string[] | undefined,\n parser?: FilterValueParser\n ): ResolvedFilterValue | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n if (parser === undefined) {\n return value;\n }\n\n return parser(value);\n }\n\n private static toScalarString(value: ResolvedFilterValue): string {\n if (Array.isArray(value)) {\n return value.join(',');\n }\n return String(value);\n }\n\n /**\n * Return a new filter set with parser-aware scalar/range/in resolvers for matching fields.\n */\n withFieldParsers(parsers: Partial<Record<string, FilterValueParser>>): FilterSet<T> {\n if (Object.keys(parsers).length === 0) {\n return this;\n }\n\n let changed = false;\n const nextSpec = Object.fromEntries(\n Object.entries(this.spec).map(([param, resolver]) => {\n const nextResolver = this.applyFieldParserOverride(resolver, parsers);\n if (nextResolver !== resolver) {\n changed = true;\n }\n return [param, nextResolver];\n })\n ) as Record<string, FilterResolver<T>>;\n\n return changed ? new FilterSet(nextSpec, this.allowAllParams) : this;\n }\n\n /**\n * Apply all configured resolvers against query params.\n */\n apply(params: TangoQueryParams): FilterInput<T>[] {\n const filters: FilterInput<T>[] = [];\n const keys = new Set<string>();\n\n for (const [key] of params.entries()) {\n keys.add(key);\n }\n\n for (const key of keys) {\n const resolver = this.spec[key] ?? (this.allowAllParams ? this.buildAllResolver(key) : undefined);\n if (!resolver) continue;\n\n const rawValue = params.getAll(key);\n const value = rawValue.length > 1 ? rawValue : rawValue[0];\n\n if (value === undefined) continue;\n\n const filter = this.resolveFilter(resolver, value);\n if (filter) {\n filters.push(filter);\n }\n }\n\n return filters;\n }\n\n private buildAllResolver(param: string): FilterResolver<T> | undefined {\n const segments = param.split('__').filter(Boolean);\n if (segments.length === 0) {\n return undefined;\n }\n\n const lastSegment = segments.at(-1)!;\n const lookup = isFilterLookup(lastSegment) ? lastSegment : 'exact';\n const field = (lookup === 'exact' ? segments : segments.slice(0, -1)).join('__') as FilterFieldRef<T>;\n\n if (!field) {\n return undefined;\n }\n\n if (lookup === 'exact') {\n return { type: InternalFilterType.SCALAR, column: field };\n }\n\n return FilterSet.createLookupResolver(field, lookup);\n }\n\n private resolveFilter(\n resolver: FilterResolver<T>,\n value: string | string[] | undefined\n ): FilterInput<T> | undefined {\n if (value === undefined) return undefined;\n\n switch (resolver.type) {\n case InternalFilterType.SCALAR:\n return { [resolver.column]: value } as FilterInput<T>;\n\n case InternalFilterType.ILIKE: {\n const pattern = FilterSet.toScalarString(value);\n const filter: Partial<Record<FilterKey<T>, FilterValue>> = {};\n resolver.columns.forEach((col) => {\n filter[`${String(col)}__icontains` as FilterKey<T>] = pattern;\n });\n return filter;\n }\n\n case InternalFilterType.RANGE: {\n const lookupKey = `${String(resolver.column)}__${resolver.op}` as keyof FilterInput<T>;\n return { [lookupKey]: value } as FilterInput<T>;\n }\n\n case InternalFilterType.IN: {\n const arr = Array.isArray(value) ? value : String(value).split(',');\n const lookupKey = `${String(resolver.column)}__in` as keyof FilterInput<T>;\n return { [lookupKey]: arr } as FilterInput<T>;\n }\n\n case InternalFilterType.CUSTOM:\n return resolver.apply(value);\n\n default:\n return undefined;\n }\n }\n\n private applyFieldParserOverride(\n resolver: FilterResolver<T>,\n parsers: Partial<Record<string, FilterValueParser>>\n ): FilterResolver<T> {\n switch (resolver.type) {\n case InternalFilterType.SCALAR: {\n const parser = parsers[resolver.column];\n return parser ? FilterSet.createLookupResolver(resolver.column, 'exact', parser) : resolver;\n }\n\n case InternalFilterType.RANGE: {\n const parser = parsers[resolver.column];\n return parser ? FilterSet.createLookupResolver(resolver.column, resolver.op, parser) : resolver;\n }\n\n case InternalFilterType.IN: {\n const parser = parsers[resolver.column];\n return parser ? FilterSet.createLookupResolver(resolver.column, 'in', parser) : resolver;\n }\n\n default:\n return resolver;\n }\n }\n}\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport type { FilterType } from './FilterType';\nexport type { RangeOperator } from './RangeOperator';\nexport type {\n AliasFilterDeclaration,\n FieldFilterDeclaration,\n FilterLookup,\n FilterResolver,\n FilterSetDefineConfig,\n FilterValueParser,\n} from './FilterSet';\nexport { FilterSet } from './FilterSet';\n"],"mappings":";;;AAAA,MAAa,qBAAqB;CAC9B,QAAQ;CACR,OAAO;CACP,OAAO;CACP,IAAI;CACJ,QAAQ;AACZ;;;ACNA,MAAa,uBAAuB;CAChC,OAAO;CACP,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,QAAQ;CACR,UAAU;CACV,WAAW;CACX,YAAY;CACZ,aAAa;CACb,UAAU;CACV,WAAW;AACf;;;ACRA,MAAM,iBAAiB,OAAO,OAAO,oBAAoB;AAIzD,SAAS,eAAe,OAAoC;CACxD,OAAQ,eAAqC,SAAS,KAAK;AAC/D;;;;;;;AAyDA,IAAa,YAAb,MAAa,UAA6C;CAQjC;CACA;CARrB,OAAgB,QAAQ;CACxB,eAAgD,UAAU;;;;CAK1D,YACI,MACA,iBAA2C,OAC7C;EAFmB,KAAA,OAAA;EACA,KAAA,iBAAA;CAClB;;;;CAKH,OAAO,OAA0C,QAAgD;EAE7F,OAAO,IAAI,UADE,UAAU,sBAAsB,MACrB,GAAG,OAAO,QAAQ,SAAS;CACvD;;;;CAKA,OAAO,YAA+C,OAAuC;EACzF,OACI,OAAO,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB,UAAU;CAEzE;CAEA,OAAe,sBACX,QACiC;EACjC,MAAM,OAA0C,CAAC;EACjD,MAAM,oBAAqE,OAAO,UAAU,CAAC;EAC7F,MAAM,eAA2D,OAAO,WAAW,CAAC;EAEpF,KAAK,MAAM,YAAY,OAAO,KAAK,iBAAiB,GAA+B;GAC/E,MAAM,cAAc,kBAAkB;GACtC,IAAI,gBAAgB,KAAA,GAAW;GAC/B,MAAM,SAAS,aAAa;GAC5B,UAAU,oBAAoB,MAAM,UAAU,aAAa,MAAM;EACrE;EAEA,MAAM,UAAU,OAAO,WAAW,CAAC;EACnC,KAAK,MAAM,CAAC,OAAO,gBAAgB,OAAO,QAAQ,OAAO,GACrD,KAAK,SAAS,UAAU,0BAA0B,WAAW;EAGjE,OAAO;CACX;CAEA,OAAe,oBACX,MACA,OACA,aACA,QACI;EACJ,IAAI,gBAAgB,MAAM;GACtB,KAAK,OAAO,KAAK,KAAK,UAAU,qBAAqB,OAAO,qBAAqB,OAAO,MAAM;GAC9F;EACJ;EAEA,IAAI,UAAU,cAAc,WAAW,GAAG;GACtC,KAAK,MAAM,UAAU,aAAa;IAC9B,MAAM,QAAQ,UAAU,mBAAmB,OAAO,KAAK,GAAG,MAAM;IAChE,KAAK,SAAS,UAAU,qBAAqB,OAAO,QAAQ,MAAM;GACtE;GACA;EACJ;EAEA,MAAM,UAAU,YAAY,WAAW,CAAC,qBAAqB,KAAK;EAClE,MAAM,YAAY,YAAY,SAAS,OAAO,KAAK;EACnD,MAAM,kBAAkB,YAAY,SAAS;EAE7C,KAAK,MAAM,UAAU,SAAS;GAC1B,MAAM,QAAQ,UAAU,mBAAmB,WAAW,MAAM;GAC5D,KAAK,SAAS,UAAU,qBAAqB,OAAO,QAAQ,eAAe;EAC/E;CACJ;CAEA,OAAe,cAAc,OAAiE;EAC1F,OAAO,MAAM,QAAQ,KAAK;CAC9B;CAEA,OAAe,0BACX,aACiB;EACjB,IAAI,UAAU,4BAA4B,WAAW,GACjD,OAAO;EAGX,IAAI,YAAY,aAAa;GACzB,MAAM,SAAS,YAAY,UAAU,qBAAqB;GAC1D,OAAO,UAAU,yBAAyB,YAAY,QAAQ,QAAQ,YAAY,KAAK;EAC3F;EAEA,OAAO,UAAU,qBACb,YAAY,OACZ,YAAY,UAAU,qBAAqB,OAC3C,YAAY,KAChB;CACJ;CAEA,OAAe,4BACX,OAC0B;EAC1B,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,EAAE,UAAU,QAC3D,OAAO;EAGX,OAAO;GACH,mBAAmB;GACnB,mBAAmB;GACnB,mBAAmB;GACnB,mBAAmB;GACnB,mBAAmB;EACvB,EAAE,SAAS,MAAM,IAAI;CACzB;CAEA,OAAe,yBACX,QACA,QACA,QACiB;EACjB,IAAI,WAAW,qBAAqB,aAAa,WAAW,KAAA,GACxD,OAAO;GAAE,MAAM,mBAAmB;GAAO,SAAS,CAAC,GAAG,MAAM;EAAE;EAGlE,OAAO;GACH,MAAM,mBAAmB;GACzB,QAAQ,QAAQ;IACZ,MAAM,SAAS,UAAU,mBAAmB,KAAK,MAAM;IACvD,IAAI,WAAW,KAAA,GAAW,OAAO,KAAA;IAEjC,MAAM,WAAuD,CAAC;IAC9D,KAAK,MAAM,SAAS,QAAQ;KACxB,MAAM,UAAU,UAAU,oBAAoB,OAAO,QAAQ,MAAM;KACnE,IAAI,CAAC,SAAS;KACd,OAAO,OAAO,UAAU,OAAO;IACnC;IAEA,OAAO,OAAO,KAAK,QAAQ,EAAE,SAAS,IAAK,WAA8B,KAAA;GAC7E;EACJ;CACJ;CAEA,OAAe,qBACX,OACA,QACA,QACiB;EACjB,IAAI,WAAW,KAAA,GACX,OAAO;GACH,MAAM,mBAAmB;GACzB,QAAQ,QAAQ;IACZ,MAAM,SAAS,UAAU,mBAAmB,KAAK,MAAM;IACvD,IAAI,WAAW,KAAA,GAAW,OAAO,KAAA;IACjC,OAAO,UAAU,oBAAoB,OAAO,QAAQ,MAAM;GAC9D;EACJ;EAGJ,QAAQ,QAAR;GACI,KAAK,SACD,OAAO;IAAE,MAAM,mBAAmB;IAAQ,QAAQ;GAAM;GAC5D,KAAK,MACD,OAAO;IAAE,MAAM,mBAAmB;IAAI,QAAQ;GAAM;GACxD,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK,OACD,OAAO;IAAE,MAAM,mBAAmB;IAAO,QAAQ;IAAO,IAAI;GAAO;GACvE,KAAK,aACD,OAAO;IAAE,MAAM,mBAAmB;IAAO,SAAS,CAAC,KAAK;GAAE;GAC9D,SACI,OAAO;IACH,MAAM,mBAAmB;IACzB,QAAQ,QAAQ,UAAU,oBAAoB,OAAO,QAAQ,GAAG;GACpE;EACR;CACJ;CAEA,OAAe,oBACX,OACA,QACA,OAC0B;EAC1B,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;EAEhC,IAAI,WAAW,SACX,OAAO,GAAG,QAAQ,MAAM;EAG5B,IAAI,WAAW,MAAM;GACjB,MAAM,MAAM,MAAM,QAAQ,KAAK,IAAI,QAAQ,OAAO,KAAK,EAAE,MAAM,GAAG;GAElE,OAAO,GAAG,GADW,OAAO,KAAK,EAAE,QACb,IAAI;EAC9B;EAEA,IAAI,WAAW,aAEX,OAAO,GAAG,GADW,OAAO,KAAK,EAAE,eACb,UAAU,eAAe,KAAK,EAAE;EAI1D,OAAO,GAAG,GADW,OAAO,KAAK,EAAE,IAAI,WACjB,MAAqB;CAC/C;CAEA,OAAe,mBAAmB,WAAmB,QAA8B;EAC/E,IAAI,WAAW,SACX,OAAO;EAEX,OAAO,GAAG,UAAU,IAAI;CAC5B;CAEA,OAAe,mBACX,OACA,QAC+B;EAC/B,IAAI,UAAU,KAAA,GACV;EAGJ,IAAI,WAAW,KAAA,GACX,OAAO;EAGX,OAAO,OAAO,KAAK;CACvB;CAEA,OAAe,eAAe,OAAoC;EAC9D,IAAI,MAAM,QAAQ,KAAK,GACnB,OAAO,MAAM,KAAK,GAAG;EAEzB,OAAO,OAAO,KAAK;CACvB;;;;CAKA,iBAAiB,SAAmE;EAChF,IAAI,OAAO,KAAK,OAAO,EAAE,WAAW,GAChC,OAAO;EAGX,IAAI,UAAU;EACd,MAAM,WAAW,OAAO,YACpB,OAAO,QAAQ,KAAK,IAAI,EAAE,KAAK,CAAC,OAAO,cAAc;GACjD,MAAM,eAAe,KAAK,yBAAyB,UAAU,OAAO;GACpE,IAAI,iBAAiB,UACjB,UAAU;GAEd,OAAO,CAAC,OAAO,YAAY;EAC/B,CAAC,CACL;EAEA,OAAO,UAAU,IAAI,UAAU,UAAU,KAAK,cAAc,IAAI;CACpE;;;;CAKA,MAAM,QAA4C;EAC9C,MAAM,UAA4B,CAAC;EACnC,MAAM,uBAAO,IAAI,IAAY;EAE7B,KAAK,MAAM,CAAC,QAAQ,OAAO,QAAQ,GAC/B,KAAK,IAAI,GAAG;EAGhB,KAAK,MAAM,OAAO,MAAM;GACpB,MAAM,WAAW,KAAK,KAAK,SAAS,KAAK,iBAAiB,KAAK,iBAAiB,GAAG,IAAI,KAAA;GACvF,IAAI,CAAC,UAAU;GAEf,MAAM,WAAW,OAAO,OAAO,GAAG;GAClC,MAAM,QAAQ,SAAS,SAAS,IAAI,WAAW,SAAS;GAExD,IAAI,UAAU,KAAA,GAAW;GAEzB,MAAM,SAAS,KAAK,cAAc,UAAU,KAAK;GACjD,IAAI,QACA,QAAQ,KAAK,MAAM;EAE3B;EAEA,OAAO;CACX;CAEA,iBAAyB,OAA8C;EACnE,MAAM,WAAW,MAAM,MAAM,IAAI,EAAE,OAAO,OAAO;EACjD,IAAI,SAAS,WAAW,GACpB;EAGJ,MAAM,cAAc,SAAS,GAAG,EAAE;EAClC,MAAM,SAAS,eAAe,WAAW,IAAI,cAAc;EAC3D,MAAM,SAAS,WAAW,UAAU,WAAW,SAAS,MAAM,GAAG,EAAE,GAAG,KAAK,IAAI;EAE/E,IAAI,CAAC,OACD;EAGJ,IAAI,WAAW,SACX,OAAO;GAAE,MAAM,mBAAmB;GAAQ,QAAQ;EAAM;EAG5D,OAAO,UAAU,qBAAqB,OAAO,MAAM;CACvD;CAEA,cACI,UACA,OAC0B;EAC1B,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;EAEhC,QAAQ,SAAS,MAAjB;GACI,KAAK,mBAAmB,QACpB,OAAO,GAAG,SAAS,SAAS,MAAM;GAEtC,KAAK,mBAAmB,OAAO;IAC3B,MAAM,UAAU,UAAU,eAAe,KAAK;IAC9C,MAAM,SAAqD,CAAC;IAC5D,SAAS,QAAQ,SAAS,QAAQ;KAC9B,OAAO,GAAG,OAAO,GAAG,EAAE,gBAAgC;IAC1D,CAAC;IACD,OAAO;GACX;GAEA,KAAK,mBAAmB,OAEpB,OAAO,GAAG,GADW,OAAO,SAAS,MAAM,EAAE,IAAI,SAAS,OACpC,MAAM;GAGhC,KAAK,mBAAmB,IAAI;IACxB,MAAM,MAAM,MAAM,QAAQ,KAAK,IAAI,QAAQ,OAAO,KAAK,EAAE,MAAM,GAAG;IAElE,OAAO,GAAG,GADW,OAAO,SAAS,MAAM,EAAE,QACvB,IAAI;GAC9B;GAEA,KAAK,mBAAmB,QACpB,OAAO,SAAS,MAAM,KAAK;GAE/B,SACI;EACR;CACJ;CAEA,yBACI,UACA,SACiB;EACjB,QAAQ,SAAS,MAAjB;GACI,KAAK,mBAAmB,QAAQ;IAC5B,MAAM,SAAS,QAAQ,SAAS;IAChC,OAAO,SAAS,UAAU,qBAAqB,SAAS,QAAQ,SAAS,MAAM,IAAI;GACvF;GAEA,KAAK,mBAAmB,OAAO;IAC3B,MAAM,SAAS,QAAQ,SAAS;IAChC,OAAO,SAAS,UAAU,qBAAqB,SAAS,QAAQ,SAAS,IAAI,MAAM,IAAI;GAC3F;GAEA,KAAK,mBAAmB,IAAI;IACxB,MAAM,SAAS,QAAQ,SAAS;IAChC,OAAO,SAAS,UAAU,qBAAqB,SAAS,QAAQ,MAAM,MAAM,IAAI;GACpF;GAEA,SACI,OAAO;EACf;CACJ;AACJ"}
@@ -0,0 +1,24 @@
1
+ import { a as BasePaginatedResponse, c as PaginatedResponse, i as Paginator, l as BasePaginator, n as OffsetPaginator, o as CursorPaginatedResponse, r as Page, s as OffsetPaginatedResponse, t as CursorPaginator } from "./CursorPaginator-CfeMQCdJ.js";
2
+ import { z } from "zod";
3
+
4
+ //#region src/pagination/OffsetPaginationInput.d.ts
5
+ type OffsetPaginationInputValue = {
6
+ limit: number;
7
+ offset: number;
8
+ page?: number;
9
+ };
10
+ declare const OffsetPaginationInput: z.ZodType<OffsetPaginationInputValue>;
11
+ //#endregion
12
+ //#region src/pagination/CursorPaginationInput.d.ts
13
+ type CursorPaginationInputValue = {
14
+ limit?: number;
15
+ cursor: string | null;
16
+ ordering?: string;
17
+ };
18
+ declare const CursorPaginationInput: z.ZodType<CursorPaginationInputValue>;
19
+ declare namespace index_d_exports {
20
+ export { BasePaginatedResponse, BasePaginator, CursorPaginatedResponse, CursorPaginationInput, CursorPaginationInputValue, CursorPaginator, OffsetPaginatedResponse, OffsetPaginationInput, OffsetPaginationInputValue, OffsetPaginator, Page, PaginatedResponse, Paginator };
21
+ }
22
+ //#endregion
23
+ export { OffsetPaginationInputValue as a, OffsetPaginationInput as i, CursorPaginationInput as n, CursorPaginationInputValue as r, index_d_exports as t };
24
+ //# sourceMappingURL=index-Ac94YL5S.d.ts.map
@@ -0,0 +1,54 @@
1
+ import { TangoRequest } from "@danceroutine/tango-core";
2
+
3
+ //#region src/context/RequestContext.d.ts
4
+ /**
5
+ * Default user shape for RequestContext.
6
+ * Consumers can provide their own user type via the TUser generic parameter.
7
+ */
8
+ interface BaseUser {
9
+ id: string | number;
10
+ roles?: string[];
11
+ }
12
+ /**
13
+ * Normalized request context passed through the framework adapter into viewset methods.
14
+ * Generic over the user type so consumers can plug in their own auth infrastructure.
15
+ */
16
+ declare class RequestContext<TUser = BaseUser> {
17
+ readonly request: TangoRequest;
18
+ user: TUser | null;
19
+ params: Record<string, string>;
20
+ static readonly BRAND: "tango.resources.request_context";
21
+ readonly __tangoBrand: typeof RequestContext.BRAND;
22
+ private state;
23
+ constructor(request: TangoRequest, user?: TUser | null, params?: Record<string, string>);
24
+ /**
25
+ * Narrow an unknown value to `RequestContext`.
26
+ */
27
+ static isRequestContext<TUser = BaseUser>(value: unknown): value is RequestContext<TUser>;
28
+ /**
29
+ * Construct a context with optional user payload.
30
+ */
31
+ static create<TUser = BaseUser>(request: Request, user?: TUser | null): RequestContext<TUser>;
32
+ /**
33
+ * Store arbitrary per-request state for downstream middleware/handlers.
34
+ */
35
+ setState<T>(key: string | symbol, value: T): void;
36
+ /**
37
+ * Retrieve previously stored request state.
38
+ */
39
+ getState<T>(key: string | symbol): T | undefined;
40
+ /**
41
+ * Check whether a state key has been set.
42
+ */
43
+ hasState(key: string | symbol): boolean;
44
+ /**
45
+ * Clone the context, including route params and request-local state.
46
+ */
47
+ clone(): RequestContext<TUser>;
48
+ }
49
+ declare namespace index_d_exports {
50
+ export { BaseUser, RequestContext };
51
+ }
52
+ //#endregion
53
+ export { BaseUser as n, RequestContext as r, index_d_exports as t };
54
+ //# sourceMappingURL=index-BJJalUDB.d.ts.map