@venizia/ignis-connectors 0.2.0-40 → 0.2.0-41
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/dist/cjs/common/scope-filter.js +1 -1
- package/dist/cjs/common/scope-filter.js.map +1 -1
- package/dist/cjs/http/common/types.d.ts +8 -36
- package/dist/cjs/http/common/types.d.ts.map +1 -1
- package/dist/cjs/http/datasource.d.ts +5 -40
- package/dist/cjs/http/datasource.d.ts.map +1 -1
- package/dist/cjs/http/datasource.js +71 -69
- package/dist/cjs/http/datasource.js.map +1 -1
- package/dist/cjs/http/repository.d.ts +10 -23
- package/dist/cjs/http/repository.d.ts.map +1 -1
- package/dist/cjs/http/repository.js +38 -34
- package/dist/cjs/http/repository.js.map +1 -1
- package/dist/cjs/relational/core/migrations/runner.d.ts.map +1 -1
- package/dist/cjs/relational/core/migrations/runner.js +2 -1
- package/dist/cjs/relational/core/migrations/runner.js.map +1 -1
- package/dist/cjs/relational/core/repositories/dialect/filter.d.ts +6 -3
- package/dist/cjs/relational/core/repositories/dialect/filter.d.ts.map +1 -1
- package/dist/cjs/relational/core/repositories/dialect/filter.js +53 -16
- package/dist/cjs/relational/core/repositories/dialect/filter.js.map +1 -1
- package/dist/cjs/relational/postgres/models/enrichers/id.enricher.d.ts.map +1 -1
- package/dist/cjs/relational/postgres/models/enrichers/id.enricher.js +3 -1
- package/dist/cjs/relational/postgres/models/enrichers/id.enricher.js.map +1 -1
- package/dist/cjs/relational/sqlite/models/enrichers/id.enricher.d.ts.map +1 -1
- package/dist/cjs/relational/sqlite/models/enrichers/id.enricher.js +3 -1
- package/dist/cjs/relational/sqlite/models/enrichers/id.enricher.js.map +1 -1
- package/dist/cjs/search/core/datasources/base.d.ts.map +1 -1
- package/dist/cjs/search/core/datasources/base.js +2 -1
- package/dist/cjs/search/core/datasources/base.js.map +1 -1
- package/dist/cjs/search/core/repositories/common/constants.d.ts.map +1 -1
- package/dist/cjs/search/core/repositories/common/constants.js +2 -1
- package/dist/cjs/search/core/repositories/common/constants.js.map +1 -1
- package/dist/cjs/search/meilisearch/internal/connector-internal.d.ts.map +1 -1
- package/dist/cjs/search/meilisearch/internal/connector-internal.js +2 -1
- package/dist/cjs/search/meilisearch/internal/connector-internal.js.map +1 -1
- package/dist/cjs/search/meilisearch/repositories/dialect/query-dialect.d.ts.map +1 -1
- package/dist/cjs/search/meilisearch/repositories/dialect/query-dialect.js +2 -1
- package/dist/cjs/search/meilisearch/repositories/dialect/query-dialect.js.map +1 -1
- package/dist/cjs/search/typesense/compiler.d.ts.map +1 -1
- package/dist/cjs/search/typesense/compiler.js +2 -1
- package/dist/cjs/search/typesense/compiler.js.map +1 -1
- package/dist/cjs/search/typesense/repositories/dialect/query-dialect.d.ts.map +1 -1
- package/dist/cjs/search/typesense/repositories/dialect/query-dialect.js +2 -1
- package/dist/cjs/search/typesense/repositories/dialect/query-dialect.js.map +1 -1
- package/dist/esm/common/scope-filter.js +1 -1
- package/dist/esm/common/scope-filter.js.map +1 -1
- package/dist/esm/http/common/types.d.ts +8 -36
- package/dist/esm/http/common/types.d.ts.map +1 -1
- package/dist/esm/http/datasource.d.ts +5 -40
- package/dist/esm/http/datasource.d.ts.map +1 -1
- package/dist/esm/http/datasource.js +71 -69
- package/dist/esm/http/datasource.js.map +1 -1
- package/dist/esm/http/repository.d.ts +10 -23
- package/dist/esm/http/repository.d.ts.map +1 -1
- package/dist/esm/http/repository.js +38 -34
- package/dist/esm/http/repository.js.map +1 -1
- package/dist/esm/relational/core/migrations/runner.d.ts.map +1 -1
- package/dist/esm/relational/core/migrations/runner.js +2 -1
- package/dist/esm/relational/core/migrations/runner.js.map +1 -1
- package/dist/esm/relational/core/repositories/dialect/filter.d.ts +6 -3
- package/dist/esm/relational/core/repositories/dialect/filter.d.ts.map +1 -1
- package/dist/esm/relational/core/repositories/dialect/filter.js +53 -16
- package/dist/esm/relational/core/repositories/dialect/filter.js.map +1 -1
- package/dist/esm/relational/postgres/models/enrichers/id.enricher.d.ts.map +1 -1
- package/dist/esm/relational/postgres/models/enrichers/id.enricher.js +4 -2
- package/dist/esm/relational/postgres/models/enrichers/id.enricher.js.map +1 -1
- package/dist/esm/relational/sqlite/models/enrichers/id.enricher.d.ts.map +1 -1
- package/dist/esm/relational/sqlite/models/enrichers/id.enricher.js +4 -2
- package/dist/esm/relational/sqlite/models/enrichers/id.enricher.js.map +1 -1
- package/dist/esm/search/core/datasources/base.d.ts.map +1 -1
- package/dist/esm/search/core/datasources/base.js +2 -1
- package/dist/esm/search/core/datasources/base.js.map +1 -1
- package/dist/esm/search/core/repositories/common/constants.d.ts.map +1 -1
- package/dist/esm/search/core/repositories/common/constants.js +2 -1
- package/dist/esm/search/core/repositories/common/constants.js.map +1 -1
- package/dist/esm/search/meilisearch/internal/connector-internal.d.ts.map +1 -1
- package/dist/esm/search/meilisearch/internal/connector-internal.js +2 -1
- package/dist/esm/search/meilisearch/internal/connector-internal.js.map +1 -1
- package/dist/esm/search/meilisearch/repositories/dialect/query-dialect.d.ts.map +1 -1
- package/dist/esm/search/meilisearch/repositories/dialect/query-dialect.js +2 -1
- package/dist/esm/search/meilisearch/repositories/dialect/query-dialect.js.map +1 -1
- package/dist/esm/search/typesense/compiler.d.ts.map +1 -1
- package/dist/esm/search/typesense/compiler.js +2 -1
- package/dist/esm/search/typesense/compiler.js.map +1 -1
- package/dist/esm/search/typesense/repositories/dialect/query-dialect.d.ts.map +1 -1
- package/dist/esm/search/typesense/repositories/dialect/query-dialect.js +2 -1
- package/dist/esm/search/typesense/repositories/dialect/query-dialect.js.map +1 -1
- package/package.json +18 -6
|
@@ -19,7 +19,7 @@ const assertScopeFilterSupported = (opts) => {
|
|
|
19
19
|
if (!entry.metadata?.settings?.scopeFilter) {
|
|
20
20
|
continue;
|
|
21
21
|
}
|
|
22
|
-
const modelClass = (0, common_1.resolveValue)(entry.target);
|
|
22
|
+
const modelClass = (0, common_1.resolveValue)({ value: entry.target });
|
|
23
23
|
if (modelClass === models_1.BaseSearchEntity || modelClass.prototype instanceof models_1.BaseSearchEntity) {
|
|
24
24
|
searchBacked.push(name);
|
|
25
25
|
continue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope-filter.js","sourceRoot":"","sources":["../../../src/common/scope-filter.ts"],"names":[],"mappings":";;;AAAA,0DAA6D;AAC7D,sDAAuD;AACvD,wDAAyD;AACzD,iDAAwD;AAExD;;;;;GAKG;AACI,MAAM,0BAA0B,GAAG,CAAC,IAAsC,EAAQ,EAAE;IACzF,MAAM,MAAM,GAAG,+BAAgB,CAAC,WAAW,EAAE,CAAC,YAAY,EAAE,CAAC;IAE7D,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,MAAM,qBAAqB,GAAa,EAAE,CAAC;IAE3C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;QACnC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;YAC3C,SAAS;QACX,CAAC;QAED,MAAM,UAAU,GAAG,IAAA,qBAAY,EAAC,KAAK,CAAC,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"scope-filter.js","sourceRoot":"","sources":["../../../src/common/scope-filter.ts"],"names":[],"mappings":";;;AAAA,0DAA6D;AAC7D,sDAAuD;AACvD,wDAAyD;AACzD,iDAAwD;AAExD;;;;;GAKG;AACI,MAAM,0BAA0B,GAAG,CAAC,IAAsC,EAAQ,EAAE;IACzF,MAAM,MAAM,GAAG,+BAAgB,CAAC,WAAW,EAAE,CAAC,YAAY,EAAE,CAAC;IAE7D,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,MAAM,qBAAqB,GAAa,EAAE,CAAC;IAE3C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;QACnC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;YAC3C,SAAS;QACX,CAAC;QAED,MAAM,UAAU,GAAG,IAAA,qBAAY,EAAC,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAEzD,IAAI,UAAU,KAAK,yBAAgB,IAAI,UAAU,CAAC,SAAS,YAAY,yBAAgB,EAAE,CAAC;YACxF,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxB,SAAS;QACX,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC9B,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAA,eAAQ,EAAC;YACb,OAAO,EAAE;gBACP,wFAAwF,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACjH,0EAA0E;gBAC1E,gIAAgI;gBAChI,4FAA4F;aAC7F,CAAC,IAAI,CAAC,KAAK,CAAC;SACd,CAAC,CAAC;IACL,CAAC;IAED,IAAI,qBAAqB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,IAAA,eAAQ,EAAC;YACb,OAAO,EAAE;gBACP,2GAA2G,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBAC7I,6FAA6F;gBAC7F,sLAAsL;gBACtL,kEAAkE;aACnE,CAAC,IAAI,CAAC,KAAK,CAAC;SACd,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC;AA5CW,QAAA,0BAA0B,8BA4CrC"}
|
|
@@ -1,57 +1,29 @@
|
|
|
1
1
|
import type { TFilter } from '@venizia/ignis-filter';
|
|
2
|
-
/** What a caller hands the resolver seam: the token and, optionally, which provider issued it. */
|
|
3
2
|
export interface IAuthToken {
|
|
4
3
|
value: string;
|
|
5
4
|
type?: string;
|
|
6
5
|
provider?: string;
|
|
7
6
|
}
|
|
8
|
-
/**
|
|
9
|
-
* Where the token comes from when the datasource was not given one outright.
|
|
10
|
-
*
|
|
11
|
-
* A seam, not a guard: a browser resolver reads storage, a server resolver reads a secret, and
|
|
12
|
-
* neither is baked into the transport. Returning `undefined` means "no token", which is different
|
|
13
|
-
* from an empty one.
|
|
14
|
-
*/
|
|
7
|
+
/** `undefined` means no token. */
|
|
15
8
|
export type TAuthTokenResolver = () => IAuthToken | undefined;
|
|
16
|
-
/**
|
|
17
|
-
* Every shape `Headers` accepts. Not `Record<string, string>`: header names are case-INSENSITIVE,
|
|
18
|
-
* so a plain object lets two spellings of one name coexist, and merging them APPENDS rather than
|
|
19
|
-
* overrides - `{ 'x-request-count': 'false', 'X-Request-Count': 'true' }` reaches the wire as
|
|
20
|
-
* `x-request-count: "false, true"`, which parses as neither.
|
|
21
|
-
*/
|
|
9
|
+
/** Not `Record` alone: header names are case-insensitive, and an object merge appends two spellings. */
|
|
22
10
|
export type THttpHeaders = Headers | Array<[string, string]> | Record<string, string>;
|
|
23
11
|
export interface IHttpDataSourceSettings {
|
|
24
12
|
baseUrl: string;
|
|
25
|
-
/** Sent on every request
|
|
13
|
+
/** Sent on every request. `x-request-count` is refused - the connector owns it. */
|
|
26
14
|
headers?: THttpHeaders;
|
|
27
|
-
/**
|
|
15
|
+
/** Wins over `authTokenResolver`. */
|
|
28
16
|
authToken?: IAuthToken;
|
|
29
17
|
authTokenResolver?: TAuthTokenResolver;
|
|
30
|
-
/**
|
|
31
|
-
* Runs on a 401, and its ANSWER decides: `true` retries the request once, `false` lets the 401
|
|
32
|
-
* stand. Absent means no retry at all.
|
|
33
|
-
*
|
|
34
|
-
* A hook rather than a boolean, because "recover from a 401" is the host's policy, not the
|
|
35
|
-
* transport's: one host refreshes a token then retries, another logs the user out, a third does
|
|
36
|
-
* both in an order only it knows. A boolean could only mean "ask the resolver again", which reads
|
|
37
|
-
* like recovery and is not - someone would wire it expecting a refresh and get a silent loop.
|
|
38
|
-
*
|
|
39
|
-
* The transport's part is the seam and the single retry. Whatever the hook does to make the next
|
|
40
|
-
* attempt work - refresh, re-login, nothing - happens before it answers, and the retry re-resolves
|
|
41
|
-
* the token afterwards.
|
|
42
|
-
*/
|
|
18
|
+
/** Runs on a 401: `true` retries once (re-resolving the token), `false` lets the 401 stand. */
|
|
43
19
|
onUnauthorized?: () => Promise<boolean> | boolean;
|
|
44
20
|
}
|
|
45
|
-
/**
|
|
46
|
-
* One response, with the total kept apart from the rows.
|
|
47
|
-
*
|
|
48
|
-
* `hasRange` is the whole point: a list with no `Content-Range` has NO total, which is a different
|
|
49
|
-
* answer from "the total equals this page". Folding the two is how a count of 7000 reports 1 and
|
|
50
|
-
* every screen reading it looks healthy.
|
|
51
|
-
*/
|
|
21
|
+
/** A list with no `Content-Range` has no total - `hasRange` says so rather than using the page size. */
|
|
52
22
|
export interface IHttpReadResult<R> {
|
|
53
23
|
data: R;
|
|
54
24
|
hasRange: boolean;
|
|
25
|
+
/** Raw header: tells a present-but-unreadable one from an absent one. */
|
|
26
|
+
contentRange?: string;
|
|
55
27
|
total?: number;
|
|
56
28
|
skip?: number;
|
|
57
29
|
dataLength: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/http/common/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/http/common/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,kCAAkC;AAClC,MAAM,MAAM,kBAAkB,GAAG,MAAM,UAAU,GAAG,SAAS,CAAC;AAE9D,wGAAwG;AACxG,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACtF,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAEhB,mFAAmF;IACnF,OAAO,CAAC,EAAE,YAAY,CAAC;IAEvB,qCAAqC;IACrC,SAAS,CAAC,EAAE,UAAU,CAAC;IAEvB,iBAAiB,CAAC,EAAE,kBAAkB,CAAC;IAEvC,+FAA+F;IAC/F,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;CACnD;AAED,wGAAwG;AACxG,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,IAAI,EAAE,CAAC,CAAC;IACR,QAAQ,EAAE,OAAO,CAAC;IAClB,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,MAAM,IAAI;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;CAAE,CAAC"}
|
|
@@ -1,41 +1,22 @@
|
|
|
1
1
|
import { AbstractDataSource } from '@venizia/ignis-kernel/repository';
|
|
2
2
|
import { NodeFetchNetworkRequest } from '@venizia/ignis-helpers/core';
|
|
3
3
|
import type { IAuthToken, IHttpDataSourceSettings, IHttpReadResult } from './common/types';
|
|
4
|
-
/**
|
|
5
|
-
* A datasource whose transport is HTTP.
|
|
6
|
-
*
|
|
7
|
-
* A repository talks to a datasource, and `AbstractDataSource` is engine-neutral - its only required
|
|
8
|
-
* member is `configure()`. So "a request to another IGNIS server" is a datasource in the same sense
|
|
9
|
-
* Drizzle-over-Postgres is one: same role, different transport, and the same
|
|
10
|
-
* `@venizia/ignis-filter` vocabulary on the way in.
|
|
11
|
-
*
|
|
12
|
-
* It targets the IGNIS REST contract - a list route that answers `Content-Range` - and promises
|
|
13
|
-
* nothing about an arbitrary REST API. How a filter serialises and which header carries the total
|
|
14
|
-
* are one API's CONVENTIONS; IGNIS talking to IGNIS is both ends speaking its own.
|
|
15
|
-
*/
|
|
4
|
+
/** Reads an IGNIS REST server through the repository contract. Targets IGNIS, not any REST API. */
|
|
16
5
|
export declare class HttpDataSource extends AbstractDataSource<IHttpDataSourceSettings> {
|
|
17
6
|
name: string;
|
|
18
7
|
settings: IHttpDataSourceSettings;
|
|
19
|
-
/** A remote API publishes no schema to this process. An empty object where a caller expects table metadata is worse than nothing. */
|
|
20
8
|
schema: never;
|
|
21
|
-
/** The framework's own HTTP layer, not a bare `fetch`: timeout, abort, secret redaction and scoped logging come with it, and one HTTP path in the framework beats two. */
|
|
22
9
|
protected network: NodeFetchNetworkRequest;
|
|
10
|
+
/** Normalised once: every request copies these, never re-parses `settings.headers`. */
|
|
11
|
+
protected configuredHeaders: Array<[string, string]>;
|
|
23
12
|
constructor(opts: IHttpDataSourceSettings & {
|
|
24
13
|
name?: string;
|
|
25
14
|
});
|
|
26
|
-
/** Nothing to open. Holding no connection is what makes this one safe to construct anywhere. */
|
|
27
15
|
configure(): Promise<void>;
|
|
28
|
-
/** No transactions over REST. The root probes capabilities rather than assuming them. */
|
|
29
16
|
getCapabilities(): {
|
|
30
17
|
transactions: boolean;
|
|
31
18
|
};
|
|
32
|
-
/** Explicit token first, resolver only when there is none - a caller that supplied one is never overridden by a lookup. */
|
|
33
19
|
protected resolveAuthToken(): IAuthToken | undefined;
|
|
34
|
-
/**
|
|
35
|
-
* Built through `Headers` rather than a plain object, so a caller's value genuinely OVERRIDES a
|
|
36
|
-
* default. Two spellings of one name in an object both survive the merge and `Headers` then
|
|
37
|
-
* APPENDS them - `x-request-count: "false, true"` - which parses as neither.
|
|
38
|
-
*/
|
|
39
20
|
protected buildHeaders(opts: {
|
|
40
21
|
token?: IAuthToken;
|
|
41
22
|
}): Headers;
|
|
@@ -43,32 +24,16 @@ export declare class HttpDataSource extends AbstractDataSource<IHttpDataSourceSe
|
|
|
43
24
|
paths: Array<string>;
|
|
44
25
|
query?: Record<string, unknown>;
|
|
45
26
|
}): string;
|
|
46
|
-
/**
|
|
47
|
-
* One request, with the total read from `Content-Range` and REPORTED as absent when the header is
|
|
48
|
-
* not there.
|
|
49
|
-
*
|
|
50
|
-
* Goes through {@link HttpDataSource.request}, so auth, the 401 hook and the single retry live in
|
|
51
|
-
* ONE place - a second header-building path is where a guard gets forgotten.
|
|
52
|
-
*/
|
|
53
|
-
/**
|
|
54
|
-
* One request, answered RAW.
|
|
55
|
-
*
|
|
56
|
-
* `read` is about rows and cannot express a response that is not JSON - an export endpoint returns
|
|
57
|
-
* bytes and a filename. Rather than invent a blob shape on the repository, whose contract is rows,
|
|
58
|
-
* the transport stays reachable: a caller gets the `Response` and reads `.blob()` and
|
|
59
|
-
* `content-disposition` itself.
|
|
60
|
-
*
|
|
61
|
-
* Auth, the 401 hook and the single retry apply here exactly as they do to `read`.
|
|
62
|
-
*/
|
|
27
|
+
/** The raw `Response` - for what is not rows, like an export. Auth and the 401 retry apply. */
|
|
63
28
|
request(opts: {
|
|
64
29
|
paths: Array<string>;
|
|
65
30
|
query?: Record<string, unknown>;
|
|
66
31
|
method?: string;
|
|
67
32
|
}): Promise<Response>;
|
|
33
|
+
/** Rows plus the total from `Content-Range`, reported absent when the header is. */
|
|
68
34
|
read<R>(opts: {
|
|
69
35
|
paths: Array<string>;
|
|
70
36
|
query?: Record<string, unknown>;
|
|
71
|
-
/** What the caller asked for. `one` is never unwrapped - see {@link unwrapBody}. */
|
|
72
37
|
shape?: 'list' | 'one';
|
|
73
38
|
}): Promise<IHttpReadResult<R>>;
|
|
74
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datasource.d.ts","sourceRoot":"","sources":["../../../src/http/datasource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAEtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"datasource.d.ts","sourceRoot":"","sources":["../../../src/http/datasource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAEtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,OAAO,KAAK,EACV,UAAU,EACV,uBAAuB,EACvB,eAAe,EAEhB,MAAM,gBAAgB,CAAC;AAkGxB,mGAAmG;AACnG,qBAAa,cAAe,SAAQ,kBAAkB,CAAC,uBAAuB,CAAC;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,uBAAuB,CAAC;IAClC,MAAM,EAAS,KAAK,CAAC;IAE9B,SAAS,CAAC,OAAO,EAAE,uBAAuB,CAAC;IAC3C,uFAAuF;IACvF,SAAS,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;gBAEzC,IAAI,EAAE,uBAAuB,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE;IAsBvD,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAEvB,eAAe;;;IAIxB,SAAS,CAAC,gBAAgB,IAAI,UAAU,GAAG,SAAS;IAIpD,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE;QAAE,KAAK,CAAC,EAAE,UAAU,CAAA;KAAE,GAAG,OAAO;IAqB7D,QAAQ,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,MAAM;IAgBjF,+FAA+F;IACzF,OAAO,CAAC,IAAI,EAAE;QAClB,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAChC,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAuBrB,oFAAoF;IAC9E,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE;QAClB,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAChC,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;KACxB,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;CAwBhC"}
|
|
@@ -5,62 +5,93 @@ const repository_1 = require("@venizia/ignis-kernel/repository");
|
|
|
5
5
|
const common_1 = require("@venizia/ignis-helpers/common");
|
|
6
6
|
const core_1 = require("@venizia/ignis-helpers/core");
|
|
7
7
|
const core_2 = require("@venizia/ignis-helpers/core");
|
|
8
|
+
const MAX_URL_IN_MESSAGE = 256;
|
|
9
|
+
/** A long `inq` makes a URL 200 KB: the message keeps its head and length. 414/431 name the URL. */
|
|
10
|
+
const describeUrl = (opts) => {
|
|
11
|
+
const { url, status } = opts;
|
|
12
|
+
const shown = url.length > MAX_URL_IN_MESSAGE
|
|
13
|
+
? `${url.slice(0, MAX_URL_IN_MESSAGE)}... (${url.length} chars)`
|
|
14
|
+
: url;
|
|
15
|
+
const isTooLong = status === common_1.HTTP.ResultCodes.RS_4.URITooLong ||
|
|
16
|
+
status === common_1.HTTP.ResultCodes.RS_4.RequestHeaderFieldsTooLarge;
|
|
17
|
+
return isTooLong
|
|
18
|
+
? `${shown} | The URL is too long for a GET - split the filter (a long inq) into smaller requests.`
|
|
19
|
+
: shown;
|
|
20
|
+
};
|
|
8
21
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* `x-request-count` decides it, and its DEFAULT is on (`rest/base.ts`: `?? 'true'`), so an IGNIS
|
|
12
|
-
* list route answers the count envelope unless asked otherwise. This datasource asks for the bare
|
|
13
|
-
* array, but a hand-written route that never reaches `normalizeCountData` can still answer the
|
|
14
|
-
* envelope - so both are accepted rather than one assumed. Treating an envelope as a row is the
|
|
15
|
-
* failure that reports one record where there were fifty, with no error anywhere.
|
|
22
|
+
* A list is a bare array or the `{ count, data }` envelope; `one` is never unwrapped, since a record
|
|
23
|
+
* may carry `data` and `count` columns. The envelope `count` is the page size, never the total.
|
|
16
24
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* `shape` is asked for rather than sniffed. Structure alone cannot tell an envelope from a record
|
|
21
|
-
* that happens to carry a `data` column and a `count` column, and guessing wrong there unwraps a
|
|
22
|
-
* row into whatever its `data` field held.
|
|
25
|
+
* Anything else asked for as a list throws: counting it as one row is how `existsWith` answers true
|
|
26
|
+
* for an empty result and a page reports a length it does not have.
|
|
23
27
|
*/
|
|
24
28
|
const unwrapBody = (opts) => {
|
|
25
|
-
const { body, shape } = opts;
|
|
29
|
+
const { body, shape, url } = opts;
|
|
26
30
|
if (shape === 'one' || Array.isArray(body)) {
|
|
27
31
|
return body;
|
|
28
32
|
}
|
|
29
33
|
if (body && typeof body === 'object' && 'data' in body && 'count' in body) {
|
|
30
34
|
return body.data;
|
|
31
35
|
}
|
|
32
|
-
|
|
36
|
+
throw (0, core_2.getError)({
|
|
37
|
+
statusCode: common_1.HTTP.ResultCodes.RS_5.InternalServerError,
|
|
38
|
+
message: `[read] A list was asked for and the response is neither an array nor a { count, data } envelope | ${url}`,
|
|
39
|
+
});
|
|
33
40
|
};
|
|
34
|
-
|
|
41
|
+
// `records 0-24/137` -> skip 0, total 137; an empty page `records */137` -> total 137; else undefined.
|
|
35
42
|
const readContentRange = (opts) => {
|
|
36
43
|
const { header } = opts;
|
|
37
44
|
if (!header) {
|
|
38
45
|
return undefined;
|
|
39
46
|
}
|
|
40
|
-
const
|
|
41
|
-
if (
|
|
42
|
-
return
|
|
47
|
+
const range = header.match(/(\d+)\s*-\s*(\d+)\s*\/\s*(\d+)/);
|
|
48
|
+
if (range) {
|
|
49
|
+
return { skip: Number(range[1]), total: Number(range[3]) };
|
|
43
50
|
}
|
|
44
|
-
|
|
51
|
+
const unsatisfied = header.match(/\*\s*\/\s*(\d+)/);
|
|
52
|
+
if (unsatisfied) {
|
|
53
|
+
return { total: Number(unsatisfied[1]) };
|
|
54
|
+
}
|
|
55
|
+
return undefined;
|
|
45
56
|
};
|
|
46
57
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* A repository talks to a datasource, and `AbstractDataSource` is engine-neutral - its only required
|
|
50
|
-
* member is `configure()`. So "a request to another IGNIS server" is a datasource in the same sense
|
|
51
|
-
* Drizzle-over-Postgres is one: same role, different transport, and the same
|
|
52
|
-
* `@venizia/ignis-filter` vocabulary on the way in.
|
|
58
|
+
* Caller headers as unique lowercase pairs, last spelling winning.
|
|
53
59
|
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
60
|
+
* Never `new Headers(input)`: that constructor APPENDS, so `{ 'X-Tenant': 'north', 'x-tenant':
|
|
61
|
+
* 'south' }` - which a merge of two config objects produces - reaches the wire as `"north, south"`,
|
|
62
|
+
* a value neither caller wrote. A `Headers` instance arrives already joined; that one is the
|
|
63
|
+
* caller's own, and is passed through as it stands.
|
|
57
64
|
*/
|
|
65
|
+
const toHeaderEntries = (opts) => {
|
|
66
|
+
const { headers } = opts;
|
|
67
|
+
if (!headers) {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
const source = headers instanceof Headers
|
|
71
|
+
? [...headers.entries()]
|
|
72
|
+
: Array.isArray(headers)
|
|
73
|
+
? headers
|
|
74
|
+
: Object.entries(headers);
|
|
75
|
+
const merged = new Map();
|
|
76
|
+
for (const [name, value] of source) {
|
|
77
|
+
merged.set(name.toLowerCase(), value);
|
|
78
|
+
}
|
|
79
|
+
return [...merged.entries()];
|
|
80
|
+
};
|
|
81
|
+
/** Reads an IGNIS REST server through the repository contract. Targets IGNIS, not any REST API. */
|
|
58
82
|
class HttpDataSource extends repository_1.AbstractDataSource {
|
|
59
83
|
constructor(opts) {
|
|
60
84
|
super({ scope: opts.name ?? HttpDataSource.name });
|
|
61
|
-
/** A remote API publishes no schema to this process. An empty object where a caller expects table metadata is worse than nothing. */
|
|
62
85
|
this.schema = {};
|
|
63
86
|
const { name = 'http', ...settings } = opts;
|
|
87
|
+
const configured = toHeaderEntries({ headers: settings.headers });
|
|
88
|
+
if (configured.some(([headerName]) => headerName === common_1.HTTP.Headers.REQUEST_COUNT_DATA)) {
|
|
89
|
+
throw (0, core_2.getError)({
|
|
90
|
+
statusCode: common_1.HTTP.ResultCodes.RS_5.InternalServerError,
|
|
91
|
+
message: `[${name}] ${common_1.HTTP.Headers.REQUEST_COUNT_DATA} is owned by HttpDataSource and always sent as false: rows come back bare, the total in Content-Range.`,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
this.configuredHeaders = configured;
|
|
64
95
|
this.name = name;
|
|
65
96
|
this.settings = settings;
|
|
66
97
|
this.network = new core_1.NodeFetchNetworkRequest({
|
|
@@ -68,37 +99,23 @@ class HttpDataSource extends repository_1.AbstractDataSource {
|
|
|
68
99
|
networkOptions: { baseUrl: settings.baseUrl },
|
|
69
100
|
});
|
|
70
101
|
}
|
|
71
|
-
/** Nothing to open. Holding no connection is what makes this one safe to construct anywhere. */
|
|
72
102
|
async configure() { }
|
|
73
|
-
/** No transactions over REST. The root probes capabilities rather than assuming them. */
|
|
74
103
|
getCapabilities() {
|
|
75
104
|
return { transactions: false };
|
|
76
105
|
}
|
|
77
|
-
/** Explicit token first, resolver only when there is none - a caller that supplied one is never overridden by a lookup. */
|
|
78
106
|
resolveAuthToken() {
|
|
79
107
|
return this.settings.authToken ?? this.settings.authTokenResolver?.();
|
|
80
108
|
}
|
|
81
|
-
/**
|
|
82
|
-
* Built through `Headers` rather than a plain object, so a caller's value genuinely OVERRIDES a
|
|
83
|
-
* default. Two spellings of one name in an object both survive the merge and `Headers` then
|
|
84
|
-
* APPENDS them - `x-request-count: "false, true"` - which parses as neither.
|
|
85
|
-
*/
|
|
86
109
|
buildHeaders(opts) {
|
|
87
110
|
const { token } = opts;
|
|
88
|
-
const headers = new Headers();
|
|
89
|
-
//
|
|
90
|
-
// one less shape to tell apart. Set FIRST so a caller can override it.
|
|
111
|
+
const headers = new Headers(this.configuredHeaders);
|
|
112
|
+
// Set last: under the envelope a record read answers `{ count, data }`.
|
|
91
113
|
headers.set(common_1.HTTP.Headers.REQUEST_COUNT_DATA, 'false');
|
|
92
|
-
const configured = [...new Headers(this.settings.headers).entries()];
|
|
93
|
-
for (const [name, value] of configured) {
|
|
94
|
-
headers.set(name, value);
|
|
95
|
-
}
|
|
96
114
|
if (!token) {
|
|
97
115
|
return headers;
|
|
98
116
|
}
|
|
99
117
|
headers.set(common_1.HTTP.Headers.AUTHORIZATION, `${token.type ?? 'Bearer'} ${token.value}`);
|
|
100
|
-
//
|
|
101
|
-
// server reads as a provider by that name.
|
|
118
|
+
// Unconditionally it would send the string "undefined".
|
|
102
119
|
if (token.provider) {
|
|
103
120
|
headers.set('x-auth-provider', token.provider);
|
|
104
121
|
}
|
|
@@ -106,8 +123,6 @@ class HttpDataSource extends repository_1.AbstractDataSource {
|
|
|
106
123
|
}
|
|
107
124
|
buildUrl(opts) {
|
|
108
125
|
const { paths, query } = opts;
|
|
109
|
-
// Path joining belongs to the network helper - it already normalises leading slashes and
|
|
110
|
-
// refuses an unset base url with a catalogued error.
|
|
111
126
|
const url = new URL(this.network.getRequestUrl({ paths }));
|
|
112
127
|
const parameters = Object.entries(query ?? {});
|
|
113
128
|
for (const [key, value] of parameters) {
|
|
@@ -118,23 +133,7 @@ class HttpDataSource extends repository_1.AbstractDataSource {
|
|
|
118
133
|
}
|
|
119
134
|
return url.toString();
|
|
120
135
|
}
|
|
121
|
-
/**
|
|
122
|
-
* One request, with the total read from `Content-Range` and REPORTED as absent when the header is
|
|
123
|
-
* not there.
|
|
124
|
-
*
|
|
125
|
-
* Goes through {@link HttpDataSource.request}, so auth, the 401 hook and the single retry live in
|
|
126
|
-
* ONE place - a second header-building path is where a guard gets forgotten.
|
|
127
|
-
*/
|
|
128
|
-
/**
|
|
129
|
-
* One request, answered RAW.
|
|
130
|
-
*
|
|
131
|
-
* `read` is about rows and cannot express a response that is not JSON - an export endpoint returns
|
|
132
|
-
* bytes and a filename. Rather than invent a blob shape on the repository, whose contract is rows,
|
|
133
|
-
* the transport stays reachable: a caller gets the `Response` and reads `.blob()` and
|
|
134
|
-
* `content-disposition` itself.
|
|
135
|
-
*
|
|
136
|
-
* Auth, the 401 hook and the single retry apply here exactly as they do to `read`.
|
|
137
|
-
*/
|
|
136
|
+
/** The raw `Response` - for what is not rows, like an export. Auth and the 401 retry apply. */
|
|
138
137
|
async request(opts) {
|
|
139
138
|
const url = this.buildUrl(opts);
|
|
140
139
|
const send = () => this.network.getNetworkService().send({
|
|
@@ -151,20 +150,23 @@ class HttpDataSource extends repository_1.AbstractDataSource {
|
|
|
151
150
|
}
|
|
152
151
|
return response;
|
|
153
152
|
}
|
|
153
|
+
/** Rows plus the total from `Content-Range`, reported absent when the header is. */
|
|
154
154
|
async read(opts) {
|
|
155
155
|
const response = await this.request(opts);
|
|
156
156
|
if (!response.ok) {
|
|
157
157
|
throw (0, core_2.getError)({
|
|
158
158
|
statusCode: response.status,
|
|
159
|
-
message: `[${this.name}][read] ${response.status} | ${this.buildUrl(opts)}`,
|
|
159
|
+
message: `[${this.name}][read] ${response.status} | ${describeUrl({ url: this.buildUrl(opts), status: response.status })}`,
|
|
160
160
|
});
|
|
161
161
|
}
|
|
162
162
|
const body = await response.json();
|
|
163
|
-
const
|
|
164
|
-
const
|
|
163
|
+
const contentRange = response.headers.get(common_1.HTTP.Headers.CONTENT_RANGE) ?? undefined;
|
|
164
|
+
const range = readContentRange({ header: contentRange ?? null });
|
|
165
|
+
const data = unwrapBody({ body, shape: opts.shape ?? 'list', url: this.buildUrl(opts) });
|
|
165
166
|
return {
|
|
166
167
|
data,
|
|
167
168
|
hasRange: range !== undefined,
|
|
169
|
+
contentRange,
|
|
168
170
|
total: range?.total,
|
|
169
171
|
skip: range?.skip,
|
|
170
172
|
dataLength: Array.isArray(data) ? data.length : 1,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datasource.js","sourceRoot":"","sources":["../../../src/http/datasource.ts"],"names":[],"mappings":";;;AAAA,iEAAsE;AACtE,0DAAqD;AACrD,sDAAsE;AACtE,sDAAuD;
|
|
1
|
+
{"version":3,"file":"datasource.js","sourceRoot":"","sources":["../../../src/http/datasource.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,27 +2,18 @@ import { AbstractEntity } from '@venizia/ignis-kernel/repository';
|
|
|
2
2
|
import type { IReadableRepository, TCount, TDataWithRange, TFilter, TSchemaType, TWhere } from '@venizia/ignis-kernel/repository';
|
|
3
3
|
import type { AnyType } from '@venizia/ignis-helpers/common';
|
|
4
4
|
import type { HttpDataSource } from './datasource';
|
|
5
|
-
/**
|
|
5
|
+
/** A remote resource has a name but no local schema. */
|
|
6
6
|
export declare class HttpResourceEntity extends AbstractEntity {
|
|
7
7
|
getSchema<T = unknown>(_opts: {
|
|
8
8
|
type: TSchemaType;
|
|
9
9
|
}): T;
|
|
10
10
|
}
|
|
11
|
-
/**
|
|
12
|
-
* Read access to one remote resource, through {@link HttpDataSource}.
|
|
13
|
-
*
|
|
14
|
-
* `IReadableRepository` rather than `AbstractRepository`: the abstract class demands twelve members,
|
|
15
|
-
* so a resource that cannot be written would have to stub `create`, `updateById` and `deleteById`
|
|
16
|
-
* with throws. Five real methods say more than twelve where seven are lies.
|
|
17
|
-
*
|
|
18
|
-
* Every query leaves as the `@venizia/ignis-filter` vocabulary - the same language an IGNIS
|
|
19
|
-
* repository speaks to Drizzle. One query language, two transports.
|
|
20
|
-
*/
|
|
11
|
+
/** Read access to one remote resource, in the `@venizia/ignis-filter` vocabulary. */
|
|
21
12
|
export declare class HttpRepository<E extends object = AnyType> implements IReadableRepository<E, {}> {
|
|
22
13
|
dataSource: HttpDataSource;
|
|
23
14
|
entity: AbstractEntity;
|
|
24
15
|
protected resource: string;
|
|
25
|
-
/**
|
|
16
|
+
/** A count route, if the API has one. Absent, the total comes from `Content-Range`. */
|
|
26
17
|
protected countPath?: string;
|
|
27
18
|
constructor(opts: {
|
|
28
19
|
dataSource: HttpDataSource;
|
|
@@ -30,17 +21,13 @@ export declare class HttpRepository<E extends object = AnyType> implements IRead
|
|
|
30
21
|
countPath?: string;
|
|
31
22
|
});
|
|
32
23
|
getEntity(): AbstractEntity;
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
*
|
|
41
|
-
* With no header there is NO total, and this says so rather than answering with the page size - a
|
|
42
|
-
* count of 1 for a table of 7000 reads as healthy in every screen that consumes it.
|
|
43
|
-
*/
|
|
24
|
+
/** No header and an unreadable one (`/*`) have different fixes, so different messages. */
|
|
25
|
+
protected getMissingTotalError(opts: {
|
|
26
|
+
method: string;
|
|
27
|
+
contentRange?: string;
|
|
28
|
+
noHeader: string;
|
|
29
|
+
}): import("@venizia/ignis-helpers/core").ApplicationError;
|
|
30
|
+
/** From `Content-Range`, or `countPath`. No total throws rather than reporting the page size. */
|
|
44
31
|
count(opts: {
|
|
45
32
|
where: TWhere<E>;
|
|
46
33
|
options?: {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../../src/http/repository.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../../src/http/repository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAkB,MAAM,kCAAkC,CAAC;AAClF,OAAO,KAAK,EACV,mBAAmB,EACnB,MAAM,EACN,cAAc,EACd,OAAO,EACP,WAAW,EACX,MAAM,EACP,MAAM,kCAAkC,CAAC;AAE1C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,wDAAwD;AACxD,qBAAa,kBAAmB,SAAQ,cAAc;IACpD,SAAS,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE;QAAE,IAAI,EAAE,WAAW,CAAA;KAAE,GAAG,CAAC;CAGxD;AAED,qFAAqF;AACrF,qBAAa,cAAc,CAAC,CAAC,SAAS,MAAM,GAAG,OAAO,CAAE,YAAW,mBAAmB,CAAC,CAAC,EAAE,EAAE,CAAC;IAC3F,UAAU,EAAE,cAAc,CAAC;IAC3B,MAAM,EAAE,cAAc,CAAC;IAEvB,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC3B,uFAAuF;IACvF,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;gBAEjB,IAAI,EAAE;QAAE,UAAU,EAAE,cAAc,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;IAOtF,SAAS,IAAI,cAAc;IAI3B,0FAA0F;IAC1F,SAAS,CAAC,oBAAoB,CAAC,IAAI,EAAE;QACnC,MAAM,EAAE,MAAM,CAAC;QACf,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,QAAQ,EAAE,MAAM,CAAC;KAClB;IAYD,iGAAiG;IAC3F,KAAK,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QAAC,OAAO,CAAC,EAAE,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAmChE,UAAU,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QAAC,OAAO,CAAC,EAAE,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAStE,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QACtB,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QACnB,OAAO,EAAE;YAAE,gBAAgB,EAAE,IAAI,CAAA;SAAE,CAAC;KACrC,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IACxB,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QAAC,OAAO,CAAC,EAAE,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAoC3E,OAAO,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QAAC,OAAO,CAAC,EAAE,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAK9E,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAC1B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QACpB,OAAO,CAAC,EAAE,EAAE,CAAC;KACd,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;CAStB"}
|