@ucdjs-internal/worker-utils 0.0.1-beta.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-PRESENT Lucas Nørgård
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.
@@ -0,0 +1,200 @@
1
+ import { ApiError } from "@ucdjs/schemas";
2
+ import { Context } from "hono";
3
+ import { TypedResponse } from "hono/types";
4
+ import { ContentfulStatusCode } from "hono/utils/http-status";
5
+ import { ZodType, z } from "zod";
6
+
7
+ //#region src/cache.d.ts
8
+ type ClearCacheFn = (requestOrPath: Request | string) => Promise<void>;
9
+ declare function clearCacheEntry(name: string): Promise<ClearCacheFn>;
10
+ //#endregion
11
+ //#region src/environment.d.ts
12
+ type WorkerEnvironmentName = "production" | "preview" | "local" | "testing" | (string & {});
13
+ declare function getApiOriginForEnvironment(environment: WorkerEnvironmentName | undefined): string;
14
+ //#endregion
15
+ //#region src/errors.d.ts
16
+ interface ResponseOptions {
17
+ /**
18
+ * The message to include in the response.
19
+ */
20
+ message?: string;
21
+ /**
22
+ * Additional headers to include in the response.
23
+ * This can be used to set custom headers like `Content-Type`, `Cache-Control`,
24
+ * or any other headers that might be relevant to the response.
25
+ */
26
+ headers?: Record<string, string>;
27
+ }
28
+ /**
29
+ * Creates a standardized 400 Bad Request HTTP response with JSON error details.
30
+ *
31
+ * @param {Context | ResponseOptions} contextOrOptions - Hono context or configuration options
32
+ * @param {ResponseOptions?} options - Configuration options when context is provided
33
+ * @returns {Response} A Response object with 400 status and JSON error body
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * import { badRequest } from "../../lib";
38
+ *
39
+ * // Basic usage (legacy)
40
+ * return badRequest();
41
+ *
42
+ * // With custom message
43
+ * return badRequest({
44
+ * message: "Invalid request parameters",
45
+ * });
46
+ *
47
+ * // With Hono context (new)
48
+ * return badRequest(c, { message: "Invalid request parameters" });
49
+ * ```
50
+ */
51
+ declare function badRequest(contextOrOptions?: Context | ResponseOptions, options?: ResponseOptions): Response & TypedResponse<ApiError, 400, "json">;
52
+ /**
53
+ * Creates a standardized 403 Forbidden HTTP response with JSON error details.
54
+ *
55
+ * @param {Context | ResponseOptions} contextOrOptions - Hono context or configuration options
56
+ * @param {ResponseOptions?} options - Configuration options when context is provided
57
+ * @returns {Response} A Response object with 403 status and JSON error body
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * import { forbidden } from "../../lib";
62
+ *
63
+ * // Basic usage (legacy)
64
+ * return forbidden();
65
+ *
66
+ * // With custom message (legacy)
67
+ * return forbidden({
68
+ * message: "Access denied to this resource"
69
+ * });
70
+ *
71
+ * // With Hono context (new)
72
+ * return forbidden(c, { message: "Access denied to this resource" });
73
+ * ```
74
+ */
75
+ declare function forbidden(contextOrOptions?: Context | ResponseOptions, options?: ResponseOptions): Response & TypedResponse<ApiError, 403, "json">;
76
+ /**
77
+ * Creates a standardized 404 Not Found HTTP response with JSON error details.
78
+ *
79
+ * @param {Context | ResponseOptions} contextOrOptions - Hono context or configuration options
80
+ * @param {ResponseOptions?} options - Configuration options when context is provided
81
+ * @returns {Response} A Response object with 404 status and JSON error body
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * import { notFound } from "../../lib";
86
+ *
87
+ * // Basic usage (legacy)
88
+ * return notFound();
89
+ *
90
+ * // With custom message (legacy)
91
+ * return notFound({
92
+ * message: "User not found"
93
+ * });
94
+ *
95
+ * // With Hono context (new)
96
+ * return notFound(c, { message: "User not found" });
97
+ * ```
98
+ */
99
+ declare function notFound(contextOrOptions?: Context | ResponseOptions, options?: ResponseOptions): Response & TypedResponse<ApiError, 404, "json">;
100
+ /**
101
+ * Creates a standardized 500 Internal Server Error HTTP response with JSON error details.
102
+ *
103
+ * @param {Context | ResponseOptions} contextOrOptions - Hono context or configuration options
104
+ * @param {ResponseOptions?} options - Configuration options when context is provided
105
+ * @returns {Response} A Response object with 500 status and JSON error body
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * import { internalServerError } from "../../lib";
110
+ *
111
+ * // Basic usage (legacy)
112
+ * return internalServerError();
113
+ *
114
+ * // With custom message (legacy)
115
+ * return internalServerError({
116
+ * message: "Database connection failed"
117
+ * });
118
+ *
119
+ * // With Hono context (new)
120
+ * return internalServerError(c, { message: "Database connection failed" });
121
+ * ```
122
+ */
123
+ declare function internalServerError(contextOrOptions?: Context | ResponseOptions, options?: ResponseOptions): Response & TypedResponse<ApiError, 500, "json">;
124
+ declare function badGateway(contextOrOptions?: Context | ResponseOptions, options?: ResponseOptions): Response & TypedResponse<ApiError, 502, "json">;
125
+ declare function unauthorized(contextOrOptions?: Context | ResponseOptions, options?: ResponseOptions): Response & TypedResponse<ApiError, 401, "json">;
126
+ type CustomResponseOptions = Omit<Required<ResponseOptions>, "headers"> & {
127
+ /**
128
+ * Custom headers to include in the response.
129
+ * This can be used to set headers like `Content-Type`, `Cache-Control`, etc.
130
+ */
131
+ headers?: Record<string, string>;
132
+ /**
133
+ * The HTTP status code to use for the response.
134
+ * This should be a valid @see {ContentfulStatusCode}.
135
+ */
136
+ status: number;
137
+ };
138
+ type CustomResponseOptionsWithContext = CustomResponseOptions & {
139
+ /**
140
+ * Custom headers to include in the response.
141
+ * This can be used to set headers like `Content-Type`, `Cache-Control`, etc.
142
+ */
143
+ headers?: Record<string, string>;
144
+ /**
145
+ * The HTTP status code to use for the response.
146
+ * This should be a valid @see {ContentfulStatusCode}.
147
+ */
148
+ status: number;
149
+ };
150
+ /**
151
+ * Creates a custom HTTP error response with specified status code and JSON error details.
152
+ * This function allows for flexible error responses with any valid HTTP status code.
153
+ *
154
+ * @param {Context | CustomResponseOptions} contextOrOptions - Hono context or configuration options
155
+ * @param {CustomResponseOptionsWithContext?} options - Configuration options when context is provided
156
+ * @returns {Response} A Response object with the specified status and JSON error body
157
+ *
158
+ * @example
159
+ * ```typescript
160
+ * import { customError } from "../../lib";
161
+ *
162
+ * // Custom 422 Unprocessable Entity error (legacy)
163
+ * return customError({
164
+ * status: 422,
165
+ * message: "Validation failed",
166
+ * });
167
+ *
168
+ * // Custom 429 Too Many Requests error with headers (legacy)
169
+ * return customError({
170
+ * status: 429,
171
+ * message: "Rate limit exceeded",
172
+ * headers: {
173
+ * "Retry-After": "3600"
174
+ * }
175
+ * });
176
+ *
177
+ * // With Hono context (new)
178
+ * return customError(c, {
179
+ * status: 422,
180
+ * message: "Validation failed"
181
+ * });
182
+ * ```
183
+ */
184
+ declare function customError(contextOrOptions: Context | CustomResponseOptions, options?: CustomResponseOptionsWithContext): Response;
185
+ //#endregion
186
+ //#region src/hostnames.d.ts
187
+ declare function isStoreSubdomainHostname(hostname: string): boolean;
188
+ //#endregion
189
+ //#region src/strict.d.ts
190
+ declare function strictJSONResponse<C extends Context, S extends ZodType, D extends Parameters<Context["json"]>[0] & z.infer<S>, U extends ContentfulStatusCode>(c: C, schema: S, data: D, statusCode?: U): Response;
191
+ //#endregion
192
+ //#region src/tasks.d.ts
193
+ declare const MAX_TAR_SIZE_BYTES: number;
194
+ declare const MAX_WORKFLOW_INSTANCE_ID_LENGTH = 100;
195
+ declare const ALLOWED_STRING_ID_PATTERN = "^\\w[\\w-]*$";
196
+ declare function makeManifestUploadId(version: string, now?: () => number): string;
197
+ declare function isValidWorkflowInstanceId(id: string): boolean;
198
+ declare function buildR2Key(version: string, workflowId: string): string;
199
+ //#endregion
200
+ export { ALLOWED_STRING_ID_PATTERN, ClearCacheFn, CustomResponseOptions, CustomResponseOptionsWithContext, MAX_TAR_SIZE_BYTES, MAX_WORKFLOW_INSTANCE_ID_LENGTH, ResponseOptions, WorkerEnvironmentName, badGateway, badRequest, buildR2Key, clearCacheEntry, customError, forbidden, getApiOriginForEnvironment, internalServerError, isStoreSubdomainHostname, isValidWorkflowInstanceId, makeManifestUploadId, notFound, strictJSONResponse, unauthorized };
package/dist/index.mjs ADDED
@@ -0,0 +1,297 @@
1
+ //#region src/cache.ts
2
+ async function clearCacheEntry(name) {
3
+ let cachePromise = null;
4
+ return async (requestOrPath) => {
5
+ if (!cachePromise) cachePromise = caches.open(name);
6
+ const cache = await cachePromise;
7
+ const request = typeof requestOrPath === "string" ? new Request(requestOrPath) : requestOrPath;
8
+ await cache.delete(request);
9
+ };
10
+ }
11
+
12
+ //#endregion
13
+ //#region src/environment.ts
14
+ function getApiOriginForEnvironment(environment) {
15
+ if (environment === "production") return "https://api.ucdjs.dev";
16
+ if (environment === "preview") return "https://preview.api.ucdjs.dev";
17
+ return "http://localhost:8787";
18
+ }
19
+
20
+ //#endregion
21
+ //#region src/errors.ts
22
+ /**
23
+ * Creates a standardized 400 Bad Request HTTP response with JSON error details.
24
+ *
25
+ * @param {Context | ResponseOptions} contextOrOptions - Hono context or configuration options
26
+ * @param {ResponseOptions?} options - Configuration options when context is provided
27
+ * @returns {Response} A Response object with 400 status and JSON error body
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * import { badRequest } from "../../lib";
32
+ *
33
+ * // Basic usage (legacy)
34
+ * return badRequest();
35
+ *
36
+ * // With custom message
37
+ * return badRequest({
38
+ * message: "Invalid request parameters",
39
+ * });
40
+ *
41
+ * // With Hono context (new)
42
+ * return badRequest(c, { message: "Invalid request parameters" });
43
+ * ```
44
+ */
45
+ function badRequest(contextOrOptions = {}, options = {}) {
46
+ let finalOptions;
47
+ if ("req" in contextOrOptions) finalOptions = options;
48
+ else finalOptions = contextOrOptions;
49
+ return Response.json({
50
+ message: finalOptions.message || "Bad Request",
51
+ status: 400,
52
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
53
+ }, {
54
+ status: 400,
55
+ headers: {
56
+ "Content-Type": "application/json",
57
+ ...finalOptions.headers
58
+ }
59
+ });
60
+ }
61
+ /**
62
+ * Creates a standardized 403 Forbidden HTTP response with JSON error details.
63
+ *
64
+ * @param {Context | ResponseOptions} contextOrOptions - Hono context or configuration options
65
+ * @param {ResponseOptions?} options - Configuration options when context is provided
66
+ * @returns {Response} A Response object with 403 status and JSON error body
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * import { forbidden } from "../../lib";
71
+ *
72
+ * // Basic usage (legacy)
73
+ * return forbidden();
74
+ *
75
+ * // With custom message (legacy)
76
+ * return forbidden({
77
+ * message: "Access denied to this resource"
78
+ * });
79
+ *
80
+ * // With Hono context (new)
81
+ * return forbidden(c, { message: "Access denied to this resource" });
82
+ * ```
83
+ */
84
+ function forbidden(contextOrOptions = {}, options = {}) {
85
+ let finalOptions;
86
+ if ("req" in contextOrOptions) finalOptions = options;
87
+ else finalOptions = contextOrOptions;
88
+ return Response.json({
89
+ message: finalOptions.message || "Forbidden",
90
+ status: 403,
91
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
92
+ }, {
93
+ status: 403,
94
+ headers: {
95
+ "Content-Type": "application/json",
96
+ ...finalOptions.headers
97
+ }
98
+ });
99
+ }
100
+ /**
101
+ * Creates a standardized 404 Not Found HTTP response with JSON error details.
102
+ *
103
+ * @param {Context | ResponseOptions} contextOrOptions - Hono context or configuration options
104
+ * @param {ResponseOptions?} options - Configuration options when context is provided
105
+ * @returns {Response} A Response object with 404 status and JSON error body
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * import { notFound } from "../../lib";
110
+ *
111
+ * // Basic usage (legacy)
112
+ * return notFound();
113
+ *
114
+ * // With custom message (legacy)
115
+ * return notFound({
116
+ * message: "User not found"
117
+ * });
118
+ *
119
+ * // With Hono context (new)
120
+ * return notFound(c, { message: "User not found" });
121
+ * ```
122
+ */
123
+ function notFound(contextOrOptions = {}, options = {}) {
124
+ let finalOptions;
125
+ if ("req" in contextOrOptions) finalOptions = options;
126
+ else finalOptions = contextOrOptions;
127
+ return Response.json({
128
+ message: finalOptions.message || "Not Found",
129
+ status: 404,
130
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
131
+ }, {
132
+ status: 404,
133
+ headers: {
134
+ "Content-Type": "application/json",
135
+ ...finalOptions.headers
136
+ }
137
+ });
138
+ }
139
+ /**
140
+ * Creates a standardized 500 Internal Server Error HTTP response with JSON error details.
141
+ *
142
+ * @param {Context | ResponseOptions} contextOrOptions - Hono context or configuration options
143
+ * @param {ResponseOptions?} options - Configuration options when context is provided
144
+ * @returns {Response} A Response object with 500 status and JSON error body
145
+ *
146
+ * @example
147
+ * ```typescript
148
+ * import { internalServerError } from "../../lib";
149
+ *
150
+ * // Basic usage (legacy)
151
+ * return internalServerError();
152
+ *
153
+ * // With custom message (legacy)
154
+ * return internalServerError({
155
+ * message: "Database connection failed"
156
+ * });
157
+ *
158
+ * // With Hono context (new)
159
+ * return internalServerError(c, { message: "Database connection failed" });
160
+ * ```
161
+ */
162
+ function internalServerError(contextOrOptions = {}, options = {}) {
163
+ let finalOptions;
164
+ if ("req" in contextOrOptions) finalOptions = options;
165
+ else finalOptions = contextOrOptions;
166
+ return Response.json({
167
+ message: finalOptions.message || "Internal Server Error",
168
+ status: 500,
169
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
170
+ }, {
171
+ status: 500,
172
+ headers: {
173
+ "Content-Type": "application/json",
174
+ ...finalOptions.headers
175
+ }
176
+ });
177
+ }
178
+ function badGateway(contextOrOptions = {}, options = {}) {
179
+ let finalOptions;
180
+ if ("req" in contextOrOptions) finalOptions = options;
181
+ else finalOptions = contextOrOptions;
182
+ return Response.json({
183
+ message: finalOptions.message || "Bad Gateway",
184
+ status: 502,
185
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
186
+ }, {
187
+ status: 502,
188
+ headers: {
189
+ "Content-Type": "application/json",
190
+ ...finalOptions.headers
191
+ }
192
+ });
193
+ }
194
+ function unauthorized(contextOrOptions = {}, options = {}) {
195
+ let finalOptions;
196
+ if ("req" in contextOrOptions) finalOptions = options;
197
+ else finalOptions = contextOrOptions;
198
+ return Response.json({
199
+ message: finalOptions.message || "Unauthorized",
200
+ status: 401,
201
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
202
+ }, {
203
+ status: 401,
204
+ headers: {
205
+ "Content-Type": "application/json",
206
+ ...finalOptions.headers
207
+ }
208
+ });
209
+ }
210
+ /**
211
+ * Creates a custom HTTP error response with specified status code and JSON error details.
212
+ * This function allows for flexible error responses with any valid HTTP status code.
213
+ *
214
+ * @param {Context | CustomResponseOptions} contextOrOptions - Hono context or configuration options
215
+ * @param {CustomResponseOptionsWithContext?} options - Configuration options when context is provided
216
+ * @returns {Response} A Response object with the specified status and JSON error body
217
+ *
218
+ * @example
219
+ * ```typescript
220
+ * import { customError } from "../../lib";
221
+ *
222
+ * // Custom 422 Unprocessable Entity error (legacy)
223
+ * return customError({
224
+ * status: 422,
225
+ * message: "Validation failed",
226
+ * });
227
+ *
228
+ * // Custom 429 Too Many Requests error with headers (legacy)
229
+ * return customError({
230
+ * status: 429,
231
+ * message: "Rate limit exceeded",
232
+ * headers: {
233
+ * "Retry-After": "3600"
234
+ * }
235
+ * });
236
+ *
237
+ * // With Hono context (new)
238
+ * return customError(c, {
239
+ * status: 422,
240
+ * message: "Validation failed"
241
+ * });
242
+ * ```
243
+ */
244
+ function customError(contextOrOptions, options) {
245
+ let finalOptions;
246
+ if ("req" in contextOrOptions) {
247
+ if (!options) throw new Error("Options parameter is required when using Hono context");
248
+ finalOptions = options;
249
+ } else finalOptions = contextOrOptions;
250
+ return Response.json({
251
+ message: finalOptions.message,
252
+ status: finalOptions.status,
253
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
254
+ }, {
255
+ status: finalOptions.status,
256
+ headers: {
257
+ "Content-Type": "application/json",
258
+ ...finalOptions.headers
259
+ }
260
+ });
261
+ }
262
+
263
+ //#endregion
264
+ //#region src/hostnames.ts
265
+ function isStoreSubdomainHostname(hostname) {
266
+ return hostname === "ucd-store.ucdjs.dev" || hostname === "preview.ucd-store.ucdjs.dev" || hostname === "ucd-store.localhost";
267
+ }
268
+
269
+ //#endregion
270
+ //#region src/strict.ts
271
+ function strictJSONResponse(c, schema, data, statusCode) {
272
+ const validatedResponse = schema.safeParse(data);
273
+ if (!validatedResponse.success) return customError({
274
+ status: 400,
275
+ message: `Invalid response data: ${validatedResponse.error.message}`
276
+ });
277
+ return c.json(validatedResponse.data, statusCode);
278
+ }
279
+
280
+ //#endregion
281
+ //#region src/tasks.ts
282
+ const MAX_TAR_SIZE_BYTES = 10 * 1024 * 1024;
283
+ const MAX_WORKFLOW_INSTANCE_ID_LENGTH = 100;
284
+ const ALLOWED_STRING_ID_PATTERN = "^\\w[\\w-]*$";
285
+ const ALLOWED_WORKFLOW_INSTANCE_ID_REGEX = new RegExp(ALLOWED_STRING_ID_PATTERN);
286
+ function makeManifestUploadId(version, now = Date.now) {
287
+ return `manifest-upload-${version.replace(/\./g, "-")}-${now()}`;
288
+ }
289
+ function isValidWorkflowInstanceId(id) {
290
+ return id.length <= MAX_WORKFLOW_INSTANCE_ID_LENGTH && ALLOWED_WORKFLOW_INSTANCE_ID_REGEX.test(id);
291
+ }
292
+ function buildR2Key(version, workflowId) {
293
+ return `manifest-tars/${version}/${workflowId}.tar`;
294
+ }
295
+
296
+ //#endregion
297
+ export { ALLOWED_STRING_ID_PATTERN, MAX_TAR_SIZE_BYTES, MAX_WORKFLOW_INSTANCE_ID_LENGTH, badGateway, badRequest, buildR2Key, clearCacheEntry, customError, forbidden, getApiOriginForEnvironment, internalServerError, isStoreSubdomainHostname, isValidWorkflowInstanceId, makeManifestUploadId, notFound, strictJSONResponse, unauthorized };
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@ucdjs-internal/worker-utils",
3
+ "version": "0.0.1-beta.1",
4
+ "type": "module",
5
+ "author": {
6
+ "name": "Lucas Nørgård",
7
+ "email": "lucasnrgaard@gmail.com",
8
+ "url": "https://luxass.dev"
9
+ },
10
+ "license": "MIT",
11
+ "homepage": "https://github.com/ucdjs/ucd",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/ucdjs/ucd.git",
15
+ "directory": "packages/worker-utils"
16
+ },
17
+ "bugs": {
18
+ "url": "https://github.com/ucdjs/ucd/issues"
19
+ },
20
+ "exports": {
21
+ ".": "./dist/index.mjs",
22
+ "./package.json": "./package.json"
23
+ },
24
+ "types": "./dist/index.d.mts",
25
+ "files": [
26
+ "dist"
27
+ ],
28
+ "engines": {
29
+ "node": ">=22.18"
30
+ },
31
+ "peerDependencies": {
32
+ "hono": "4.11.9",
33
+ "zod": "4.3.6"
34
+ },
35
+ "dependencies": {
36
+ "@ucdjs-internal/shared": "0.1.1-beta.1",
37
+ "@ucdjs/schemas": "0.1.1-beta.1"
38
+ },
39
+ "devDependencies": {
40
+ "@luxass/eslint-config": "7.2.0",
41
+ "eslint": "10.0.0",
42
+ "hono": "4.11.9",
43
+ "publint": "0.3.17",
44
+ "tsdown": "0.20.3",
45
+ "typescript": "5.9.3",
46
+ "vitest-testdirs": "4.4.2",
47
+ "zod": "4.3.6",
48
+ "@ucdjs-tooling/tsdown-config": "1.0.0",
49
+ "@ucdjs-tooling/tsconfig": "1.0.0"
50
+ },
51
+ "publishConfig": {
52
+ "access": "public"
53
+ },
54
+ "scripts": {
55
+ "build": "tsdown --tsconfig=./tsconfig.build.json",
56
+ "dev": "tsdown --watch",
57
+ "clean": "git clean -xdf dist node_modules",
58
+ "lint": "eslint .",
59
+ "typecheck": "tsc --noEmit -p tsconfig.build.json"
60
+ }
61
+ }