odata-build-query 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/LICENSE +21 -0
- package/README.md +37 -0
- package/dist/encode.d.ts +1 -0
- package/dist/filter.d.ts +23 -0
- package/dist/helpers.d.ts +13 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +137 -0
- package/dist/index.js.map +1 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 VARSHA SD
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# odata-query-builder
|
|
2
|
+
|
|
3
|
+
Build OData v4 query strings without hand-concatenating them.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { build, and, gt, contains } from "odata-build-query";
|
|
7
|
+
|
|
8
|
+
const query = build({
|
|
9
|
+
filter: and(gt("Age", 18), contains("Name", "ob")),
|
|
10
|
+
select: ["Id", "Name"],
|
|
11
|
+
top: 10,
|
|
12
|
+
});
|
|
13
|
+
// ?$top=10&$filter=Age%20gt%2018%20and%20contains(Name,'ob')&$select=Id,Name
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install odata-build-query
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
ESM only. Ships with TypeScript types.
|
|
23
|
+
|
|
24
|
+
## Supported
|
|
25
|
+
|
|
26
|
+
`$top`, `$skip`, `$count`, `$select`, `$orderby`, `$filter` (comparisons, `and` / `or` / `not`,
|
|
27
|
+
`contains` / `startswith` / `endswith`), `$expand` (including nested options).
|
|
28
|
+
|
|
29
|
+
## Encoding
|
|
30
|
+
|
|
31
|
+
The result is percent-encoded by default and ready to append to a URL:
|
|
32
|
+
`fetch(baseUrl + query)`. Pass `{ encode: false }` as the second argument for readable output.
|
|
33
|
+
Don't pass the result as a value to `URLSearchParams` or an axios `params` object; it would be encoded twice.
|
|
34
|
+
|
|
35
|
+
## Not supported yet
|
|
36
|
+
|
|
37
|
+
`$search`, `$apply`, `$levels`, `$ref`, lambda operators (`any` / `all`), arithmetic and date functions.
|
package/dist/encode.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function encodeQuery(query: string): string;
|
package/dist/filter.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type FilterValue = string | number | boolean | null | Date;
|
|
2
|
+
export type ComparisonOp = "eq" | "ne" | "gt" | "ge" | "lt" | "le";
|
|
3
|
+
export type FilterFn = "contains" | "startswith" | "endswith";
|
|
4
|
+
export type FilterNode = {
|
|
5
|
+
type: "comparison";
|
|
6
|
+
field: string;
|
|
7
|
+
op: ComparisonOp;
|
|
8
|
+
value: FilterValue;
|
|
9
|
+
} | {
|
|
10
|
+
type: "function";
|
|
11
|
+
name: FilterFn;
|
|
12
|
+
field: string;
|
|
13
|
+
value: string;
|
|
14
|
+
} | {
|
|
15
|
+
type: "group";
|
|
16
|
+
op: "and" | "or";
|
|
17
|
+
conditions: FilterNode[];
|
|
18
|
+
} | {
|
|
19
|
+
type: "not";
|
|
20
|
+
condition: FilterNode;
|
|
21
|
+
};
|
|
22
|
+
export declare function formatValue(value: FilterValue): string;
|
|
23
|
+
export declare function renderFilter(node: FilterNode): string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FilterNode, FilterValue } from "./filter.js";
|
|
2
|
+
export declare const eq: (field: string, value: FilterValue) => FilterNode;
|
|
3
|
+
export declare const ne: (field: string, value: FilterValue) => FilterNode;
|
|
4
|
+
export declare const gt: (field: string, value: FilterValue) => FilterNode;
|
|
5
|
+
export declare const ge: (field: string, value: FilterValue) => FilterNode;
|
|
6
|
+
export declare const lt: (field: string, value: FilterValue) => FilterNode;
|
|
7
|
+
export declare const le: (field: string, value: FilterValue) => FilterNode;
|
|
8
|
+
export declare const contains: (field: string, value: string) => FilterNode;
|
|
9
|
+
export declare const startsWith: (field: string, value: string) => FilterNode;
|
|
10
|
+
export declare const endsWith: (field: string, value: string) => FilterNode;
|
|
11
|
+
export declare const and: (...conditions: FilterNode[]) => FilterNode;
|
|
12
|
+
export declare const or: (...conditions: FilterNode[]) => FilterNode;
|
|
13
|
+
export declare const not: (condition: FilterNode) => FilterNode;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type FilterNode } from "./filter.js";
|
|
2
|
+
export interface BuildConfig {
|
|
3
|
+
/** Percent-encode the result (default: true). */
|
|
4
|
+
encode?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export type OrderByItem = string | {
|
|
7
|
+
field: string;
|
|
8
|
+
direction?: "asc" | "desc";
|
|
9
|
+
};
|
|
10
|
+
export interface QueryOptions {
|
|
11
|
+
top?: number;
|
|
12
|
+
skip?: number;
|
|
13
|
+
count?: boolean;
|
|
14
|
+
select?: string[];
|
|
15
|
+
orderBy?: OrderByItem[];
|
|
16
|
+
filter?: FilterNode;
|
|
17
|
+
expand?: ExpandItem[];
|
|
18
|
+
}
|
|
19
|
+
export type ExpandItem = string | {
|
|
20
|
+
path: string;
|
|
21
|
+
options?: QueryOptions;
|
|
22
|
+
};
|
|
23
|
+
export declare function build(options?: QueryOptions, config?: BuildConfig): string;
|
|
24
|
+
export type { FilterNode, FilterValue, ComparisonOp, FilterFn, } from "./filter.js";
|
|
25
|
+
export { eq, ne, gt, ge, lt, le, contains, startsWith, endsWith, and, or, not, } from "./helpers.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// src/filter.ts
|
|
2
|
+
function formatValue(value) {
|
|
3
|
+
if (value === null) return "null";
|
|
4
|
+
if (value instanceof Date) {
|
|
5
|
+
if (Number.isNaN(value.getTime())) throw new Error("Invalid Date");
|
|
6
|
+
return value.toISOString();
|
|
7
|
+
}
|
|
8
|
+
switch (typeof value) {
|
|
9
|
+
case "string":
|
|
10
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
11
|
+
case "number":
|
|
12
|
+
if (!Number.isFinite(value)) throw new Error(`Invalid number: ${value}`);
|
|
13
|
+
return String(value);
|
|
14
|
+
case "boolean":
|
|
15
|
+
return String(value);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function renderFilter(node) {
|
|
19
|
+
switch (node.type) {
|
|
20
|
+
case "comparison":
|
|
21
|
+
return `${node.field} ${node.op} ${formatValue(node.value)}`;
|
|
22
|
+
case "function":
|
|
23
|
+
return `${node.name}(${node.field},${formatValue(node.value)})`;
|
|
24
|
+
case "not":
|
|
25
|
+
return `not (${renderFilter(node.condition)})`;
|
|
26
|
+
case "group": {
|
|
27
|
+
if (node.conditions.length === 0) {
|
|
28
|
+
throw new Error("Filter group must contain at least one condition");
|
|
29
|
+
}
|
|
30
|
+
const parts = node.conditions.map((child) => {
|
|
31
|
+
const text = renderFilter(child);
|
|
32
|
+
const needsParens = child.type === "group" && child.op !== node.op;
|
|
33
|
+
return needsParens ? `(${text})` : text;
|
|
34
|
+
});
|
|
35
|
+
return parts.join(` ${node.op} `);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// src/encode.ts
|
|
41
|
+
var TOKEN = /'(?:[^']|'')*'| /g;
|
|
42
|
+
function encodeQuery(query) {
|
|
43
|
+
return query.replace(
|
|
44
|
+
TOKEN,
|
|
45
|
+
(match) => match === " " ? "%20" : encodeURIComponent(match)
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/helpers.ts
|
|
50
|
+
var cmp = (op) => (field, value) => ({
|
|
51
|
+
type: "comparison",
|
|
52
|
+
field,
|
|
53
|
+
op,
|
|
54
|
+
value
|
|
55
|
+
});
|
|
56
|
+
var eq = cmp("eq");
|
|
57
|
+
var ne = cmp("ne");
|
|
58
|
+
var gt = cmp("gt");
|
|
59
|
+
var ge = cmp("ge");
|
|
60
|
+
var lt = cmp("lt");
|
|
61
|
+
var le = cmp("le");
|
|
62
|
+
var fn = (name) => (field, value) => ({
|
|
63
|
+
type: "function",
|
|
64
|
+
name,
|
|
65
|
+
field,
|
|
66
|
+
value
|
|
67
|
+
});
|
|
68
|
+
var contains = fn("contains");
|
|
69
|
+
var startsWith = fn("startswith");
|
|
70
|
+
var endsWith = fn("endswith");
|
|
71
|
+
var and = (...conditions) => ({
|
|
72
|
+
type: "group",
|
|
73
|
+
op: "and",
|
|
74
|
+
conditions
|
|
75
|
+
});
|
|
76
|
+
var or = (...conditions) => ({
|
|
77
|
+
type: "group",
|
|
78
|
+
op: "or",
|
|
79
|
+
conditions
|
|
80
|
+
});
|
|
81
|
+
var not = (condition) => ({
|
|
82
|
+
type: "not",
|
|
83
|
+
condition
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// src/index.ts
|
|
87
|
+
var top = (n) => n === void 0 ? void 0 : `$top=${n}`;
|
|
88
|
+
var skip = (n) => n === void 0 ? void 0 : `$skip=${n}`;
|
|
89
|
+
var count = (b) => b === void 0 ? void 0 : `$count=${b}`;
|
|
90
|
+
var select = (fields) => fields && fields.length ? `$select=${fields.join(",")}` : void 0;
|
|
91
|
+
var orderBy = (items) => {
|
|
92
|
+
if (!items || !items.length) return void 0;
|
|
93
|
+
const parts = items.map(
|
|
94
|
+
(item) => typeof item === "string" ? item : item.direction ? `${item.field} ${item.direction}` : item.field
|
|
95
|
+
);
|
|
96
|
+
return `$orderby=${parts.join(",")}`;
|
|
97
|
+
};
|
|
98
|
+
var filter = (node) => node === void 0 ? void 0 : `$filter=${renderFilter(node)}`;
|
|
99
|
+
var expand = (items) => items?.length ? `$expand=${items.map(renderExpandItem).join(",")}` : void 0;
|
|
100
|
+
function renderParts(options = {}) {
|
|
101
|
+
return [
|
|
102
|
+
top(options.top),
|
|
103
|
+
skip(options.skip),
|
|
104
|
+
count(options.count),
|
|
105
|
+
filter(options.filter),
|
|
106
|
+
select(options.select),
|
|
107
|
+
orderBy(options.orderBy),
|
|
108
|
+
expand(options.expand)
|
|
109
|
+
].filter((p) => p !== void 0);
|
|
110
|
+
}
|
|
111
|
+
function build(options = {}, config = {}) {
|
|
112
|
+
const { encode = true } = config;
|
|
113
|
+
const query = renderParts(options).join("&");
|
|
114
|
+
if (!query) return "";
|
|
115
|
+
return `?${encode ? encodeQuery(query) : query}`;
|
|
116
|
+
}
|
|
117
|
+
function renderExpandItem(item) {
|
|
118
|
+
if (typeof item === "string") return item;
|
|
119
|
+
const inner = renderParts(item.options).join(";");
|
|
120
|
+
return inner ? `${item.path}(${inner})` : item.path;
|
|
121
|
+
}
|
|
122
|
+
export {
|
|
123
|
+
and,
|
|
124
|
+
build,
|
|
125
|
+
contains,
|
|
126
|
+
endsWith,
|
|
127
|
+
eq,
|
|
128
|
+
ge,
|
|
129
|
+
gt,
|
|
130
|
+
le,
|
|
131
|
+
lt,
|
|
132
|
+
ne,
|
|
133
|
+
not,
|
|
134
|
+
or,
|
|
135
|
+
startsWith
|
|
136
|
+
};
|
|
137
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/filter.ts","../src/encode.ts","../src/helpers.ts","../src/index.ts"],"sourcesContent":["export type FilterValue = string | number | boolean | null | Date;\r\n\r\nexport type ComparisonOp = \"eq\" | \"ne\" | \"gt\" | \"ge\" | \"lt\" | \"le\";\r\nexport type FilterFn = \"contains\" | \"startswith\" | \"endswith\";\r\n\r\nexport type FilterNode =\r\n | { type: \"comparison\"; field: string; op: ComparisonOp; value: FilterValue }\r\n | { type: \"function\"; name: FilterFn; field: string; value: string }\r\n | { type: \"group\"; op: \"and\" | \"or\"; conditions: FilterNode[] }\r\n | { type: \"not\"; condition: FilterNode };\r\n\r\nexport function formatValue(value: FilterValue): string {\r\n if (value === null) return \"null\";\r\n if (value instanceof Date) {\r\n if (Number.isNaN(value.getTime())) throw new Error(\"Invalid Date\");\r\n return value.toISOString();\r\n }\r\n switch (typeof value) {\r\n case \"string\":\r\n return `'${value.replace(/'/g, \"''\")}'`;\r\n case \"number\":\r\n if (!Number.isFinite(value)) throw new Error(`Invalid number: ${value}`);\r\n return String(value);\r\n case \"boolean\":\r\n return String(value);\r\n }\r\n}\r\n\r\nexport function renderFilter(node: FilterNode): string {\r\n switch (node.type) {\r\n case \"comparison\":\r\n return `${node.field} ${node.op} ${formatValue(node.value)}`;\r\n\r\n case \"function\":\r\n return `${node.name}(${node.field},${formatValue(node.value)})`;\r\n\r\n case \"not\":\r\n return `not (${renderFilter(node.condition)})`;\r\n\r\n case \"group\": {\r\n if (node.conditions.length === 0) {\r\n throw new Error(\"Filter group must contain at least one condition\");\r\n }\r\n const parts = node.conditions.map((child) => {\r\n const text = renderFilter(child);\r\n const needsParens = child.type === \"group\" && child.op !== node.op;\r\n return needsParens ? `(${text})` : text;\r\n });\r\n return parts.join(` ${node.op} `);\r\n }\r\n }\r\n}\r\n","// Matches a whole OData string literal ('' is an escaped quote inside it) or a space.\r\nconst TOKEN = /'(?:[^']|'')*'| /g;\r\n\r\nexport function encodeQuery(query: string): string {\r\n return query.replace(TOKEN, (match) =>\r\n match === \" \" ? \"%20\" : encodeURIComponent(match),\r\n );\r\n}\r\n","import type {\r\n ComparisonOp,\r\n FilterFn,\r\n FilterNode,\r\n FilterValue,\r\n} from \"./filter.js\";\r\n\r\nconst cmp =\r\n (op: ComparisonOp) =>\r\n (field: string, value: FilterValue): FilterNode => ({\r\n type: \"comparison\",\r\n field,\r\n op,\r\n value,\r\n });\r\n\r\nexport const eq = cmp(\"eq\");\r\nexport const ne = cmp(\"ne\");\r\nexport const gt = cmp(\"gt\");\r\nexport const ge = cmp(\"ge\");\r\nexport const lt = cmp(\"lt\");\r\nexport const le = cmp(\"le\");\r\n\r\nconst fn =\r\n (name: FilterFn) =>\r\n (field: string, value: string): FilterNode => ({\r\n type: \"function\",\r\n name,\r\n field,\r\n value,\r\n });\r\n\r\nexport const contains = fn(\"contains\");\r\nexport const startsWith = fn(\"startswith\");\r\nexport const endsWith = fn(\"endswith\");\r\n\r\nexport const and = (...conditions: FilterNode[]): FilterNode => ({\r\n type: \"group\",\r\n op: \"and\",\r\n conditions,\r\n});\r\n\r\nexport const or = (...conditions: FilterNode[]): FilterNode => ({\r\n type: \"group\",\r\n op: \"or\",\r\n conditions,\r\n});\r\n\r\nexport const not = (condition: FilterNode): FilterNode => ({\r\n type: \"not\",\r\n condition,\r\n});\r\n","import { renderFilter, type FilterNode } from \"./filter.js\";\r\nimport { encodeQuery } from \"./encode.js\";\r\n\r\nexport interface BuildConfig {\r\n /** Percent-encode the result (default: true). */\r\n encode?: boolean;\r\n}\r\nexport type OrderByItem =\r\n | string\r\n | { field: string; direction?: \"asc\" | \"desc\" };\r\n\r\nexport interface QueryOptions {\r\n top?: number;\r\n skip?: number;\r\n count?: boolean;\r\n select?: string[];\r\n orderBy?: OrderByItem[];\r\n filter?: FilterNode;\r\n expand?: ExpandItem[];\r\n}\r\n\r\nexport type ExpandItem = string | { path: string; options?: QueryOptions };\r\n\r\nconst top = (n?: number) => (n === undefined ? undefined : `$top=${n}`);\r\nconst skip = (n?: number) => (n === undefined ? undefined : `$skip=${n}`);\r\nconst count = (b?: boolean) => (b === undefined ? undefined : `$count=${b}`);\r\n\r\nconst select = (fields?: string[]) =>\r\n fields && fields.length ? `$select=${fields.join(\",\")}` : undefined;\r\n\r\nconst orderBy = (items?: OrderByItem[]) => {\r\n if (!items || !items.length) return undefined;\r\n const parts = items.map((item) =>\r\n typeof item === \"string\"\r\n ? item\r\n : item.direction\r\n ? `${item.field} ${item.direction}`\r\n : item.field,\r\n );\r\n return `$orderby=${parts.join(\",\")}`;\r\n};\r\n\r\nconst filter = (node?: FilterNode) =>\r\n node === undefined ? undefined : `$filter=${renderFilter(node)}`;\r\n\r\nconst expand = (items?: ExpandItem[]) =>\r\n items?.length\r\n ? `$expand=${items.map(renderExpandItem).join(\",\")}`\r\n : undefined;\r\n\r\nfunction renderParts(options: QueryOptions = {}): string[] {\r\n return [\r\n top(options.top),\r\n skip(options.skip),\r\n count(options.count),\r\n filter(options.filter),\r\n select(options.select),\r\n orderBy(options.orderBy),\r\n expand(options.expand),\r\n ].filter((p): p is string => p !== undefined);\r\n}\r\n\r\nexport function build(\r\n options: QueryOptions = {},\r\n config: BuildConfig = {},\r\n): string {\r\n const { encode = true } = config;\r\n const query = renderParts(options).join(\"&\");\r\n if (!query) return \"\";\r\n return `?${encode ? encodeQuery(query) : query}`;\r\n}\r\n\r\nfunction renderExpandItem(item: ExpandItem): string {\r\n if (typeof item === \"string\") return item;\r\n const inner = renderParts(item.options).join(\";\");\r\n return inner ? `${item.path}(${inner})` : item.path;\r\n}\r\n\r\nexport type {\r\n FilterNode,\r\n FilterValue,\r\n ComparisonOp,\r\n FilterFn,\r\n} from \"./filter.js\";\r\nexport {\r\n eq,\r\n ne,\r\n gt,\r\n ge,\r\n lt,\r\n le,\r\n contains,\r\n startsWith,\r\n endsWith,\r\n and,\r\n or,\r\n not,\r\n} from \"./helpers.js\";\r\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "odata-build-query",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Type-friendly builder for OData v4 query strings ($filter, $select, $orderby, $expand and more)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Varsha SD",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/sdv02/odata-query-builder.git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/sdv02/odata-query-builder#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/sdv02/odata-query-builder/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"odata",
|
|
18
|
+
"query",
|
|
19
|
+
"query-builder",
|
|
20
|
+
"typescript",
|
|
21
|
+
"rest"
|
|
22
|
+
],
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=18"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"tsup": "^8.5.1",
|
|
29
|
+
"typescript": "^7.0.2",
|
|
30
|
+
"vitest": "^5.0.1"
|
|
31
|
+
},
|
|
32
|
+
"main": "./dist/index.js",
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"import": "./dist/index.js"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"dist"
|
|
42
|
+
],
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsup && tsc -p tsconfig.build.json",
|
|
45
|
+
"test": "vitest run",
|
|
46
|
+
"test:watch": "vitest",
|
|
47
|
+
"typecheck": "tsc --noEmit",
|
|
48
|
+
"prepublishOnly": "npm test && npm run typecheck && npm run build"
|
|
49
|
+
}
|
|
50
|
+
}
|