@clipboard-health/json-api-nestjs 0.12.3 → 0.13.1

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 CHANGED
@@ -25,6 +25,7 @@ Create Zod schemas for your API's queries:
25
25
  ```ts
26
26
  // ../example-nestjs/examples/query.ts
27
27
 
28
+ // packages/json-api-nestjs/src/lib/query/cursorPaginationQuery.ts,packages/json-api-nestjs/src/lib/query/fieldsQuery.ts,packages/json-api-nestjs/src/lib/query/filterQuery.ts,packages/json-api-nestjs/src/lib/query/includeQuery.ts,packages/json-api-nestjs/src/lib/query/sortQuery.ts
28
29
  import { booleanString } from "@clipboard-health/contract-core";
29
30
  import {
30
31
  cursorPaginationQuery,
@@ -63,14 +64,6 @@ const userFilterMap = {
63
64
  },
64
65
  } as const satisfies FilterMap<UserAttributeFields>;
65
66
 
66
- /**
67
- * Disclaimer: Just because JSON:API supports robust querying doesn’t mean your service should
68
- * implement them as they may require database indexes, which have a cost. **Implement only access
69
- * patterns required by clients.**
70
- *
71
- * The spec says that if clients provide fields the server doesn’t support, it **MUST** return 400
72
- * Bad Request, hence the `.strict()`.
73
- */
74
67
  export const query = z
75
68
  .object({
76
69
  ...cursorPaginationQuery(),
package/package.json CHANGED
@@ -1,22 +1,36 @@
1
1
  {
2
2
  "name": "@clipboard-health/json-api-nestjs",
3
3
  "description": "TypeScript-friendly utilities for adhering to the JSON:API specification with NestJS.",
4
- "version": "0.12.3",
4
+ "version": "0.13.1",
5
+ "bugs": "https://github.com/ClipboardHealth/core-utils/issues",
5
6
  "dependencies": {
6
7
  "@clipboard-health/contract-core": "0.3.0",
7
8
  "tslib": "2.8.0",
8
- "type-fest": "4.26.1",
9
+ "type-fest": "4.27.0",
9
10
  "zod": "3.23.8"
10
11
  },
11
12
  "devDependencies": {
12
- "@clipboard-health/testing-core": "0.8.3"
13
+ "@clipboard-health/testing-core": "0.9.1"
13
14
  },
14
- "keywords": [],
15
+ "keywords": [
16
+ "api",
17
+ "json-api",
18
+ "json:api",
19
+ "jsonapi",
20
+ "nestjs",
21
+ "rest",
22
+ "typescript"
23
+ ],
15
24
  "license": "MIT",
16
25
  "main": "./src/index.js",
17
26
  "publishConfig": {
18
27
  "access": "public"
19
28
  },
29
+ "repository": {
30
+ "directory": "packages/json-api-nestjs",
31
+ "type": "git",
32
+ "url": "git+https://github.com/ClipboardHealth/core-utils.git"
33
+ },
20
34
  "scripts": {
21
35
  "embed": "embedme README.md"
22
36
  },
@@ -8,9 +8,59 @@ export declare const PAGINATION: {
8
8
  /**
9
9
  * Creates a Zod schema for JSON:API cursor pagination.
10
10
  *
11
- * @includeExample ./packages/example-nestjs/examples/query.ts
11
+ * @example
12
+ * ```ts
13
+ * // packages/example-nestjs/examples/query.ts
14
+ * import { booleanString } from "@clipboard-health/contract-core";
15
+ * import {
16
+ * cursorPaginationQuery,
17
+ * fieldsQuery,
18
+ * type FilterMap,
19
+ * filterQuery,
20
+ * includeQuery,
21
+ * sortQuery,
22
+ * } from "@clipboard-health/json-api-nestjs";
23
+ * import { z } from "zod";
24
+ *
25
+ * import {
26
+ * type ArticleAttributeFields,
27
+ * type UserAttributeFields,
28
+ * type UserIncludeFields,
29
+ * } from "../src/contract";
30
+ *
31
+ * const articleFields = ["title"] as const satisfies readonly ArticleAttributeFields[];
32
+ * const userFields = ["age", "dateOfBirth"] as const satisfies readonly UserAttributeFields[];
33
+ * const userIncludeFields = [
34
+ * "articles",
35
+ * "articles.comments",
36
+ * ] as const satisfies readonly UserIncludeFields[];
37
+ * const userFilterMap = {
38
+ * age: {
39
+ * filters: ["eq", "gt"],
40
+ * schema: z.coerce.number().int().positive().max(125),
41
+ * },
42
+ * dateOfBirth: {
43
+ * filters: ["gte"],
44
+ * schema: z.coerce.date().min(new Date("1900-01-01")).max(new Date()),
45
+ * },
46
+ * isActive: {
47
+ * filters: ["eq"],
48
+ * schema: booleanString,
49
+ * },
50
+ * } as const satisfies FilterMap<UserAttributeFields>;
51
+ *
52
+ * export const query = z
53
+ * .object({
54
+ * ...cursorPaginationQuery(),
55
+ * ...fieldsQuery({ article: articleFields, user: userFields }),
56
+ * ...filterQuery(userFilterMap),
57
+ * ...sortQuery(userFields),
58
+ * ...includeQuery(userIncludeFields),
59
+ * })
60
+ * .strict();
61
+ *
62
+ * ```
12
63
  *
13
- * @see [Usage example](../../../../example-nestjs/examples/query.ts)
14
64
  * @see {@link https://jsonapi.org/format/#fetching-pagination JSON:API pagination}
15
65
  * @see {@link https://jsonapi.org/examples/#pagination JSON:API pagination examples}
16
66
  */
@@ -13,9 +13,59 @@ exports.PAGINATION = {
13
13
  /**
14
14
  * Creates a Zod schema for JSON:API cursor pagination.
15
15
  *
16
- * @includeExample ./packages/example-nestjs/examples/query.ts
16
+ * @example
17
+ * ```ts
18
+ * // packages/example-nestjs/examples/query.ts
19
+ * import { booleanString } from "@clipboard-health/contract-core";
20
+ * import {
21
+ * cursorPaginationQuery,
22
+ * fieldsQuery,
23
+ * type FilterMap,
24
+ * filterQuery,
25
+ * includeQuery,
26
+ * sortQuery,
27
+ * } from "@clipboard-health/json-api-nestjs";
28
+ * import { z } from "zod";
29
+ *
30
+ * import {
31
+ * type ArticleAttributeFields,
32
+ * type UserAttributeFields,
33
+ * type UserIncludeFields,
34
+ * } from "../src/contract";
35
+ *
36
+ * const articleFields = ["title"] as const satisfies readonly ArticleAttributeFields[];
37
+ * const userFields = ["age", "dateOfBirth"] as const satisfies readonly UserAttributeFields[];
38
+ * const userIncludeFields = [
39
+ * "articles",
40
+ * "articles.comments",
41
+ * ] as const satisfies readonly UserIncludeFields[];
42
+ * const userFilterMap = {
43
+ * age: {
44
+ * filters: ["eq", "gt"],
45
+ * schema: z.coerce.number().int().positive().max(125),
46
+ * },
47
+ * dateOfBirth: {
48
+ * filters: ["gte"],
49
+ * schema: z.coerce.date().min(new Date("1900-01-01")).max(new Date()),
50
+ * },
51
+ * isActive: {
52
+ * filters: ["eq"],
53
+ * schema: booleanString,
54
+ * },
55
+ * } as const satisfies FilterMap<UserAttributeFields>;
56
+ *
57
+ * export const query = z
58
+ * .object({
59
+ * ...cursorPaginationQuery(),
60
+ * ...fieldsQuery({ article: articleFields, user: userFields }),
61
+ * ...filterQuery(userFilterMap),
62
+ * ...sortQuery(userFields),
63
+ * ...includeQuery(userIncludeFields),
64
+ * })
65
+ * .strict();
66
+ *
67
+ * ```
17
68
  *
18
- * @see [Usage example](../../../../example-nestjs/examples/query.ts)
19
69
  * @see {@link https://jsonapi.org/format/#fetching-pagination JSON:API pagination}
20
70
  * @see {@link https://jsonapi.org/examples/#pagination JSON:API pagination examples}
21
71
  */
@@ -1 +1 @@
1
- {"version":3,"file":"cursorPaginationQuery.js","sourceRoot":"","sources":["../../../../../../packages/json-api-nestjs/src/lib/query/cursorPaginationQuery.ts"],"names":[],"mappings":";;;AAmBA,sDAeC;AAlCD,mEAAiE;AACjE,6BAAwB;AAEX,QAAA,UAAU,GAAG;IACxB,IAAI,EAAE;QACJ,OAAO,EAAE,EAAE;QACX,OAAO,EAAE,GAAG;KACb;CACO,CAAC;AAEX;;;;;;;;GAQG;AACH,SAAgB,qBAAqB,CACnC,UAAuE;IAEvE,MAAM,EAAE,IAAI,EAAE,GAAG,kBAAU,CAAC;IAC5B,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC;IAE/F,OAAO;QACL,IAAI,EAAE,OAAC;aACJ,MAAM,CAAC;YACN,MAAM,EAAE,8BAAc,CAAC,QAAQ,EAAE;YACjC,IAAI,EAAE,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;SAC3E,CAAC;aACD,MAAM,EAAE;aACR,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;KAClC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"cursorPaginationQuery.js","sourceRoot":"","sources":["../../../../../../packages/json-api-nestjs/src/lib/query/cursorPaginationQuery.ts"],"names":[],"mappings":";;;AAqEA,sDAeC;AApFD,mEAAiE;AACjE,6BAAwB;AAEX,QAAA,UAAU,GAAG;IACxB,IAAI,EAAE;QACJ,OAAO,EAAE,EAAE;QACX,OAAO,EAAE,GAAG;KACb;CACO,CAAC;AAEX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,SAAgB,qBAAqB,CACnC,UAAuE;IAEvE,MAAM,EAAE,IAAI,EAAE,GAAG,kBAAU,CAAC;IAC5B,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC;IAE/F,OAAO;QACL,IAAI,EAAE,OAAC;aACJ,MAAM,CAAC;YACN,MAAM,EAAE,8BAAc,CAAC,QAAQ,EAAE;YACjC,IAAI,EAAE,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;SAC3E,CAAC;aACD,MAAM,EAAE;aACR,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;KAClC,CAAC;AACJ,CAAC"}
@@ -13,9 +13,59 @@ export type AttributeFields<DocumentT extends JsonApiDocument> = DocumentT["data
13
13
  /**
14
14
  * Creates a Zod schema for JSON:API sparse fieldsets.
15
15
  *
16
- * @includeExample ./packages/example-nestjs/examples/query.ts
16
+ * @example
17
+ * ```ts
18
+ * // packages/example-nestjs/examples/query.ts
19
+ * import { booleanString } from "@clipboard-health/contract-core";
20
+ * import {
21
+ * cursorPaginationQuery,
22
+ * fieldsQuery,
23
+ * type FilterMap,
24
+ * filterQuery,
25
+ * includeQuery,
26
+ * sortQuery,
27
+ * } from "@clipboard-health/json-api-nestjs";
28
+ * import { z } from "zod";
29
+ *
30
+ * import {
31
+ * type ArticleAttributeFields,
32
+ * type UserAttributeFields,
33
+ * type UserIncludeFields,
34
+ * } from "../src/contract";
35
+ *
36
+ * const articleFields = ["title"] as const satisfies readonly ArticleAttributeFields[];
37
+ * const userFields = ["age", "dateOfBirth"] as const satisfies readonly UserAttributeFields[];
38
+ * const userIncludeFields = [
39
+ * "articles",
40
+ * "articles.comments",
41
+ * ] as const satisfies readonly UserIncludeFields[];
42
+ * const userFilterMap = {
43
+ * age: {
44
+ * filters: ["eq", "gt"],
45
+ * schema: z.coerce.number().int().positive().max(125),
46
+ * },
47
+ * dateOfBirth: {
48
+ * filters: ["gte"],
49
+ * schema: z.coerce.date().min(new Date("1900-01-01")).max(new Date()),
50
+ * },
51
+ * isActive: {
52
+ * filters: ["eq"],
53
+ * schema: booleanString,
54
+ * },
55
+ * } as const satisfies FilterMap<UserAttributeFields>;
56
+ *
57
+ * export const query = z
58
+ * .object({
59
+ * ...cursorPaginationQuery(),
60
+ * ...fieldsQuery({ article: articleFields, user: userFields }),
61
+ * ...filterQuery(userFilterMap),
62
+ * ...sortQuery(userFields),
63
+ * ...includeQuery(userIncludeFields),
64
+ * })
65
+ * .strict();
66
+ *
67
+ * ```
17
68
  *
18
- * @see [Usage example](../../../../example-nestjs/examples/query.ts)
19
69
  * @see {@link https://jsonapi.org/format/#fetching-sparse-fieldsets JSON:API sparse fieldsets}
20
70
  */
21
71
  export declare function fieldsQuery<const MapT extends FieldsMap>(parameters: Readonly<MapT>): {
@@ -6,9 +6,59 @@ const splitString_1 = require("../internal/splitString");
6
6
  /**
7
7
  * Creates a Zod schema for JSON:API sparse fieldsets.
8
8
  *
9
- * @includeExample ./packages/example-nestjs/examples/query.ts
9
+ * @example
10
+ * ```ts
11
+ * // packages/example-nestjs/examples/query.ts
12
+ * import { booleanString } from "@clipboard-health/contract-core";
13
+ * import {
14
+ * cursorPaginationQuery,
15
+ * fieldsQuery,
16
+ * type FilterMap,
17
+ * filterQuery,
18
+ * includeQuery,
19
+ * sortQuery,
20
+ * } from "@clipboard-health/json-api-nestjs";
21
+ * import { z } from "zod";
22
+ *
23
+ * import {
24
+ * type ArticleAttributeFields,
25
+ * type UserAttributeFields,
26
+ * type UserIncludeFields,
27
+ * } from "../src/contract";
28
+ *
29
+ * const articleFields = ["title"] as const satisfies readonly ArticleAttributeFields[];
30
+ * const userFields = ["age", "dateOfBirth"] as const satisfies readonly UserAttributeFields[];
31
+ * const userIncludeFields = [
32
+ * "articles",
33
+ * "articles.comments",
34
+ * ] as const satisfies readonly UserIncludeFields[];
35
+ * const userFilterMap = {
36
+ * age: {
37
+ * filters: ["eq", "gt"],
38
+ * schema: z.coerce.number().int().positive().max(125),
39
+ * },
40
+ * dateOfBirth: {
41
+ * filters: ["gte"],
42
+ * schema: z.coerce.date().min(new Date("1900-01-01")).max(new Date()),
43
+ * },
44
+ * isActive: {
45
+ * filters: ["eq"],
46
+ * schema: booleanString,
47
+ * },
48
+ * } as const satisfies FilterMap<UserAttributeFields>;
49
+ *
50
+ * export const query = z
51
+ * .object({
52
+ * ...cursorPaginationQuery(),
53
+ * ...fieldsQuery({ article: articleFields, user: userFields }),
54
+ * ...filterQuery(userFilterMap),
55
+ * ...sortQuery(userFields),
56
+ * ...includeQuery(userIncludeFields),
57
+ * })
58
+ * .strict();
59
+ *
60
+ * ```
10
61
  *
11
- * @see [Usage example](../../../../example-nestjs/examples/query.ts)
12
62
  * @see {@link https://jsonapi.org/format/#fetching-sparse-fieldsets JSON:API sparse fieldsets}
13
63
  */
14
64
  function fieldsQuery(parameters) {
@@ -1 +1 @@
1
- {"version":3,"file":"fieldsQuery.js","sourceRoot":"","sources":["../../../../../../packages/json-api-nestjs/src/lib/query/fieldsQuery.ts"],"names":[],"mappings":";;AAmCA,kCAYC;AA/CD,6BAAwB;AAExB,yDAAsD;AAyBtD;;;;;;;GAOG;AACH,SAAgB,WAAW,CAA+B,UAA0B;IAClF,MAAM,YAAY,GAAG,MAAM,CAAC,WAAW,CACrC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,CAAiC,EAAE,EAAE,CAAC;QACpF,OAAO;QACP,OAAC,CAAC,UAAU,CAAC,yBAAW,EAAE,OAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;KAC7E,CAAC,CAEmB,CAAC;IAExB,OAAO;QACL,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KACnD,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"fieldsQuery.js","sourceRoot":"","sources":["../../../../../../packages/json-api-nestjs/src/lib/query/fieldsQuery.ts"],"names":[],"mappings":";;AAqFA,kCAYC;AAjGD,6BAAwB;AAExB,yDAAsD;AAyBtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,SAAgB,WAAW,CAA+B,UAA0B;IAClF,MAAM,YAAY,GAAG,MAAM,CAAC,WAAW,CACrC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,CAAiC,EAAE,EAAE,CAAC;QACpF,OAAO;QACP,OAAC,CAAC,UAAU,CAAC,yBAAW,EAAE,OAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;KAC7E,CAAC,CAEmB,CAAC;IAExB,OAAO;QACL,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KACnD,CAAC;AACJ,CAAC"}
@@ -6,7 +6,7 @@ export interface FilterValue {
6
6
  filters: FilterTuple;
7
7
  schema: z.ZodTypeAny;
8
8
  }
9
- type InternalFilterMap<FieldT extends Field = Field> = Record<FieldT, FilterValue>;
9
+ export type InternalFilterMap<FieldT extends Field = Field> = Record<FieldT, FilterValue>;
10
10
  export type FilterMap<FieldT extends Field = Field> = Partial<InternalFilterMap<FieldT>>;
11
11
  export type FilterSchema<MapT extends InternalFilterMap> = {
12
12
  [K in keyof MapT]: z.ZodOptional<z.ZodEffects<z.ZodOptional<z.ZodObject<{
@@ -16,13 +16,62 @@ export type FilterSchema<MapT extends InternalFilterMap> = {
16
16
  /**
17
17
  * Creates a Zod schema for JSON:API filters.
18
18
  *
19
- * @includeExample ./packages/example-nestjs/examples/query.ts
19
+ * @example
20
+ * ```ts
21
+ * // packages/example-nestjs/examples/query.ts
22
+ * import { booleanString } from "@clipboard-health/contract-core";
23
+ * import {
24
+ * cursorPaginationQuery,
25
+ * fieldsQuery,
26
+ * type FilterMap,
27
+ * filterQuery,
28
+ * includeQuery,
29
+ * sortQuery,
30
+ * } from "@clipboard-health/json-api-nestjs";
31
+ * import { z } from "zod";
32
+ *
33
+ * import {
34
+ * type ArticleAttributeFields,
35
+ * type UserAttributeFields,
36
+ * type UserIncludeFields,
37
+ * } from "../src/contract";
38
+ *
39
+ * const articleFields = ["title"] as const satisfies readonly ArticleAttributeFields[];
40
+ * const userFields = ["age", "dateOfBirth"] as const satisfies readonly UserAttributeFields[];
41
+ * const userIncludeFields = [
42
+ * "articles",
43
+ * "articles.comments",
44
+ * ] as const satisfies readonly UserIncludeFields[];
45
+ * const userFilterMap = {
46
+ * age: {
47
+ * filters: ["eq", "gt"],
48
+ * schema: z.coerce.number().int().positive().max(125),
49
+ * },
50
+ * dateOfBirth: {
51
+ * filters: ["gte"],
52
+ * schema: z.coerce.date().min(new Date("1900-01-01")).max(new Date()),
53
+ * },
54
+ * isActive: {
55
+ * filters: ["eq"],
56
+ * schema: booleanString,
57
+ * },
58
+ * } as const satisfies FilterMap<UserAttributeFields>;
59
+ *
60
+ * export const query = z
61
+ * .object({
62
+ * ...cursorPaginationQuery(),
63
+ * ...fieldsQuery({ article: articleFields, user: userFields }),
64
+ * ...filterQuery(userFilterMap),
65
+ * ...sortQuery(userFields),
66
+ * ...includeQuery(userIncludeFields),
67
+ * })
68
+ * .strict();
69
+ *
70
+ * ```
20
71
  *
21
- * @see [Usage example](../../../../example-nestjs/examples/query.ts)
22
72
  * @see {@link https://jsonapi.org/recommendations/#filtering JSON:API filtering}
23
73
  * @see {@link https://discuss.jsonapi.org/t/share-propose-a-filtering-strategy/257 JSON:API filtering strategy}
24
74
  */
25
75
  export declare function filterQuery<const MapT extends InternalFilterMap>(parameters: Readonly<MapT>): {
26
76
  filter: z.ZodOptional<z.ZodObject<FilterSchema<MapT>, "strict", z.ZodTypeAny, z.objectUtil.addQuestionMarks<z.baseObjectOutputType<FilterSchema<MapT>>, any> extends infer T ? { [k in keyof T]: z.objectUtil.addQuestionMarks<z.baseObjectOutputType<FilterSchema<MapT>>, any>[k]; } : never, z.baseObjectInputType<FilterSchema<MapT>> extends infer T_1 ? { [k_1 in keyof T_1]: z.baseObjectInputType<FilterSchema<MapT>>[k_1]; } : never>>;
27
77
  };
28
- export {};
@@ -7,9 +7,59 @@ const splitString_1 = require("../internal/splitString");
7
7
  /**
8
8
  * Creates a Zod schema for JSON:API filters.
9
9
  *
10
- * @includeExample ./packages/example-nestjs/examples/query.ts
10
+ * @example
11
+ * ```ts
12
+ * // packages/example-nestjs/examples/query.ts
13
+ * import { booleanString } from "@clipboard-health/contract-core";
14
+ * import {
15
+ * cursorPaginationQuery,
16
+ * fieldsQuery,
17
+ * type FilterMap,
18
+ * filterQuery,
19
+ * includeQuery,
20
+ * sortQuery,
21
+ * } from "@clipboard-health/json-api-nestjs";
22
+ * import { z } from "zod";
23
+ *
24
+ * import {
25
+ * type ArticleAttributeFields,
26
+ * type UserAttributeFields,
27
+ * type UserIncludeFields,
28
+ * } from "../src/contract";
29
+ *
30
+ * const articleFields = ["title"] as const satisfies readonly ArticleAttributeFields[];
31
+ * const userFields = ["age", "dateOfBirth"] as const satisfies readonly UserAttributeFields[];
32
+ * const userIncludeFields = [
33
+ * "articles",
34
+ * "articles.comments",
35
+ * ] as const satisfies readonly UserIncludeFields[];
36
+ * const userFilterMap = {
37
+ * age: {
38
+ * filters: ["eq", "gt"],
39
+ * schema: z.coerce.number().int().positive().max(125),
40
+ * },
41
+ * dateOfBirth: {
42
+ * filters: ["gte"],
43
+ * schema: z.coerce.date().min(new Date("1900-01-01")).max(new Date()),
44
+ * },
45
+ * isActive: {
46
+ * filters: ["eq"],
47
+ * schema: booleanString,
48
+ * },
49
+ * } as const satisfies FilterMap<UserAttributeFields>;
50
+ *
51
+ * export const query = z
52
+ * .object({
53
+ * ...cursorPaginationQuery(),
54
+ * ...fieldsQuery({ article: articleFields, user: userFields }),
55
+ * ...filterQuery(userFilterMap),
56
+ * ...sortQuery(userFields),
57
+ * ...includeQuery(userIncludeFields),
58
+ * })
59
+ * .strict();
60
+ *
61
+ * ```
11
62
  *
12
- * @see [Usage example](../../../../example-nestjs/examples/query.ts)
13
63
  * @see {@link https://jsonapi.org/recommendations/#filtering JSON:API filtering}
14
64
  * @see {@link https://discuss.jsonapi.org/t/share-propose-a-filtering-strategy/257 JSON:API filtering strategy}
15
65
  */
@@ -1 +1 @@
1
- {"version":3,"file":"filterQuery.js","sourceRoot":"","sources":["../../../../../../packages/json-api-nestjs/src/lib/query/filterQuery.ts"],"names":[],"mappings":";;AA0CA,kCAcC;AAxDD,6BAAwB;AAExB,iFAA8E;AAC9E,yDAAsD;AA8BtD;;;;;;;;GAQG;AACH,SAAgB,WAAW,CAAuC,UAA0B;IAC1F,OAAO;QACL,MAAM,EAAE,OAAC;aACN,MAAM,CACL,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,CAAiC,EAAE,EAAE,CAAC;YACnF,OAAO;YACP,OAAC,CAAC,UAAU,CAAC,iDAAuB,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE;SACtE,CAAC,CACmB,CACxB;aACA,MAAM,EAAE;aACR,QAAQ,EAAE;KACd,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,UAAuB;IAC3C,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC;IAEvC,OAAO,OAAC;SACL,MAAM,CACL,MAAM,CAAC,WAAW,CAChB,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;QACtB,MAAM;QACN,OAAC,CAAC,UAAU,CAAC,yBAAW,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE;KACnF,CAAC,CACH,CACF;SACA,MAAM,EAAE;SACR,QAAQ,EAAE,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"filterQuery.js","sourceRoot":"","sources":["../../../../../../packages/json-api-nestjs/src/lib/query/filterQuery.ts"],"names":[],"mappings":";;AA4FA,kCAcC;AA1GD,6BAAwB;AAExB,iFAA8E;AAC9E,yDAAsD;AA8BtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,SAAgB,WAAW,CAAuC,UAA0B;IAC1F,OAAO;QACL,MAAM,EAAE,OAAC;aACN,MAAM,CACL,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,CAAiC,EAAE,EAAE,CAAC;YACnF,OAAO;YACP,OAAC,CAAC,UAAU,CAAC,iDAAuB,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE;SACtE,CAAC,CACmB,CACxB;aACA,MAAM,EAAE;aACR,QAAQ,EAAE;KACd,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,UAAuB;IAC3C,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC;IAEvC,OAAO,OAAC;SACL,MAAM,CACL,MAAM,CAAC,WAAW,CAChB,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;QACtB,MAAM;QACN,OAAC,CAAC,UAAU,CAAC,yBAAW,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE;KACnF,CAAC,CACH,CACF;SACA,MAAM,EAAE;SACR,QAAQ,EAAE,CAAC;AAChB,CAAC"}
@@ -23,9 +23,59 @@ export type RelationshipPaths<MapT extends Record<string, z.ZodTypeAny>, Documen
23
23
  /**
24
24
  * Creates a Zod schema for JSON:API include parameters.
25
25
  *
26
- * @includeExample ./packages/example-nestjs/examples/query.ts
26
+ * @example
27
+ * ```ts
28
+ * // packages/example-nestjs/examples/query.ts
29
+ * import { booleanString } from "@clipboard-health/contract-core";
30
+ * import {
31
+ * cursorPaginationQuery,
32
+ * fieldsQuery,
33
+ * type FilterMap,
34
+ * filterQuery,
35
+ * includeQuery,
36
+ * sortQuery,
37
+ * } from "@clipboard-health/json-api-nestjs";
38
+ * import { z } from "zod";
39
+ *
40
+ * import {
41
+ * type ArticleAttributeFields,
42
+ * type UserAttributeFields,
43
+ * type UserIncludeFields,
44
+ * } from "../src/contract";
45
+ *
46
+ * const articleFields = ["title"] as const satisfies readonly ArticleAttributeFields[];
47
+ * const userFields = ["age", "dateOfBirth"] as const satisfies readonly UserAttributeFields[];
48
+ * const userIncludeFields = [
49
+ * "articles",
50
+ * "articles.comments",
51
+ * ] as const satisfies readonly UserIncludeFields[];
52
+ * const userFilterMap = {
53
+ * age: {
54
+ * filters: ["eq", "gt"],
55
+ * schema: z.coerce.number().int().positive().max(125),
56
+ * },
57
+ * dateOfBirth: {
58
+ * filters: ["gte"],
59
+ * schema: z.coerce.date().min(new Date("1900-01-01")).max(new Date()),
60
+ * },
61
+ * isActive: {
62
+ * filters: ["eq"],
63
+ * schema: booleanString,
64
+ * },
65
+ * } as const satisfies FilterMap<UserAttributeFields>;
66
+ *
67
+ * export const query = z
68
+ * .object({
69
+ * ...cursorPaginationQuery(),
70
+ * ...fieldsQuery({ article: articleFields, user: userFields }),
71
+ * ...filterQuery(userFilterMap),
72
+ * ...sortQuery(userFields),
73
+ * ...includeQuery(userIncludeFields),
74
+ * })
75
+ * .strict();
76
+ *
77
+ * ```
27
78
  *
28
- * @see [Usage example](../../../../example-nestjs/examples/query.ts)
29
79
  * @see {@link https://jsonapi.org/format/#fetching-includes JSON:API includes}
30
80
  */
31
81
  export declare function includeQuery<const FieldT extends readonly string[]>(fields: FieldT): {
@@ -6,9 +6,59 @@ const splitString_1 = require("../internal/splitString");
6
6
  /**
7
7
  * Creates a Zod schema for JSON:API include parameters.
8
8
  *
9
- * @includeExample ./packages/example-nestjs/examples/query.ts
9
+ * @example
10
+ * ```ts
11
+ * // packages/example-nestjs/examples/query.ts
12
+ * import { booleanString } from "@clipboard-health/contract-core";
13
+ * import {
14
+ * cursorPaginationQuery,
15
+ * fieldsQuery,
16
+ * type FilterMap,
17
+ * filterQuery,
18
+ * includeQuery,
19
+ * sortQuery,
20
+ * } from "@clipboard-health/json-api-nestjs";
21
+ * import { z } from "zod";
22
+ *
23
+ * import {
24
+ * type ArticleAttributeFields,
25
+ * type UserAttributeFields,
26
+ * type UserIncludeFields,
27
+ * } from "../src/contract";
28
+ *
29
+ * const articleFields = ["title"] as const satisfies readonly ArticleAttributeFields[];
30
+ * const userFields = ["age", "dateOfBirth"] as const satisfies readonly UserAttributeFields[];
31
+ * const userIncludeFields = [
32
+ * "articles",
33
+ * "articles.comments",
34
+ * ] as const satisfies readonly UserIncludeFields[];
35
+ * const userFilterMap = {
36
+ * age: {
37
+ * filters: ["eq", "gt"],
38
+ * schema: z.coerce.number().int().positive().max(125),
39
+ * },
40
+ * dateOfBirth: {
41
+ * filters: ["gte"],
42
+ * schema: z.coerce.date().min(new Date("1900-01-01")).max(new Date()),
43
+ * },
44
+ * isActive: {
45
+ * filters: ["eq"],
46
+ * schema: booleanString,
47
+ * },
48
+ * } as const satisfies FilterMap<UserAttributeFields>;
49
+ *
50
+ * export const query = z
51
+ * .object({
52
+ * ...cursorPaginationQuery(),
53
+ * ...fieldsQuery({ article: articleFields, user: userFields }),
54
+ * ...filterQuery(userFilterMap),
55
+ * ...sortQuery(userFields),
56
+ * ...includeQuery(userIncludeFields),
57
+ * })
58
+ * .strict();
59
+ *
60
+ * ```
10
61
  *
11
- * @see [Usage example](../../../../example-nestjs/examples/query.ts)
12
62
  * @see {@link https://jsonapi.org/format/#fetching-includes JSON:API includes}
13
63
  */
14
64
  function includeQuery(fields) {
@@ -1 +1 @@
1
- {"version":3,"file":"includeQuery.js","sourceRoot":"","sources":["../../../../../../packages/json-api-nestjs/src/lib/query/includeQuery.ts"],"names":[],"mappings":";;AAyDA,oCAuBC;AA/ED,6BAAwB;AAExB,yDAAsD;AA8CtD;;;;;;;GAOG;AACH,SAAgB,YAAY,CAAyC,MAAc;IACjF,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IAEjC,OAAO;QACL,OAAO,EAAE,OAAC;aACP,UAAU,CAAC,yBAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;aACtE,WAAW,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO;YACT,CAAC;YAED,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;gBAC1B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzB,OAAO,CAAC,QAAQ,CAAC;wBACf,IAAI,EAAE,OAAC,CAAC,YAAY,CAAC,MAAM;wBAC3B,OAAO,EAAE,2BAA2B,KAAK,GAAG;wBAC5C,IAAI,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC;qBACzB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC,CAAC;aACD,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAA0C,CAAC;KACpE,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"includeQuery.js","sourceRoot":"","sources":["../../../../../../packages/json-api-nestjs/src/lib/query/includeQuery.ts"],"names":[],"mappings":";;AA2GA,oCAuBC;AAjID,6BAAwB;AAExB,yDAAsD;AA8CtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,SAAgB,YAAY,CAAyC,MAAc;IACjF,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IAEjC,OAAO;QACL,OAAO,EAAE,OAAC;aACP,UAAU,CAAC,yBAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;aACtE,WAAW,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO;YACT,CAAC;YAED,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;gBAC1B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzB,OAAO,CAAC,QAAQ,CAAC;wBACf,IAAI,EAAE,OAAC,CAAC,YAAY,CAAC,MAAM;wBAC3B,OAAO,EAAE,2BAA2B,KAAK,GAAG;wBAC5C,IAAI,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC;qBACzB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC,CAAC;aACD,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAA0C,CAAC;KACpE,CAAC;AACJ,CAAC"}
@@ -3,9 +3,59 @@ import { type Field } from "../types";
3
3
  /**
4
4
  * Creates a Zod schema for JSON:API sort parameters.
5
5
  *
6
- * @includeExample ./packages/example-nestjs/examples/query.ts
6
+ * @example
7
+ * ```ts
8
+ * // packages/example-nestjs/examples/query.ts
9
+ * import { booleanString } from "@clipboard-health/contract-core";
10
+ * import {
11
+ * cursorPaginationQuery,
12
+ * fieldsQuery,
13
+ * type FilterMap,
14
+ * filterQuery,
15
+ * includeQuery,
16
+ * sortQuery,
17
+ * } from "@clipboard-health/json-api-nestjs";
18
+ * import { z } from "zod";
19
+ *
20
+ * import {
21
+ * type ArticleAttributeFields,
22
+ * type UserAttributeFields,
23
+ * type UserIncludeFields,
24
+ * } from "../src/contract";
25
+ *
26
+ * const articleFields = ["title"] as const satisfies readonly ArticleAttributeFields[];
27
+ * const userFields = ["age", "dateOfBirth"] as const satisfies readonly UserAttributeFields[];
28
+ * const userIncludeFields = [
29
+ * "articles",
30
+ * "articles.comments",
31
+ * ] as const satisfies readonly UserIncludeFields[];
32
+ * const userFilterMap = {
33
+ * age: {
34
+ * filters: ["eq", "gt"],
35
+ * schema: z.coerce.number().int().positive().max(125),
36
+ * },
37
+ * dateOfBirth: {
38
+ * filters: ["gte"],
39
+ * schema: z.coerce.date().min(new Date("1900-01-01")).max(new Date()),
40
+ * },
41
+ * isActive: {
42
+ * filters: ["eq"],
43
+ * schema: booleanString,
44
+ * },
45
+ * } as const satisfies FilterMap<UserAttributeFields>;
46
+ *
47
+ * export const query = z
48
+ * .object({
49
+ * ...cursorPaginationQuery(),
50
+ * ...fieldsQuery({ article: articleFields, user: userFields }),
51
+ * ...filterQuery(userFilterMap),
52
+ * ...sortQuery(userFields),
53
+ * ...includeQuery(userIncludeFields),
54
+ * })
55
+ * .strict();
56
+ *
57
+ * ```
7
58
  *
8
- * @see [Usage example](../../../../example-nestjs/examples/query.ts)
9
59
  * @see {@link https://jsonapi.org/format/#fetching-sorting JSON:API sorting}
10
60
  */
11
61
  export declare function sortQuery<const FieldT extends readonly [Field, ...Field[]]>(fields: FieldT): {
@@ -6,9 +6,59 @@ const splitString_1 = require("../internal/splitString");
6
6
  /**
7
7
  * Creates a Zod schema for JSON:API sort parameters.
8
8
  *
9
- * @includeExample ./packages/example-nestjs/examples/query.ts
9
+ * @example
10
+ * ```ts
11
+ * // packages/example-nestjs/examples/query.ts
12
+ * import { booleanString } from "@clipboard-health/contract-core";
13
+ * import {
14
+ * cursorPaginationQuery,
15
+ * fieldsQuery,
16
+ * type FilterMap,
17
+ * filterQuery,
18
+ * includeQuery,
19
+ * sortQuery,
20
+ * } from "@clipboard-health/json-api-nestjs";
21
+ * import { z } from "zod";
22
+ *
23
+ * import {
24
+ * type ArticleAttributeFields,
25
+ * type UserAttributeFields,
26
+ * type UserIncludeFields,
27
+ * } from "../src/contract";
28
+ *
29
+ * const articleFields = ["title"] as const satisfies readonly ArticleAttributeFields[];
30
+ * const userFields = ["age", "dateOfBirth"] as const satisfies readonly UserAttributeFields[];
31
+ * const userIncludeFields = [
32
+ * "articles",
33
+ * "articles.comments",
34
+ * ] as const satisfies readonly UserIncludeFields[];
35
+ * const userFilterMap = {
36
+ * age: {
37
+ * filters: ["eq", "gt"],
38
+ * schema: z.coerce.number().int().positive().max(125),
39
+ * },
40
+ * dateOfBirth: {
41
+ * filters: ["gte"],
42
+ * schema: z.coerce.date().min(new Date("1900-01-01")).max(new Date()),
43
+ * },
44
+ * isActive: {
45
+ * filters: ["eq"],
46
+ * schema: booleanString,
47
+ * },
48
+ * } as const satisfies FilterMap<UserAttributeFields>;
49
+ *
50
+ * export const query = z
51
+ * .object({
52
+ * ...cursorPaginationQuery(),
53
+ * ...fieldsQuery({ article: articleFields, user: userFields }),
54
+ * ...filterQuery(userFilterMap),
55
+ * ...sortQuery(userFields),
56
+ * ...includeQuery(userIncludeFields),
57
+ * })
58
+ * .strict();
59
+ *
60
+ * ```
10
61
  *
11
- * @see [Usage example](../../../../example-nestjs/examples/query.ts)
12
62
  * @see {@link https://jsonapi.org/format/#fetching-sorting JSON:API sorting}
13
63
  */
14
64
  function sortQuery(fields) {
@@ -1 +1 @@
1
- {"version":3,"file":"sortQuery.js","sourceRoot":"","sources":["../../../../../../packages/json-api-nestjs/src/lib/query/sortQuery.ts"],"names":[],"mappings":";;AAaA,8BAsBC;AAnCD,6BAAwB;AAExB,yDAAsD;AAGtD;;;;;;;GAOG;AACH,SAAgB,SAAS,CAAoD,MAAc;IACzF,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IACjC,OAAO;QACL,IAAI,EAAE,OAAC;aACJ,UAAU,CAAC,yBAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;aACtE,WAAW,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO;YACT,CAAC;YAED,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;gBAC1B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;oBAClE,OAAO,CAAC,QAAQ,CAAC;wBACf,IAAI,EAAE,OAAC,CAAC,YAAY,CAAC,MAAM;wBAC3B,OAAO,EAAE,wBAAwB,KAAK,GAAG;wBACzC,IAAI,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC;qBACtB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC,CAAC;aACD,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAiE,CAAC;KAC3F,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"sortQuery.js","sourceRoot":"","sources":["../../../../../../packages/json-api-nestjs/src/lib/query/sortQuery.ts"],"names":[],"mappings":";;AA+DA,8BAsBC;AArFD,6BAAwB;AAExB,yDAAsD;AAGtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,SAAgB,SAAS,CAAoD,MAAc;IACzF,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IACjC,OAAO;QACL,IAAI,EAAE,OAAC;aACJ,UAAU,CAAC,yBAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;aACtE,WAAW,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO;YACT,CAAC;YAED,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;gBAC1B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;oBAClE,OAAO,CAAC,QAAQ,CAAC;wBACf,IAAI,EAAE,OAAC,CAAC,YAAY,CAAC,MAAM;wBAC3B,OAAO,EAAE,wBAAwB,KAAK,GAAG;wBACzC,IAAI,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC;qBACtB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC,CAAC;aACD,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAiE,CAAC;KAC3F,CAAC;AACJ,CAAC"}