@clipboard-health/json-api 0.1.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 +70 -0
- package/package.json +26 -0
- package/src/index.d.ts +3 -0
- package/src/index.js +7 -0
- package/src/index.js.map +1 -0
- package/src/lib/toJsonApiQuery.d.ts +7 -0
- package/src/lib/toJsonApiQuery.js +61 -0
- package/src/lib/toJsonApiQuery.js.map +1 -0
- package/src/lib/toSearchParams.d.ts +8 -0
- package/src/lib/toSearchParams.js +42 -0
- package/src/lib/toSearchParams.js.map +1 -0
- package/src/lib/types.d.ts +51 -0
- package/src/lib/types.js +3 -0
- package/src/lib/types.js.map +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# @clipboard-health/json-api
|
|
2
|
+
|
|
3
|
+
Utilities for adhering to the [JSON:API](https://jsonapi.org/) specification.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Install](#install)
|
|
8
|
+
- [Usage](#usage)
|
|
9
|
+
- [Local development commands](#local-development-commands)
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @clipboard-health/json-api
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
### Query helpers
|
|
20
|
+
|
|
21
|
+
From the client, call `toSearchParams` to convert from `JsonApiQuery` to `URLSearchParams`:
|
|
22
|
+
|
|
23
|
+
<!-- prettier-ignore -->
|
|
24
|
+
```ts
|
|
25
|
+
// ./examples/toSearchParams.ts
|
|
26
|
+
|
|
27
|
+
import { toSearchParams } from "@clipboard-health/json-api";
|
|
28
|
+
|
|
29
|
+
import { type JsonApiQuery } from "../src/lib/types";
|
|
30
|
+
|
|
31
|
+
const query: JsonApiQuery = {
|
|
32
|
+
fields: { dog: ["age", "name"] },
|
|
33
|
+
filter: { age: ["2", "5"] },
|
|
34
|
+
include: ["vet"],
|
|
35
|
+
page: { size: "10" },
|
|
36
|
+
sort: ["-age"],
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
console.log(toSearchParams(query).toString());
|
|
40
|
+
// Note: actual result is URL-encoded, but unencoded below for readability
|
|
41
|
+
// => fields[dog]=age,name&filter[age]=2,5&include=vet&page[size]=10&sort=-age
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
From the server, call `toJsonApiQuery` to convert from `URLSearchParams` to `JsonApiQuery`:
|
|
46
|
+
|
|
47
|
+
<!-- prettier-ignore -->
|
|
48
|
+
```ts
|
|
49
|
+
// ./examples/toJsonApiQuery.ts
|
|
50
|
+
|
|
51
|
+
import { toJsonApiQuery } from "@clipboard-health/json-api";
|
|
52
|
+
|
|
53
|
+
const searchParams = new URLSearchParams(
|
|
54
|
+
"fields%5Bdog%5D=age%2Cname&filter%5Bage%5D=2%2C5&include=vet&page%5Bsize%5D=10&sort=-age",
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
console.log(toJsonApiQuery(searchParams));
|
|
58
|
+
// => {
|
|
59
|
+
// fields: { dog: ["age", "name"] },
|
|
60
|
+
// filter: { age: ["2", "5"] },
|
|
61
|
+
// include: ["vet"],
|
|
62
|
+
// page: { size: "10" },
|
|
63
|
+
// sort: ["-age"],
|
|
64
|
+
// }
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Local development commands
|
|
69
|
+
|
|
70
|
+
See [`package.json`](./package.json) `scripts` for a list of commands.
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@clipboard-health/json-api",
|
|
3
|
+
"description": "",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"bugs": "https://github.com/clipboardhealth/core-utils/issues",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"tslib": "2.6.3"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [],
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"main": "./src/index.js",
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/clipboardhealth/core-utils.git",
|
|
18
|
+
"directory": "packages/json-api"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"embed": "embedme README.md"
|
|
22
|
+
},
|
|
23
|
+
"type": "commonjs",
|
|
24
|
+
"typings": "./src/index.d.ts",
|
|
25
|
+
"types": "./src/index.d.ts"
|
|
26
|
+
}
|
package/src/index.d.ts
ADDED
package/src/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./lib/toJsonApiQuery"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./lib/toSearchParams"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./lib/types"), exports);
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/json-api/src/index.ts"],"names":[],"mappings":";;;AAAA,+DAAqC;AACrC,+DAAqC;AACrC,sDAA4B"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type JsonApiQuery } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Call this function from clients to convert from {@link URLSearchParams} to {@link JsonApiQuery}.
|
|
4
|
+
*
|
|
5
|
+
* @see [Example](https://github.com/ClipboardHealth/core-utils/blob/main/packages/json-api/examples/toJsonApiQuery.ts)
|
|
6
|
+
*/
|
|
7
|
+
export declare function toJsonApiQuery(searchParams: URLSearchParams): JsonApiQuery;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toJsonApiQuery = toJsonApiQuery;
|
|
4
|
+
const REGEX = {
|
|
5
|
+
fields: /^fields\[(.*?)]$/i,
|
|
6
|
+
filter: /^filter\[([^\]]*?)]$/i,
|
|
7
|
+
filterType: /^filter\[(.*?)]\[(.*?)]$/i,
|
|
8
|
+
include: /^include$/i,
|
|
9
|
+
page: /^page\[(.*?)]$/i,
|
|
10
|
+
sort: /^sort$/i,
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Call this function from clients to convert from {@link URLSearchParams} to {@link JsonApiQuery}.
|
|
14
|
+
*
|
|
15
|
+
* @see [Example](https://github.com/ClipboardHealth/core-utils/blob/main/packages/json-api/examples/toJsonApiQuery.ts)
|
|
16
|
+
*/
|
|
17
|
+
function toJsonApiQuery(searchParams) {
|
|
18
|
+
return [...searchParams].reduce((accumulator, [key, value]) => {
|
|
19
|
+
const match = Object.entries(REGEX).find(([, regex]) => regex.test(key));
|
|
20
|
+
if (!match) {
|
|
21
|
+
return accumulator;
|
|
22
|
+
}
|
|
23
|
+
const [type, regex] = match;
|
|
24
|
+
const groups = regex.exec(key)?.slice(1);
|
|
25
|
+
if (type === "fields" && groups?.[0]) {
|
|
26
|
+
return {
|
|
27
|
+
...accumulator,
|
|
28
|
+
fields: {
|
|
29
|
+
...accumulator.fields,
|
|
30
|
+
[groups[0]]: value.split(","),
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
if ((type === "filter" || type === "filterType") && groups?.length) {
|
|
35
|
+
const [field, fieldType] = groups;
|
|
36
|
+
if (field) {
|
|
37
|
+
return {
|
|
38
|
+
...accumulator,
|
|
39
|
+
filter: {
|
|
40
|
+
...accumulator.filter,
|
|
41
|
+
[field]: fieldType
|
|
42
|
+
? { ...accumulator.filter?.[field], [fieldType]: value }
|
|
43
|
+
: value.split(","),
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (type === "include" || type === "sort") {
|
|
49
|
+
return { ...accumulator, [type]: value.split(",") };
|
|
50
|
+
}
|
|
51
|
+
if (type === "page" && groups?.[0]) {
|
|
52
|
+
return {
|
|
53
|
+
...accumulator,
|
|
54
|
+
page: { ...accumulator.page, [groups[0]]: value },
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/* istanbul ignore next */
|
|
58
|
+
return accumulator;
|
|
59
|
+
}, {});
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=toJsonApiQuery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toJsonApiQuery.js","sourceRoot":"","sources":["../../../../../packages/json-api/src/lib/toJsonApiQuery.ts"],"names":[],"mappings":";;AAgBA,wCAgDC;AA9DD,MAAM,KAAK,GAAG;IACZ,MAAM,EAAE,mBAAmB;IAC3B,MAAM,EAAE,uBAAuB;IAC/B,UAAU,EAAE,2BAA2B;IACvC,OAAO,EAAE,YAAY;IACrB,IAAI,EAAE,iBAAiB;IACvB,IAAI,EAAE,SAAS;CACP,CAAC;AAEX;;;;GAIG;AACH,SAAgB,cAAc,CAAC,YAA6B;IAC1D,OAAO,CAAC,GAAG,YAAY,CAAC,CAAC,MAAM,CAAe,CAAC,WAAW,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;QAC1E,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACzE,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,WAAW,CAAC;QACrB,CAAC;QAED,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,KAAqC,CAAC;QAC5D,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;QACzC,IAAI,IAAI,KAAK,QAAQ,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrC,OAAO;gBACL,GAAG,WAAW;gBACd,MAAM,EAAE;oBACN,GAAG,WAAW,CAAC,MAAM;oBACrB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC;iBAC9B;aACF,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,YAAY,CAAC,IAAI,MAAM,EAAE,MAAM,EAAE,CAAC;YACnE,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,MAAM,CAAC;YAClC,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO;oBACL,GAAG,WAAW;oBACd,MAAM,EAAE;wBACN,GAAG,WAAW,CAAC,MAAM;wBACrB,CAAC,KAAK,CAAC,EAAE,SAAS;4BAChB,CAAC,CAAC,EAAE,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE;4BACxD,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC;qBACrB;iBACF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1C,OAAO,EAAE,GAAG,WAAW,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACtD,CAAC;QAED,IAAI,IAAI,KAAK,MAAM,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnC,OAAO;gBACL,GAAG,WAAW;gBACd,IAAI,EAAE,EAAE,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE;aAClD,CAAC;QACJ,CAAC;QAED,0BAA0B;QAC1B,OAAO,WAAW,CAAC;IACrB,CAAC,EAAE,EAAE,CAAC,CAAC;AACT,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { URLSearchParams } from "node:url";
|
|
2
|
+
import { type JsonApiQuery } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Call this function from clients to convert from {@link JsonApiQuery} to {@link URLSearchParams}.
|
|
5
|
+
*
|
|
6
|
+
* @see [Example](https://github.com/ClipboardHealth/core-utils/blob/main/packages/json-api/examples/toSearchParams.ts)
|
|
7
|
+
*/
|
|
8
|
+
export declare function toSearchParams(query: JsonApiQuery): URLSearchParams;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toSearchParams = toSearchParams;
|
|
4
|
+
const node_url_1 = require("node:url");
|
|
5
|
+
/**
|
|
6
|
+
* Call this function from clients to convert from {@link JsonApiQuery} to {@link URLSearchParams}.
|
|
7
|
+
*
|
|
8
|
+
* @see [Example](https://github.com/ClipboardHealth/core-utils/blob/main/packages/json-api/examples/toSearchParams.ts)
|
|
9
|
+
*/
|
|
10
|
+
function toSearchParams(query) {
|
|
11
|
+
const searchParams = new node_url_1.URLSearchParams();
|
|
12
|
+
if (query.fields) {
|
|
13
|
+
Object.entries(query.fields).forEach(([type, fields]) => {
|
|
14
|
+
searchParams.append(`fields[${type}]`, fields.join(","));
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
if (query.filter) {
|
|
18
|
+
Object.entries(query.filter).forEach(([field, values]) => {
|
|
19
|
+
if (Array.isArray(values)) {
|
|
20
|
+
searchParams.append(`filter[${field}]`, values.join(","));
|
|
21
|
+
}
|
|
22
|
+
else if (typeof values === "object") {
|
|
23
|
+
Object.entries(values).forEach(([fieldType, value]) => {
|
|
24
|
+
searchParams.append(`filter[${field}][${fieldType}]`, value);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
if (query.include) {
|
|
30
|
+
searchParams.append("include", query.include.join(","));
|
|
31
|
+
}
|
|
32
|
+
if (query.page) {
|
|
33
|
+
Object.entries(query.page).forEach(([key, value]) => {
|
|
34
|
+
searchParams.append(`page[${key}]`, value);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
if (query.sort) {
|
|
38
|
+
searchParams.append("sort", query.sort.join(","));
|
|
39
|
+
}
|
|
40
|
+
return searchParams;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=toSearchParams.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toSearchParams.js","sourceRoot":"","sources":["../../../../../packages/json-api/src/lib/toSearchParams.ts"],"names":[],"mappings":";;AASA,wCAoCC;AA7CD,uCAA2C;AAI3C;;;;GAIG;AACH,SAAgB,cAAc,CAAC,KAAmB;IAChD,MAAM,YAAY,GAAG,IAAI,0BAAe,EAAE,CAAC;IAE3C,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;YACtD,YAAY,CAAC,MAAM,CAAC,UAAU,IAAI,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE;YACvD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1B,YAAY,CAAC,MAAM,CAAC,UAAU,KAAK,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5D,CAAC;iBAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACtC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,EAAE;oBACpD,YAAY,CAAC,MAAM,CAAC,UAAU,KAAK,KAAK,SAAS,GAAG,EAAE,KAAK,CAAC,CAAC;gBAC/D,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,YAAY,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QACf,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YAClD,YAAY,CAAC,MAAM,CAAC,QAAQ,GAAG,GAAG,EAAE,KAAK,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QACf,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filter operators to build complex filter queries.
|
|
3
|
+
* - gt: Greater than
|
|
4
|
+
* - gte: Greater than or equal to
|
|
5
|
+
* - lt: Less than
|
|
6
|
+
* - lte: Less than or equal to
|
|
7
|
+
* - not: Not equal to
|
|
8
|
+
*/
|
|
9
|
+
type FieldType = "gt" | "gte" | "lt" | "lte" | "not";
|
|
10
|
+
/**
|
|
11
|
+
* A JSON:API URL query string.
|
|
12
|
+
*/
|
|
13
|
+
export interface JsonApiQuery {
|
|
14
|
+
/**
|
|
15
|
+
* Fields to include in the response.
|
|
16
|
+
*
|
|
17
|
+
* @see {@link https://jsonapi.org/format/#fetching-sparse-fieldsets Sparse fieldsets}
|
|
18
|
+
*/
|
|
19
|
+
fields?: Record<string, string[]>;
|
|
20
|
+
/**
|
|
21
|
+
* Filters to apply to the query.
|
|
22
|
+
*
|
|
23
|
+
* @see {@link https://jsonapi.org/recommendations/#filtering Filtering}
|
|
24
|
+
* @see {@link https://discuss.jsonapi.org/t/share-propose-a-filtering-strategy/257 Filtering strategy}
|
|
25
|
+
*/
|
|
26
|
+
filter?: Record<string, string[] | {
|
|
27
|
+
[K in FieldType]?: string;
|
|
28
|
+
}>;
|
|
29
|
+
/**
|
|
30
|
+
* Relationships to include in the response.
|
|
31
|
+
*
|
|
32
|
+
* @see {@link https://jsonapi.org/format/#fetching-includes Fetching includes}
|
|
33
|
+
*/
|
|
34
|
+
include?: string[];
|
|
35
|
+
/**
|
|
36
|
+
* Pagination data.
|
|
37
|
+
*
|
|
38
|
+
* @see {@link https://jsonapi.org/format/#fetching-pagination Pagination}
|
|
39
|
+
* @see {@link https://jsonapi.org/examples/#pagination Pagination examples}
|
|
40
|
+
*/
|
|
41
|
+
page?: {
|
|
42
|
+
[K in "cursor" | "limit" | "number" | "offset" | "size"]?: string;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Sorting data. Include the "-" prefix for descending order.
|
|
46
|
+
*
|
|
47
|
+
* @see {@link https://jsonapi.org/format/#fetching-sorting Sorting}
|
|
48
|
+
*/
|
|
49
|
+
sort?: string[];
|
|
50
|
+
}
|
|
51
|
+
export {};
|
package/src/lib/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../packages/json-api/src/lib/types.ts"],"names":[],"mappings":""}
|