@dynamicforms/fastapi-viewsets 0.3.6 → 0.4.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 +42 -3
- package/dist/fastapi-viewsets.js +313 -73
- package/dist/fastapi-viewsets.js.map +1 -1
- package/dist/fastapi-viewsets.umd.cjs +2 -2
- package/dist/fastapi-viewsets.umd.cjs.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/mixins.d.ts +161 -35
- package/dist/mixins.d.ts.map +1 -1
- package/dist/muxws-proxy.d.ts +56 -0
- package/dist/muxws-proxy.d.ts.map +1 -0
- package/dist/proxy-base.d.ts +145 -0
- package/dist/proxy-base.d.ts.map +1 -0
- package/dist/rest-proxy.d.ts +12 -24
- package/dist/rest-proxy.d.ts.map +1 -1
- package/dist/viewset.d.ts +44 -0
- package/dist/viewset.d.ts.map +1 -0
- package/package.json +12 -4
package/dist/mixins.d.ts
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* FE counterpart of BE mixins.py —
|
|
2
|
+
* FE counterpart of BE mixins.py — the mixins a ViewSet declaration is composed of.
|
|
3
3
|
*
|
|
4
|
-
* Each mixin class
|
|
5
|
-
*
|
|
4
|
+
* Each mixin is an interface merged into a class of the same name. The interface names the actions
|
|
5
|
+
* and their signatures; the class carries the `actions` list that the schema check reads at
|
|
6
|
+
* runtime. Both halves are needed because neither alone can do the job: a TypeScript `implements`
|
|
7
|
+
* clause is erased before anything runs, and a runtime list of strings says nothing about types.
|
|
6
8
|
*
|
|
7
|
-
* class ItemViewSet extends
|
|
9
|
+
* class ItemViewSet extends restViewSet<Item>()('id', [ReadOnlyViewSetMixin, LookupMixin]) {}
|
|
8
10
|
*
|
|
9
|
-
* The
|
|
11
|
+
* The list is written once, as values. `restViewSet` reads the action names off the mixins'
|
|
12
|
+
* instance types to build the ViewSet's public surface, and hands the same list to the proxy so
|
|
13
|
+
* that the schema check can compare it against the BE.
|
|
14
|
+
*
|
|
15
|
+
* The members are methods rather than properties, and are reached through an intersection rather
|
|
16
|
+
* than a `Pick<>` of a lookup table: a mapped type re-emits a method as a function-valued property,
|
|
17
|
+
* and a subclass may then not override an action with a method (TS2425). Overriding one to add
|
|
18
|
+
* caching or reshape parameters works on a hand-written proxy subclass today, and must keep
|
|
19
|
+
* working here.
|
|
20
|
+
*
|
|
21
|
+
* A composite mixin restates nothing: its interface extends the leaves its `actions` spread names,
|
|
22
|
+
* so each action's signature exists in exactly one place.
|
|
23
|
+
*
|
|
24
|
+
* The methods have no implementation anywhere in this file. The implementation is one HTTP call in
|
|
25
|
+
* ViewSetProxyBase, and a mixin carrying its own would be a second copy of it.
|
|
10
26
|
*/
|
|
11
27
|
export interface LookupItem {
|
|
12
28
|
group: unknown;
|
|
@@ -16,58 +32,168 @@ export interface LookupItem {
|
|
|
16
32
|
}
|
|
17
33
|
export type KeyType = string | number;
|
|
18
34
|
export type DestroyReturnData = Record<KeyType, any>;
|
|
35
|
+
export interface CreateMixin<T, PK extends keyof T> {
|
|
36
|
+
create(data: Omit<T, PK>): Promise<T>;
|
|
37
|
+
}
|
|
19
38
|
export declare class CreateMixin<T, PK extends keyof T> {
|
|
20
|
-
|
|
39
|
+
static readonly actions: readonly string[];
|
|
40
|
+
}
|
|
41
|
+
export interface BulkOnlyCreateMixin<T, PK extends keyof T> {
|
|
42
|
+
bulkCreate(data: Omit<T, PK>[]): Promise<T[]>;
|
|
21
43
|
}
|
|
22
44
|
export declare class BulkOnlyCreateMixin<T, PK extends keyof T> {
|
|
23
|
-
|
|
45
|
+
static readonly actions: readonly string[];
|
|
24
46
|
}
|
|
25
|
-
export
|
|
26
|
-
|
|
47
|
+
export interface BulkCreateMixin<T, PK extends keyof T> extends CreateMixin<T, PK>, BulkOnlyCreateMixin<T, PK> {
|
|
48
|
+
}
|
|
49
|
+
export declare class BulkCreateMixin<T, PK extends keyof T> extends CreateMixin<T, PK> {
|
|
50
|
+
static readonly actions: readonly string[];
|
|
51
|
+
}
|
|
52
|
+
export interface ListMixin<T> {
|
|
53
|
+
list(params?: ListParams): Promise<T[]>;
|
|
27
54
|
}
|
|
28
55
|
export declare class ListMixin<T> {
|
|
29
|
-
|
|
56
|
+
static readonly actions: readonly string[];
|
|
57
|
+
}
|
|
58
|
+
/** Query parameters a list call accepts. `sort` is 'column:asc,other:desc'; the rest are filters. */
|
|
59
|
+
export interface ListParams {
|
|
60
|
+
sort?: string;
|
|
61
|
+
[key: string]: string | number | boolean | null | undefined | Array<string | number>;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* One page, mirroring the BE PaginatedList.
|
|
65
|
+
*
|
|
66
|
+
* `count` is null when the backend could not know it without draining a lazy source. `hasMore` and
|
|
67
|
+
* `hasPrevious` are stated rather than inferred — a client that guesses from a null gets the guess
|
|
68
|
+
* wrong exactly at the boundary where it matters.
|
|
69
|
+
*/
|
|
70
|
+
export interface PaginatedList<T> {
|
|
71
|
+
results: T[];
|
|
72
|
+
offset: number;
|
|
73
|
+
limit: number | null;
|
|
74
|
+
count: number | null;
|
|
75
|
+
hasMore: boolean;
|
|
76
|
+
hasPrevious: boolean;
|
|
77
|
+
}
|
|
78
|
+
export interface PageParams extends ListParams {
|
|
79
|
+
offset?: number;
|
|
80
|
+
limit?: number;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* One cursor page.
|
|
84
|
+
*
|
|
85
|
+
* `next`/`previous` are exclusive, so following them never repeats a row. `first`/`last` are the
|
|
86
|
+
* same two edges read inclusively: they return their own row again — one duplicate to drop — and
|
|
87
|
+
* in exchange they survive rows being inserted at that edge, which is what polling a live list
|
|
88
|
+
* needs. They are present whenever the page is non-empty, even when `next` is null.
|
|
89
|
+
*
|
|
90
|
+
* There is no total count: producing one costs a second full pass per request and is stale by the
|
|
91
|
+
* time it is read.
|
|
92
|
+
*/
|
|
93
|
+
export interface CursorPage<T> {
|
|
94
|
+
results: T[];
|
|
95
|
+
limit: number;
|
|
96
|
+
hasMore: boolean;
|
|
97
|
+
hasPrevious: boolean;
|
|
98
|
+
next: string | null;
|
|
99
|
+
previous: string | null;
|
|
100
|
+
first: string | null;
|
|
101
|
+
last: string | null;
|
|
102
|
+
}
|
|
103
|
+
export interface CursorParams extends ListParams {
|
|
104
|
+
cursor?: string;
|
|
105
|
+
limit?: number;
|
|
106
|
+
}
|
|
107
|
+
/** FE counterpart of the BE CursorListMixin. See PaginatedListMixin on declaring several shapes. */
|
|
108
|
+
export interface CursorListMixin<T> {
|
|
109
|
+
listCursor(params?: CursorParams): Promise<CursorPage<T>>;
|
|
110
|
+
}
|
|
111
|
+
export declare class CursorListMixin<T> {
|
|
112
|
+
static readonly actions: readonly string[];
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* FE counterpart of the BE PaginatedListMixin. `GET {basePath}` is one endpoint answering in the
|
|
116
|
+
* shape the BE viewset declared as its default; this client sends no X-List-Shape header, so a
|
|
117
|
+
* ViewSet declares the mixin matching that default rather than one per shape it might want.
|
|
118
|
+
*/
|
|
119
|
+
export interface PaginatedListMixin<T> {
|
|
120
|
+
listPage(params?: PageParams): Promise<PaginatedList<T>>;
|
|
121
|
+
}
|
|
122
|
+
export declare class PaginatedListMixin<T> {
|
|
123
|
+
static readonly actions: readonly string[];
|
|
124
|
+
}
|
|
125
|
+
export interface RetrieveMixin<K extends KeyType, T> {
|
|
126
|
+
retrieve(pk: K): Promise<T>;
|
|
30
127
|
}
|
|
31
128
|
export declare class RetrieveMixin<K extends KeyType, T> {
|
|
32
|
-
|
|
129
|
+
static readonly actions: readonly string[];
|
|
130
|
+
}
|
|
131
|
+
export interface UpdateMixin<K extends KeyType, T> {
|
|
132
|
+
update(pk: K, data: T): Promise<T>;
|
|
133
|
+
partialUpdate(pk: K, data: Partial<T>): Promise<T>;
|
|
33
134
|
}
|
|
34
135
|
export declare class UpdateMixin<K extends KeyType, T> {
|
|
35
|
-
|
|
36
|
-
|
|
136
|
+
static readonly actions: readonly string[];
|
|
137
|
+
}
|
|
138
|
+
export interface BulkOnlyUpdateMixin<K extends KeyType, T> {
|
|
139
|
+
bulkUpdate(records: Record<K, T>): Promise<T[]>;
|
|
140
|
+
bulkPartialUpdate(records: Record<K, Partial<T>>): Promise<T[]>;
|
|
37
141
|
}
|
|
38
142
|
export declare class BulkOnlyUpdateMixin<K extends KeyType, T> {
|
|
39
|
-
|
|
40
|
-
|
|
143
|
+
static readonly actions: readonly string[];
|
|
144
|
+
}
|
|
145
|
+
export interface BulkUpdateMixin<K extends KeyType, T> extends UpdateMixin<K, T>, BulkOnlyUpdateMixin<K, T> {
|
|
41
146
|
}
|
|
42
|
-
export declare class BulkUpdateMixin<K extends KeyType, T> extends UpdateMixin<K, T>
|
|
43
|
-
|
|
44
|
-
|
|
147
|
+
export declare class BulkUpdateMixin<K extends KeyType, T> extends UpdateMixin<K, T> {
|
|
148
|
+
static readonly actions: readonly string[];
|
|
149
|
+
}
|
|
150
|
+
export interface DestroyMixin<K extends KeyType> {
|
|
151
|
+
destroy(pk: K): Promise<DestroyReturnData>;
|
|
45
152
|
}
|
|
46
153
|
export declare class DestroyMixin<K extends KeyType> {
|
|
47
|
-
|
|
154
|
+
static readonly actions: readonly string[];
|
|
155
|
+
}
|
|
156
|
+
export interface BulkOnlyDestroyMixin<K extends KeyType> {
|
|
157
|
+
bulkDestroy(pks: K[]): Promise<DestroyReturnData[]>;
|
|
48
158
|
}
|
|
49
159
|
export declare class BulkOnlyDestroyMixin<K extends KeyType> {
|
|
50
|
-
|
|
160
|
+
static readonly actions: readonly string[];
|
|
51
161
|
}
|
|
52
|
-
export
|
|
53
|
-
|
|
162
|
+
export interface BulkDestroyMixin<K extends KeyType> extends DestroyMixin<K>, BulkOnlyDestroyMixin<K> {
|
|
163
|
+
}
|
|
164
|
+
export declare class BulkDestroyMixin<K extends KeyType> extends DestroyMixin<K> {
|
|
165
|
+
static readonly actions: readonly string[];
|
|
166
|
+
}
|
|
167
|
+
export interface LookupMixin {
|
|
168
|
+
lookup(): Promise<LookupItem[]>;
|
|
54
169
|
}
|
|
55
170
|
export declare class LookupMixin {
|
|
56
|
-
|
|
171
|
+
static readonly actions: readonly string[];
|
|
172
|
+
}
|
|
173
|
+
export interface ReadOnlyViewSetMixin<K extends KeyType, T> extends ListMixin<T>, RetrieveMixin<K, T> {
|
|
174
|
+
}
|
|
175
|
+
export declare class ReadOnlyViewSetMixin<K extends KeyType, T> extends ListMixin<T> {
|
|
176
|
+
static readonly actions: readonly string[];
|
|
57
177
|
}
|
|
58
|
-
export
|
|
59
|
-
retrieve: (pk: K) => Promise<T>;
|
|
178
|
+
export interface ViewSetMixin<K extends KeyType, T, PK extends keyof T> extends ReadOnlyViewSetMixin<K, T>, CreateMixin<T, PK>, UpdateMixin<K, T>, DestroyMixin<K> {
|
|
60
179
|
}
|
|
61
|
-
export declare class ViewSetMixin<K extends KeyType, T, PK extends keyof T> extends ReadOnlyViewSetMixin<K, T>
|
|
62
|
-
|
|
63
|
-
update: (pk: K, data: T) => Promise<T>;
|
|
64
|
-
partialUpdate: (pk: K, data: Partial<T>) => Promise<T>;
|
|
65
|
-
destroy: (pk: K) => Promise<Record<string, unknown>>;
|
|
180
|
+
export declare class ViewSetMixin<K extends KeyType, T, PK extends keyof T> extends ReadOnlyViewSetMixin<K, T> {
|
|
181
|
+
static readonly actions: readonly string[];
|
|
66
182
|
}
|
|
67
|
-
export
|
|
68
|
-
bulkCreate: (data: Omit<T, PK>[]) => Promise<T[]>;
|
|
69
|
-
bulkUpdate: (records: Record<K, T>) => Promise<T[]>;
|
|
70
|
-
bulkPartialUpdate: (records: Record<K, Partial<T>>) => Promise<T[]>;
|
|
71
|
-
bulkDestroy: (pks: K[]) => Promise<Record<string, unknown>[]>;
|
|
183
|
+
export interface BulkViewSetMixin<K extends KeyType, T, PK extends keyof T> extends ViewSetMixin<K, T, PK>, BulkOnlyCreateMixin<T, PK>, BulkOnlyUpdateMixin<K, T>, BulkOnlyDestroyMixin<K> {
|
|
72
184
|
}
|
|
185
|
+
export declare class BulkViewSetMixin<K extends KeyType, T, PK extends keyof T> extends ViewSetMixin<K, T, PK> {
|
|
186
|
+
static readonly actions: readonly string[];
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* The actions named by `A`, each with the signature the mixin that contributes it declares. One
|
|
190
|
+
* conditional per single-action mixin; the composites are absent on purpose, so that any action's
|
|
191
|
+
* signature is written in exactly one place.
|
|
192
|
+
*
|
|
193
|
+
* An intersection rather than `Pick<>` of a table: a mapped type turns a method into a property,
|
|
194
|
+
* and a subclass cannot then override an action with a method (TS2425).
|
|
195
|
+
*/
|
|
196
|
+
export type ActionSurface<K extends KeyType, T, PK extends keyof T, A> = ('create' extends A ? CreateMixin<T, PK> : unknown) & ('bulkCreate' extends A ? BulkOnlyCreateMixin<T, PK> : unknown) & ('list' extends A ? ListMixin<T> : unknown) & ('listPage' extends A ? PaginatedListMixin<T> : unknown) & ('listCursor' extends A ? CursorListMixin<T> : unknown) & ('retrieve' extends A ? RetrieveMixin<K, T> : unknown) & ('update' extends A ? UpdateMixin<K, T> : unknown) & ('bulkUpdate' extends A ? BulkOnlyUpdateMixin<K, T> : unknown) & ('destroy' extends A ? DestroyMixin<K> : unknown) & ('bulkDestroy' extends A ? BulkOnlyDestroyMixin<K> : unknown) & ('lookup' extends A ? LookupMixin : unknown);
|
|
197
|
+
/** Every action name there is: `A = string` selects all of them. */
|
|
198
|
+
export type ActionName = keyof ActionSurface<KeyType, unknown, never, string>;
|
|
73
199
|
//# sourceMappingURL=mixins.d.ts.map
|
package/dist/mixins.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mixins.d.ts","sourceRoot":"","sources":["../vue/mixins.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"mixins.d.ts","sourceRoot":"","sources":["../vue/mixins.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { KeyType } from './mixins';
|
|
2
|
+
import { HttpMethod, ProxyBaseOptions, RequestOptions, ViewSetProxyBase } from './proxy-base';
|
|
3
|
+
/**
|
|
4
|
+
* The bits of a muxws Peer this proxy uses. Typed structurally rather than by importing the muxws
|
|
5
|
+
* types, so that `muxws` stays an optional dependency: an application that only uses route_rest
|
|
6
|
+
* should not have to install it.
|
|
7
|
+
*/
|
|
8
|
+
export interface MuxwsStreamLike {
|
|
9
|
+
result(options?: {
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
}): Promise<unknown>;
|
|
12
|
+
readonly replyHeadersArrived: Promise<void>;
|
|
13
|
+
readonly replyHeaders: Record<string, unknown> | null | undefined;
|
|
14
|
+
}
|
|
15
|
+
export interface MuxwsPeerLike {
|
|
16
|
+
open(payload?: unknown, options?: {
|
|
17
|
+
headers?: Record<string, unknown>;
|
|
18
|
+
end?: boolean;
|
|
19
|
+
}): MuxwsStreamLike;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Where the peer comes from. A bare peer is the simple case; a function is for the common shape
|
|
23
|
+
* where the proxy is constructed at module scope but `connect()` has not resolved yet. The
|
|
24
|
+
* function is called once and its result cached — a muxws Peer survives its own reconnects, so
|
|
25
|
+
* there is nothing to re-resolve afterwards.
|
|
26
|
+
*/
|
|
27
|
+
export type MuxwsPeerSource = MuxwsPeerLike | (() => MuxwsPeerLike | Promise<MuxwsPeerLike>);
|
|
28
|
+
export type MuxwsProxy<M> = M;
|
|
29
|
+
type ViewSetClass = abstract new (...args: any[]) => any;
|
|
30
|
+
export interface MuxwsProxyOptions extends ProxyBaseOptions {
|
|
31
|
+
peer: MuxwsPeerSource;
|
|
32
|
+
/** Per-request timeout in milliseconds. muxws resets the stream with TIMEOUT when it expires. */
|
|
33
|
+
timeoutMs?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Headers added to every request this proxy makes. The WebSocket handshake already carries
|
|
36
|
+
* whatever identified the session and the server treats that as the baseline; these override it
|
|
37
|
+
* for this proxy's calls. There is no per-call header: `RequestOptions` is `{ query, body }`.
|
|
38
|
+
*/
|
|
39
|
+
headers?: Record<string, string>;
|
|
40
|
+
}
|
|
41
|
+
export declare class MuxwsProxyImpl<K extends KeyType, T, PK extends keyof T> extends ViewSetProxyBase<K, T, PK> {
|
|
42
|
+
private readonly peerSource;
|
|
43
|
+
private readonly timeoutMs?;
|
|
44
|
+
private readonly headers;
|
|
45
|
+
private peerPromise?;
|
|
46
|
+
constructor(options: MuxwsProxyOptions);
|
|
47
|
+
private peer;
|
|
48
|
+
protected request<R>(method: HttpMethod, path: string, options?: RequestOptions): Promise<R>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Registers a muxws proxy for the given ViewSet class. The mirror of route_rest, and it takes the
|
|
52
|
+
* same generic parameter for the same reason: TypeScript cannot inspect the Python class.
|
|
53
|
+
*/
|
|
54
|
+
declare function route_muxws<M>(viewSetClass: ViewSetClass, options: MuxwsProxyOptions): MuxwsProxy<M>;
|
|
55
|
+
export { route_muxws };
|
|
56
|
+
//# sourceMappingURL=muxws-proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"muxws-proxy.d.ts","sourceRoot":"","sources":["../vue/muxws-proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EACL,KAAK,UAAU,EACf,KAAK,gBAAgB,EAErB,KAAK,cAAc,EACnB,gBAAgB,EAGjB,MAAM,cAAc,CAAC;AAEtB;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;CACnE;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,GAAG,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,eAAe,CAAC;CAC1G;AAED;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,aAAa,GAAG,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC;AAE7F,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC;AAE9B,KAAK,YAAY,GAAG,QAAQ,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;AAEzD,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD,IAAI,EAAE,eAAe,CAAC;IACtB,iGAAiG;IACjG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,qBAAa,cAAc,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,EAAE,EAAE,SAAS,MAAM,CAAC,CAAE,SAAQ,gBAAgB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;IACtG,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAkB;IAE7C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAS;IAEpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IAEjD,OAAO,CAAC,WAAW,CAAC,CAAyB;gBAEjC,OAAO,EAAE,iBAAiB;IAQtC,OAAO,CAAC,IAAI;cAQI,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,CAAC,CAAC;CAyBvG;AAkCD;;;GAGG;AACH,iBAAS,WAAW,CAAC,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,GAAG,UAAU,CAAC,CAAC,CAAC,CAO7F;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { BulkViewSetMixin, CursorListMixin, CursorPage, CursorParams, DestroyReturnData, KeyType, ListParams, LookupItem, LookupMixin, PageParams, PaginatedList, PaginatedListMixin } from './mixins';
|
|
2
|
+
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
3
|
+
/** Query values; an array becomes a repeated key, which is how FastAPI binds `list[str]`. */
|
|
4
|
+
export type QueryParams = Record<string, string | number | boolean | null | undefined | Array<string | number>>;
|
|
5
|
+
export interface RequestOptions {
|
|
6
|
+
query?: QueryParams;
|
|
7
|
+
body?: unknown;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* What a failed call throws over muxws, where there is no axios to raise anything.
|
|
11
|
+
*
|
|
12
|
+
* The shape mirrors `AxiosError` — `error.response.status`, `error.response.data` and
|
|
13
|
+
* `error.response.headers` — so a caller reads the same fields whichever transport the ViewSet
|
|
14
|
+
* speaks. Over HTTP axios raises its own error, already in that shape, and it is passed through
|
|
15
|
+
* untouched.
|
|
16
|
+
*
|
|
17
|
+
* `response` is always set here, unlike `AxiosError.response`, which is absent when the request
|
|
18
|
+
* never reached a reply.
|
|
19
|
+
*/
|
|
20
|
+
export declare class ViewSetRequestError extends Error {
|
|
21
|
+
readonly response: {
|
|
22
|
+
status: number;
|
|
23
|
+
data: unknown;
|
|
24
|
+
headers: Record<string, string>;
|
|
25
|
+
};
|
|
26
|
+
constructor(status: number, data: unknown, headers?: Record<string, string>);
|
|
27
|
+
}
|
|
28
|
+
/** One entry of a ViewSet's `static declares` list: a mixin naming the actions it contributes. */
|
|
29
|
+
export interface ViewSetMixinDeclaration {
|
|
30
|
+
readonly actions: readonly string[];
|
|
31
|
+
}
|
|
32
|
+
export interface ProxyBaseOptions {
|
|
33
|
+
/** Base path to the resource, e.g. '/items'. */
|
|
34
|
+
basePath: string;
|
|
35
|
+
/** Name of the PK field on the model, e.g. 'id'. */
|
|
36
|
+
pkFieldName: string;
|
|
37
|
+
/** Set false to skip the startup schema check (it is advisory and costs one request). */
|
|
38
|
+
validateSchema?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* The mixins the ViewSet declares, for the `route_rest` / `route_muxws` path: those build a bare
|
|
41
|
+
* proxy and use the ViewSet class only for typing, so a `static declares` on it would otherwise
|
|
42
|
+
* never reach the object being checked.
|
|
43
|
+
*/
|
|
44
|
+
declares?: readonly ViewSetMixinDeclaration[];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* What a ViewSet's own methods may reach - everything a custom endpoint needs, and nothing a caller
|
|
48
|
+
* does.
|
|
49
|
+
*
|
|
50
|
+
* A real base class rather than a type, because `protected` is checked nominally: a subclass body
|
|
51
|
+
* reaches `request()` only if it genuinely descends from the class that declared it. The ViewSet
|
|
52
|
+
* factory hands back a class typed as this plus the declared actions, which is how a factory-built
|
|
53
|
+
* ViewSet ends up with a narrow public surface and a usable private one.
|
|
54
|
+
*/
|
|
55
|
+
export declare abstract class ViewSetInternals {
|
|
56
|
+
protected readonly basePath: string;
|
|
57
|
+
protected constructor(basePath: string);
|
|
58
|
+
/**
|
|
59
|
+
* Sends one request and returns the decoded response body.
|
|
60
|
+
*
|
|
61
|
+
* `path` is relative to `basePath` — '' for the collection, '/1' for a record, '/bulk', and so
|
|
62
|
+
* on. Implementations must throw on a status of 400 or above, with `response.status` readable on
|
|
63
|
+
* the thrown value. Below 400 the two differ, on a band a caller rarely sees: the muxws proxy
|
|
64
|
+
* returns the body for any 3xx, while the REST proxy follows a redirect it can follow and rejects
|
|
65
|
+
* whatever axios' default `validateStatus` then leaves outside 200-299.
|
|
66
|
+
*
|
|
67
|
+
* Concrete here, and never reached: ViewSetProxyBase re-declares it abstract, which is where a
|
|
68
|
+
* transport is actually held to implementing it. It cannot be abstract at this level because
|
|
69
|
+
* TypeScript propagates an abstract member through a constructor type, and the factory hands one
|
|
70
|
+
* back - every ViewSet a consumer wrote would then fail TS2515 for a method the transport
|
|
71
|
+
* underneath it has always implemented.
|
|
72
|
+
*/
|
|
73
|
+
protected request<R>(method: HttpMethod, path: string, options?: RequestOptions): Promise<R>;
|
|
74
|
+
}
|
|
75
|
+
export declare abstract class ViewSetProxyBase<K extends KeyType, T, PK extends keyof T> extends ViewSetInternals implements BulkViewSetMixin<K, T, PK>, CursorListMixin<T>, PaginatedListMixin<T>, LookupMixin {
|
|
76
|
+
/**
|
|
77
|
+
* The mixins this ViewSet is composed of — the FE counterpart of a BE viewset's base classes.
|
|
78
|
+
*
|
|
79
|
+
* class ItemViewSet extends RestProxyImpl<number, Item, 'id'> {
|
|
80
|
+
* static declares = [ReadOnlyViewSetMixin, LookupMixin];
|
|
81
|
+
* }
|
|
82
|
+
*
|
|
83
|
+
* Left undefined, the ViewSet is not checked against the BE schema at all. That is deliberate:
|
|
84
|
+
* a ViewSet that never said what it has cannot be caught contradicting itself, and guessing on
|
|
85
|
+
* its behalf is what made the check report actions nobody ever claimed.
|
|
86
|
+
*/
|
|
87
|
+
static declares?: readonly ViewSetMixinDeclaration[];
|
|
88
|
+
protected readonly pkFieldName: string;
|
|
89
|
+
private readonly schemaValidationEnabled;
|
|
90
|
+
private readonly declaredMixins?;
|
|
91
|
+
protected constructor(options: ProxyBaseOptions);
|
|
92
|
+
/**
|
|
93
|
+
* Starts the advisory schema check. Subclasses must call this as the *last* statement of their
|
|
94
|
+
* constructor, never the base constructor itself: `request()` reads fields the subclass has not
|
|
95
|
+
* assigned yet while `super()` is still running, and since the check swallows its own errors,
|
|
96
|
+
* doing it here would leave it permanently and silently dead.
|
|
97
|
+
*/
|
|
98
|
+
protected initSchemaValidation(): void;
|
|
99
|
+
/** Abstract here, where a transport is actually held to it. See ViewSetInternals.request. */
|
|
100
|
+
protected abstract request<R>(method: HttpMethod, path: string, options?: RequestOptions): Promise<R>;
|
|
101
|
+
/**
|
|
102
|
+
* Fetches the BE schema and compares it against what this ViewSet declared.
|
|
103
|
+
* Logs a console warning for any mismatch found.
|
|
104
|
+
*
|
|
105
|
+
* The comparison is against `static declares`, not against which methods exist on the object:
|
|
106
|
+
* every action is implemented unconditionally on this class, so `typeof this[action]` is true for
|
|
107
|
+
* every ViewSet and answers a question nobody asked. `declares` is the only place the FE says
|
|
108
|
+
* anything a BE viewset could disagree with.
|
|
109
|
+
*
|
|
110
|
+
* Non-critical: errors during fetch or parsing are silently ignored. Note that the schema is
|
|
111
|
+
* fetched over this proxy's own transport, so a muxws proxy validates against the muxws
|
|
112
|
+
* endpoint set and a REST proxy against the REST one — which is the point, since the two are
|
|
113
|
+
* allowed to differ.
|
|
114
|
+
*/
|
|
115
|
+
private validateAgainstSchema;
|
|
116
|
+
create(data: Omit<T, PK>): Promise<T>;
|
|
117
|
+
bulkCreate(data: Omit<T, PK>[]): Promise<T[]>;
|
|
118
|
+
list(params?: ListParams): Promise<T[]>;
|
|
119
|
+
/**
|
|
120
|
+
* Fetches one page. Only meaningful against a viewset built on the BE PaginatedListMixin — a
|
|
121
|
+
* plain ListMixin ignores offset/limit and answers with the whole collection, which would not
|
|
122
|
+
* match this return type.
|
|
123
|
+
*
|
|
124
|
+
* The BE speaks snake_case (`has_more`); the rest of this client speaks whatever the model
|
|
125
|
+
* declares, so only the envelope's own fields are renamed here. The records inside are passed
|
|
126
|
+
* through untouched.
|
|
127
|
+
*/
|
|
128
|
+
/**
|
|
129
|
+
* Fetches one cursor page. Only meaningful against a viewset built on the BE CursorListMixin.
|
|
130
|
+
*
|
|
131
|
+
* Follow `next` to walk forward. Unlike offset paging, a row inserted or removed behind you
|
|
132
|
+
* cannot make the next page repeat or skip anything.
|
|
133
|
+
*/
|
|
134
|
+
listCursor(params?: CursorParams): Promise<CursorPage<T>>;
|
|
135
|
+
listPage(params?: PageParams): Promise<PaginatedList<T>>;
|
|
136
|
+
retrieve(pk: K): Promise<T>;
|
|
137
|
+
update(pk: K, data: T): Promise<T>;
|
|
138
|
+
partialUpdate(pk: K, data: Partial<T>): Promise<T>;
|
|
139
|
+
bulkUpdate(records: Record<K, T>): Promise<T[]>;
|
|
140
|
+
bulkPartialUpdate(records: Record<K, Partial<T>>): Promise<T[]>;
|
|
141
|
+
destroy(pk: K): Promise<DestroyReturnData>;
|
|
142
|
+
bulkDestroy(pks: K[]): Promise<DestroyReturnData[]>;
|
|
143
|
+
lookup(): Promise<LookupItem[]>;
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=proxy-base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy-base.d.ts","sourceRoot":"","sources":["../vue/proxy-base.ts"],"names":[],"mappings":"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"}
|
package/dist/rest-proxy.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AxiosInstance } from 'axios';
|
|
2
|
-
import {
|
|
2
|
+
import { KeyType } from './mixins';
|
|
3
|
+
import { HttpMethod, ProxyBaseOptions, RequestOptions, ViewSetProxyBase } from './proxy-base';
|
|
3
4
|
/** ViewSet class constructor (for type-level introspection only). */
|
|
4
5
|
type ViewSetClass = abstract new (...args: any[]) => any;
|
|
5
6
|
/**
|
|
@@ -8,36 +9,23 @@ type ViewSetClass = abstract new (...args: any[]) => any;
|
|
|
8
9
|
* caller provides the explicit type via the generic parameter `M` (see route_rest).
|
|
9
10
|
*/
|
|
10
11
|
export type RestProxy<M> = M;
|
|
11
|
-
export interface RestProxyOptions {
|
|
12
|
-
/** Base path to the resource, e.g. '/items'. */
|
|
13
|
-
basePath: string;
|
|
14
|
-
/** Name of the PK field on the model, e.g. 'id'. */
|
|
15
|
-
pkFieldName: string;
|
|
12
|
+
export interface RestProxyOptions extends ProxyBaseOptions {
|
|
16
13
|
/** Optional: existing axios instance. Defaults to the global axios. */
|
|
17
14
|
axiosInstance?: AxiosInstance;
|
|
18
15
|
}
|
|
19
|
-
export declare class RestProxyImpl<K extends KeyType, T, PK extends keyof T>
|
|
16
|
+
export declare class RestProxyImpl<K extends KeyType, T, PK extends keyof T> extends ViewSetProxyBase<K, T, PK> {
|
|
20
17
|
protected readonly http: AxiosInstance;
|
|
21
|
-
protected readonly basePath: string;
|
|
22
|
-
protected readonly pkFieldName: string;
|
|
23
18
|
constructor(options: RestProxyOptions);
|
|
24
19
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
20
|
+
* Dispatches to axios' per-verb methods rather than to `http.request()`, deliberately. Those
|
|
21
|
+
* are the calls this proxy has always made, and they are what application interceptors and test
|
|
22
|
+
* doubles are written against — routing everything through `request()` would be invisible on
|
|
23
|
+
* the wire but would break every one of them.
|
|
24
|
+
*
|
|
25
|
+
* axios throws its own AxiosError on a non-2xx, which already carries `response.status` — the
|
|
26
|
+
* shape ViewSetRequestError mirrors for the muxws side. Nothing to translate here.
|
|
28
27
|
*/
|
|
29
|
-
|
|
30
|
-
create(data: Omit<T, PK>): Promise<T>;
|
|
31
|
-
bulkCreate(data: Omit<T, PK>[]): Promise<T[]>;
|
|
32
|
-
list(): Promise<T[]>;
|
|
33
|
-
retrieve(pk: K): Promise<T>;
|
|
34
|
-
update(pk: K, data: T): Promise<T>;
|
|
35
|
-
partialUpdate(pk: K, data: Partial<T>): Promise<T>;
|
|
36
|
-
bulkUpdate(records: Record<K, T>): Promise<T[]>;
|
|
37
|
-
bulkPartialUpdate(records: Record<K, Partial<T>>): Promise<T[]>;
|
|
38
|
-
destroy(pk: K): Promise<DestroyReturnData>;
|
|
39
|
-
bulkDestroy(pks: K[]): Promise<DestroyReturnData[]>;
|
|
40
|
-
lookup(): Promise<LookupItem[]>;
|
|
28
|
+
protected request<R>(method: HttpMethod, path: string, options?: RequestOptions): Promise<R>;
|
|
41
29
|
}
|
|
42
30
|
/**
|
|
43
31
|
* Registers a REST proxy for the given ViewSet class.
|
package/dist/rest-proxy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rest-proxy.d.ts","sourceRoot":"","sources":["../vue/rest-proxy.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"rest-proxy.d.ts","sourceRoot":"","sources":["../vue/rest-proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAc,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAElD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EACL,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,cAAc,EAEnB,gBAAgB,EACjB,MAAM,cAAc,CAAC;AAMtB,qEAAqE;AAErE,KAAK,YAAY,GAAG,QAAQ,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;AAEzD;;;;GAIG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC;AAE7B,MAAM,WAAW,gBAAiB,SAAQ,gBAAgB;IACxD,uEAAuE;IACvE,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAMD,qBAAa,aAAa,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,EAAE,EAAE,SAAS,MAAM,CAAC,CAAE,SAAQ,gBAAgB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;IACrG,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;gBAE3B,OAAO,EAAE,gBAAgB;IAMrC;;;;;;;;OAQG;cACa,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,CAAC,CAAC;CAsCvG;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,iBAAS,UAAU,CAAC,CAAC,EACnB,aAAa,EAAE,YAAY,EAC3B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,aAAa,CAAC,EAAE,aAAa,GAC5B,SAAS,CAAC,CAAC,CAAC,CAAC;AAChB,iBAAS,UAAU,CAAC,CAAC,EAAE,aAAa,EAAE,YAAY,EAAE,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;AAuB7F,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ActionName, ActionSurface, KeyType } from './mixins';
|
|
2
|
+
import { MuxwsProxyOptions } from './muxws-proxy';
|
|
3
|
+
import { ProxyBaseOptions, ViewSetInternals, ViewSetMixinDeclaration } from './proxy-base';
|
|
4
|
+
import { RestProxyOptions } from './rest-proxy';
|
|
5
|
+
/** A mixin class: the runtime `actions` the schema check reads, and the type naming those actions. */
|
|
6
|
+
export type ViewSetMixinClass = ViewSetMixinDeclaration & (abstract new (...args: any[]) => object);
|
|
7
|
+
/**
|
|
8
|
+
* The actions a mixin class names, read off its instance type.
|
|
9
|
+
*
|
|
10
|
+
* The instance type rather than the `actions` tuple, because a tuple would have to be `as const` on
|
|
11
|
+
* every mixin, and a `readonly ['create']` static cannot then be inherited by a composite whose own
|
|
12
|
+
* static is a different tuple (TS2417). `D` is naked so that a union of mixins distributes.
|
|
13
|
+
*/
|
|
14
|
+
type ActionsOf<D> = D extends abstract new (...args: any[]) => infer I ? Extract<keyof I, ActionName> : never;
|
|
15
|
+
/** The fields of `T` that could be a primary key. */
|
|
16
|
+
export type PkFieldName<T> = Extract<{
|
|
17
|
+
[F in keyof T]-?: NonNullable<T[F]> extends KeyType ? F : never;
|
|
18
|
+
}[keyof T], string>;
|
|
19
|
+
type PkType<T, PK extends keyof T> = NonNullable<T[PK]> & KeyType;
|
|
20
|
+
/**
|
|
21
|
+
* What the factory hands back: a class to extend.
|
|
22
|
+
*
|
|
23
|
+
* A `declares` list naming no action — `[]`, or one annotated `ViewSetMixinClass[]`, which erases
|
|
24
|
+
* which mixins are in it — would otherwise produce a ViewSet with no actions and no complaint.
|
|
25
|
+
* TS2507 prints the type it was given, so the type is the sentence.
|
|
26
|
+
*/
|
|
27
|
+
export type ViewSetClass<T, PK extends keyof T, D extends readonly ViewSetMixinClass[], O extends ProxyBaseOptions> = [
|
|
28
|
+
ActionsOf<D[number]>
|
|
29
|
+
] extends [never] ? 'declares must name at least one action: pass the mixin classes themselves, unannotated' : {
|
|
30
|
+
new (options: Omit<O, 'pkFieldName' | 'declares'>): ViewSetInternals & ActionSurface<PkType<T, PK>, T, PK, ActionsOf<D[number]>>;
|
|
31
|
+
readonly declares: D;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* A REST ViewSet base class.
|
|
35
|
+
*
|
|
36
|
+
* The empty `()` is not decoration: TypeScript has no partial type-argument inference, so the model
|
|
37
|
+
* cannot be given explicitly while the pk field and the mixin list are inferred from arguments in
|
|
38
|
+
* the same call (TS2558). Currying is the only way to have both.
|
|
39
|
+
*/
|
|
40
|
+
export declare function restViewSet<T>(): <PK extends PkFieldName<T> & keyof T, D extends readonly ViewSetMixinClass[]>(pkFieldName: PK, declares: D) => ViewSetClass<T, PK, D, RestProxyOptions>;
|
|
41
|
+
/** A muxws ViewSet base class. See `restViewSet` for why the call is curried. */
|
|
42
|
+
export declare function muxwsViewSet<T>(): <PK extends PkFieldName<T> & keyof T, D extends readonly ViewSetMixinClass[]>(pkFieldName: PK, declares: D) => ViewSetClass<T, PK, D, MuxwsProxyOptions>;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=viewset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewset.d.ts","sourceRoot":"","sources":["../vue/viewset.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnE,OAAO,EAAkB,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,KAAK,gBAAgB,EAAE,gBAAgB,EAAE,KAAK,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACrG,OAAO,EAAiB,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEpE,sGAAsG;AACtG,MAAM,MAAM,iBAAiB,GAAG,uBAAuB,GAAG,CAAC,QAAQ,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,MAAM,CAAC,CAAC;AAEpG;;;;;;GAMG;AACH,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,QAAQ,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,GAAG,KAAK,CAAC;AAE9G,qDAAqD;AACrD,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,OAAO,CAClC;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,OAAO,GAAG,CAAC,GAAG,KAAK;CAAE,CAAC,MAAM,CAAC,CAAC,EAC5E,MAAM,CACP,CAAC;AAEF,KAAK,MAAM,CAAC,CAAC,EAAE,EAAE,SAAS,MAAM,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC;AAElE;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,EAAE,EAAE,SAAS,MAAM,CAAC,EAAE,CAAC,SAAS,SAAS,iBAAiB,EAAE,EAAE,CAAC,SAAS,gBAAgB,IAAI;IACpH,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;CACrB,SAAS,CAAC,KAAK,CAAC,GACb,wFAAwF,GACxF;IACE,KACE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,aAAa,GAAG,UAAU,CAAC,GAC3C,gBAAgB,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAChF,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;CACtB,CAAC;AA8BN;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,CAAC,MACnB,EAAE,SAAS,WAAW,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,SAAS,SAAS,iBAAiB,EAAE,EACjF,aAAa,EAAE,EACf,UAAU,CAAC,KACV,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,gBAAgB,CAAC,CAE5C;AAED,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,CAAC,MACpB,EAAE,SAAS,WAAW,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,SAAS,SAAS,iBAAiB,EAAE,EACjF,aAAa,EAAE,EACf,UAAU,CAAC,KACV,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,iBAAiB,CAAC,CAE7C"}
|