@clipboard-health/json-api-nestjs 0.4.1 → 0.5.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 +1 -1
- package/package.json +7 -3
- package/src/index.d.ts +0 -1
- package/src/index.js +0 -1
- package/src/index.js.map +1 -1
- package/src/lib/query/cursorPaginationQuery.js +2 -2
- package/src/lib/query/cursorPaginationQuery.js.map +1 -1
- package/src/lib/query/filterQuery.d.ts +5 -3
- package/src/lib/query/filterQuery.js +14 -12
- package/src/lib/query/filterQuery.js.map +1 -1
- package/src/lib/query/includeQuery.d.ts +9 -7
- package/src/lib/query/includeQuery.js.map +1 -1
- package/src/lib/types.d.ts +1 -1
- package/src/lib/schemas.d.ts +0 -14
- package/src/lib/schemas.js +0 -20
- package/src/lib/schemas.js.map +0 -1
- package/src/test/index.d.ts +0 -3
- package/src/test/index.js +0 -23
- package/src/test/index.js.map +0 -1
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clipboard-health/json-api-nestjs",
|
|
3
3
|
"description": "Utilities for adhering to the JSON:API specification with NestJS.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.1",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"
|
|
6
|
+
"@clipboard-health/contract-core": "0.1.1",
|
|
7
|
+
"tslib": "2.8.0",
|
|
7
8
|
"type-fest": "4.26.1",
|
|
8
9
|
"zod": "3.23.8"
|
|
9
10
|
},
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"@clipboard-health/testing-core": "0.1.1"
|
|
13
|
+
},
|
|
10
14
|
"keywords": [],
|
|
11
15
|
"license": "MIT",
|
|
12
16
|
"main": "./src/index.js",
|
|
13
17
|
"publishConfig": {
|
|
14
|
-
"access": "
|
|
18
|
+
"access": "public"
|
|
15
19
|
},
|
|
16
20
|
"scripts": {
|
|
17
21
|
"embed": "embedme README.md"
|
package/src/index.d.ts
CHANGED
package/src/index.js
CHANGED
|
@@ -6,6 +6,5 @@ tslib_1.__exportStar(require("./lib/query/fieldsQuery"), exports);
|
|
|
6
6
|
tslib_1.__exportStar(require("./lib/query/filterQuery"), exports);
|
|
7
7
|
tslib_1.__exportStar(require("./lib/query/includeQuery"), exports);
|
|
8
8
|
tslib_1.__exportStar(require("./lib/query/sortQuery"), exports);
|
|
9
|
-
tslib_1.__exportStar(require("./lib/schemas"), exports);
|
|
10
9
|
tslib_1.__exportStar(require("./lib/types"), exports);
|
|
11
10
|
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/json-api-nestjs/src/index.ts"],"names":[],"mappings":";;;AAAA,4EAAkD;AAClD,kEAAwC;AACxC,kEAAwC;AACxC,mEAAyC;AACzC,gEAAsC;AACtC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/json-api-nestjs/src/index.ts"],"names":[],"mappings":";;;AAAA,4EAAkD;AAClD,kEAAwC;AACxC,kEAAwC;AACxC,mEAAyC;AACzC,gEAAsC;AACtC,sDAA4B"}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PAGINATION = void 0;
|
|
4
4
|
exports.cursorPaginationQuery = cursorPaginationQuery;
|
|
5
|
+
const contract_core_1 = require("@clipboard-health/contract-core");
|
|
5
6
|
const zod_1 = require("zod");
|
|
6
|
-
const schemas_1 = require("../schemas");
|
|
7
7
|
exports.PAGINATION = {
|
|
8
8
|
size: {
|
|
9
9
|
maximum: 200,
|
|
@@ -26,7 +26,7 @@ function cursorPaginationQuery(parameters) {
|
|
|
26
26
|
page: zod_1.z
|
|
27
27
|
.object({
|
|
28
28
|
size: zod_1.z.coerce.number().int().positive().max(maximum).default(defaultSize),
|
|
29
|
-
cursor:
|
|
29
|
+
cursor: contract_core_1.nonEmptyString.optional(),
|
|
30
30
|
})
|
|
31
31
|
.strict()
|
|
32
32
|
.default({ size: defaultSize }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cursorPaginationQuery.js","sourceRoot":"","sources":["../../../../../../packages/json-api-nestjs/src/lib/query/cursorPaginationQuery.ts"],"names":[],"mappings":";;;
|
|
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,GAAG;QACZ,OAAO,EAAE,EAAE;KACZ;CACO,CAAC;AAEX;;;;;;;;GAQG;AACH,SAAgB,qBAAqB,CACnC,UAAuE;IAEvE,MAAM,EAAE,IAAI,EAAE,GAAG,kBAAU,CAAC;IAC5B,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC;IAE/F,OAAO;QACL,IAAI,EAAE,OAAC;aACJ,MAAM,CAAC;YACN,IAAI,EAAE,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;YAC1E,MAAM,EAAE,8BAAc,CAAC,QAAQ,EAAE;SAClC,CAAC;aACD,MAAM,EAAE;aACR,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;KAClC,CAAC;AACJ,CAAC"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { type Field } from "../types";
|
|
3
3
|
export type Filter = "eq" | "ne" | "gt" | "gte" | "lt" | "lte";
|
|
4
|
-
export type
|
|
5
|
-
|
|
4
|
+
export type FilterTuple = readonly [Filter, ...Filter[]];
|
|
5
|
+
export interface FilterValue {
|
|
6
|
+
filters: FilterTuple;
|
|
6
7
|
schema: z.ZodTypeAny;
|
|
7
|
-
}
|
|
8
|
+
}
|
|
9
|
+
export type FilterMap<FieldT extends Field = Field> = Record<FieldT, FilterValue>;
|
|
8
10
|
export type FilterSchema<MapT extends FilterMap> = {
|
|
9
11
|
[K in keyof MapT]: z.ZodOptional<z.ZodEffects<z.ZodOptional<z.ZodObject<{
|
|
10
12
|
[F in MapT[K]["filters"][number]]: z.ZodOptional<z.ZodEffects<z.ZodOptional<z.ZodReadonly<z.ZodArray<MapT[K]["schema"]>>>>>;
|
|
@@ -16,22 +16,24 @@ const splitString_1 = require("../internal/splitString");
|
|
|
16
16
|
function filterQuery(parameters) {
|
|
17
17
|
return {
|
|
18
18
|
filter: zod_1.z
|
|
19
|
-
.object(Object.fromEntries(Object.entries(parameters).map(([apiType,
|
|
19
|
+
.object(Object.fromEntries(Object.entries(parameters).map(([apiType, value]) => [
|
|
20
20
|
apiType,
|
|
21
|
-
zod_1.z
|
|
22
|
-
.preprocess(queryFilterPreprocessor_1.queryFilterPreprocessor, zod_1.z
|
|
23
|
-
.object(Object.fromEntries(filters.map((filter) => [
|
|
24
|
-
filter,
|
|
25
|
-
zod_1.z
|
|
26
|
-
.preprocess(splitString_1.splitString, schema.array().min(1).max(10_000).readonly().optional())
|
|
27
|
-
.optional(),
|
|
28
|
-
])))
|
|
29
|
-
.strict()
|
|
30
|
-
.optional())
|
|
31
|
-
.optional(),
|
|
21
|
+
zod_1.z.preprocess(queryFilterPreprocessor_1.queryFilterPreprocessor, filterSchema(value)).optional(),
|
|
32
22
|
])))
|
|
33
23
|
.strict()
|
|
34
24
|
.optional(),
|
|
35
25
|
};
|
|
36
26
|
}
|
|
27
|
+
function filterSchema(parameters) {
|
|
28
|
+
const { filters, schema } = parameters;
|
|
29
|
+
return zod_1.z
|
|
30
|
+
.object(Object.fromEntries(filters.map((filter) => [
|
|
31
|
+
filter,
|
|
32
|
+
zod_1.z
|
|
33
|
+
.preprocess(splitString_1.splitString, schema.array().min(1).max(10_000).readonly().optional())
|
|
34
|
+
.optional(),
|
|
35
|
+
])))
|
|
36
|
+
.strict()
|
|
37
|
+
.optional();
|
|
38
|
+
}
|
|
37
39
|
//# sourceMappingURL=filterQuery.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filterQuery.js","sourceRoot":"","sources":["../../../../../../packages/json-api-nestjs/src/lib/query/filterQuery.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"filterQuery.js","sourceRoot":"","sources":["../../../../../../packages/json-api-nestjs/src/lib/query/filterQuery.ts"],"names":[],"mappings":";;AAwCA,kCAcC;AAtDD,6BAAwB;AAExB,iFAA8E;AAC9E,yDAAsD;AA4BtD;;;;;;;;GAQG;AACH,SAAgB,WAAW,CAA+B,UAA0B;IAClF,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;aACE,UAAU,CAAC,yBAAW,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC;aAChF,QAAQ,EAAE;KACd,CAAC,CACH,CACF;SACA,MAAM,EAAE;SACR,QAAQ,EAAE,CAAC;AAChB,CAAC"}
|
|
@@ -2,22 +2,24 @@ import { type GreaterThan, type Subtract } from "type-fest";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { type JsonApiDocument, type Relationship } from "../types";
|
|
4
4
|
/**
|
|
5
|
-
* JSON:API
|
|
5
|
+
* Recursively traverse the JSON:API document to build a list of all possible relationship paths up
|
|
6
|
+
* to the specified depth, which prevents stack overflow for circular relationships. Use the result
|
|
7
|
+
* in `include` queries
|
|
6
8
|
*
|
|
7
9
|
* @template MapT - A map of ApiType to Zod schemas.
|
|
8
10
|
* @template DocumentT - The JSON:API document.
|
|
9
|
-
* @template
|
|
11
|
+
* @template Depth - The maximum depth for recursive relationship traversal.
|
|
10
12
|
* @template Prefix - The prefix for nested relationship paths.
|
|
11
13
|
*/
|
|
12
|
-
export type RelationshipPaths<MapT extends Record<string, z.ZodTypeAny>, DocumentT extends JsonApiDocument,
|
|
13
|
-
relationships?: infer
|
|
14
|
-
} ?
|
|
15
|
-
[K in keyof
|
|
14
|
+
export type RelationshipPaths<MapT extends Record<string, z.ZodTypeAny>, DocumentT extends JsonApiDocument, Depth extends number = 5, Prefix extends string = ""> = GreaterThan<Depth, 0> extends true ? DocumentT["data"] extends Array<infer Data> | infer Data ? Data extends {
|
|
15
|
+
relationships?: infer Relation;
|
|
16
|
+
} ? Relation extends Record<string, Relationship> ? {
|
|
17
|
+
[K in keyof Relation]: K extends string ? Relation[K]["data"] extends {
|
|
16
18
|
type?: infer RelationT;
|
|
17
19
|
} | Array<{
|
|
18
20
|
type?: infer RelationT;
|
|
19
21
|
}> ? RelationT extends keyof MapT ? `${Prefix}${K}` | RelationshipPaths<MapT, z.infer<MapT[RelationT]>, Subtract<Depth, 1>, `${Prefix}${K}.`> : never : never : never;
|
|
20
|
-
}[keyof
|
|
22
|
+
}[keyof Relation] : never : never : never : never;
|
|
21
23
|
/**
|
|
22
24
|
* Creates a Zod schema for JSON:API include parameters.
|
|
23
25
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"includeQuery.js","sourceRoot":"","sources":["../../../../../../packages/json-api-nestjs/src/lib/query/includeQuery.ts"],"names":[],"mappings":";;
|
|
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"}
|
package/src/lib/types.d.ts
CHANGED
package/src/lib/schemas.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
/**
|
|
3
|
-
* A non-empty string Zod schema.
|
|
4
|
-
*/
|
|
5
|
-
export declare const nonEmptyString: z.ZodString;
|
|
6
|
-
/**
|
|
7
|
-
* A Zod schema for use with boolean query parameters since `z.coerce.boolean()` treats any truthy
|
|
8
|
-
* value as `true`.
|
|
9
|
-
*
|
|
10
|
-
* `.transform((value) => value === "true")` causes inference issues in controllers.
|
|
11
|
-
*/
|
|
12
|
-
export declare const booleanString: z.ZodEnum<["true", "false"]>;
|
|
13
|
-
export type BooleanString = z.infer<typeof booleanString>;
|
|
14
|
-
export declare function toBoolean(value: BooleanString): boolean;
|
package/src/lib/schemas.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.booleanString = exports.nonEmptyString = void 0;
|
|
4
|
-
exports.toBoolean = toBoolean;
|
|
5
|
-
const zod_1 = require("zod");
|
|
6
|
-
/**
|
|
7
|
-
* A non-empty string Zod schema.
|
|
8
|
-
*/
|
|
9
|
-
exports.nonEmptyString = zod_1.z.string().min(1);
|
|
10
|
-
/**
|
|
11
|
-
* A Zod schema for use with boolean query parameters since `z.coerce.boolean()` treats any truthy
|
|
12
|
-
* value as `true`.
|
|
13
|
-
*
|
|
14
|
-
* `.transform((value) => value === "true")` causes inference issues in controllers.
|
|
15
|
-
*/
|
|
16
|
-
exports.booleanString = zod_1.z.enum(["true", "false"]);
|
|
17
|
-
function toBoolean(value) {
|
|
18
|
-
return value === "true";
|
|
19
|
-
}
|
|
20
|
-
//# sourceMappingURL=schemas.js.map
|
package/src/lib/schemas.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../../../../packages/json-api-nestjs/src/lib/schemas.ts"],"names":[],"mappings":";;;AAiBA,8BAEC;AAnBD,6BAAwB;AAExB;;GAEG;AACU,QAAA,cAAc,GAAG,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAEhD;;;;;GAKG;AACU,QAAA,aAAa,GAAG,OAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAIvD,SAAgB,SAAS,CAAC,KAAoB;IAC5C,OAAO,KAAK,KAAK,MAAM,CAAC;AAC1B,CAAC"}
|
package/src/test/index.d.ts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { type SafeParseError, type SafeParseReturnType, type SafeParseSuccess } from "zod";
|
|
2
|
-
export declare function expectToBeSuccess<Input, Output>(value: Readonly<SafeParseReturnType<Input, Output>>): asserts value is SafeParseSuccess<Output>;
|
|
3
|
-
export declare function expectToBeError<Input, Output>(value: Readonly<SafeParseReturnType<Input, Output>>): asserts value is SafeParseError<Input>;
|
package/src/test/index.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.expectToBeSuccess = expectToBeSuccess;
|
|
4
|
-
exports.expectToBeError = expectToBeError;
|
|
5
|
-
const node_assert_1 = require("node:assert");
|
|
6
|
-
function isNullOrUndefined(value) {
|
|
7
|
-
return value === null || value === undefined;
|
|
8
|
-
}
|
|
9
|
-
function isDefined(value) {
|
|
10
|
-
return !isNullOrUndefined(value);
|
|
11
|
-
}
|
|
12
|
-
function expectToBeDefined(value) {
|
|
13
|
-
(0, node_assert_1.ok)(isDefined(value));
|
|
14
|
-
}
|
|
15
|
-
function expectToBeSuccess(value) {
|
|
16
|
-
expectToBeDefined(value);
|
|
17
|
-
(0, node_assert_1.ok)(value.success);
|
|
18
|
-
}
|
|
19
|
-
function expectToBeError(value) {
|
|
20
|
-
expectToBeDefined(value);
|
|
21
|
-
(0, node_assert_1.ok)(!value.success);
|
|
22
|
-
}
|
|
23
|
-
//# sourceMappingURL=index.js.map
|
package/src/test/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/json-api-nestjs/src/test/index.ts"],"names":[],"mappings":";;AAmBA,8CAKC;AAED,0CAKC;AA/BD,6CAAiC;AAOjC,SAAS,iBAAiB,CAAI,KAA0B;IACtD,OAAO,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,CAAC;AAC/C,CAAC;AAED,SAAS,SAAS,CAAI,KAA0B;IAC9C,OAAO,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,iBAAiB,CAAI,KAAoB;IAChD,IAAA,gBAAE,EAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;AACvB,CAAC;AAED,SAAgB,iBAAiB,CAC/B,KAAmD;IAEnD,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACzB,IAAA,gBAAE,EAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AACpB,CAAC;AAED,SAAgB,eAAe,CAC7B,KAAmD;IAEnD,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACzB,IAAA,gBAAE,EAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC"}
|