@varmdev/api-kit 0.1.7
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 +121 -0
- package/dist/core/apiRegistry.d.ts +46 -0
- package/dist/core/apiRegistry.d.ts.map +1 -0
- package/dist/core/apiRegistry.js +122 -0
- package/dist/core/apiRegistry.js.map +1 -0
- package/dist/core/cache.d.ts +14 -0
- package/dist/core/cache.d.ts.map +1 -0
- package/dist/core/cache.js +26 -0
- package/dist/core/cache.js.map +1 -0
- package/dist/core/client.d.ts +29 -0
- package/dist/core/client.d.ts.map +1 -0
- package/dist/core/client.js +56 -0
- package/dist/core/client.js.map +1 -0
- package/dist/core/endpoint.d.ts +54 -0
- package/dist/core/endpoint.d.ts.map +1 -0
- package/dist/core/endpoint.js +10 -0
- package/dist/core/endpoint.js.map +1 -0
- package/dist/core/errors.d.ts +22 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +24 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +8 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/query.d.ts +20 -0
- package/dist/core/query.d.ts.map +1 -0
- package/dist/core/query.js +54 -0
- package/dist/core/query.js.map +1 -0
- package/dist/core/responses.d.ts +20 -0
- package/dist/core/responses.d.ts.map +1 -0
- package/dist/core/responses.js +12 -0
- package/dist/core/responses.js.map +1 -0
- package/dist/sveltekit/apiHandler.d.ts +23 -0
- package/dist/sveltekit/apiHandler.d.ts.map +1 -0
- package/dist/sveltekit/apiHandler.js +105 -0
- package/dist/sveltekit/apiHandler.js.map +1 -0
- package/dist/sveltekit/index.d.ts +2 -0
- package/dist/sveltekit/index.d.ts.map +1 -0
- package/dist/sveltekit/index.js +2 -0
- package/dist/sveltekit/index.js.map +1 -0
- package/package.json +81 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 VARM
|
|
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,121 @@
|
|
|
1
|
+
# @varmdev/api-kit
|
|
2
|
+
|
|
3
|
+
`api-kit` — это универсальный набор для создания типизированных API на TypeScript. Он помогает описывать контракт эндпоинта, валидировать входные данные, держать единый формат ответов, собирать OpenAPI-спецификацию и подключать это к SvelteKit.
|
|
4
|
+
|
|
5
|
+
Пакет не знает ничего о вашей базе данных, бизнес-логике и конкретной авторизации. Он даёт инфраструктурный слой, а приложение решает, как именно получать пользователя, как проверять права и что делать внутри хендлера.
|
|
6
|
+
|
|
7
|
+
## Что Умеет Пакет
|
|
8
|
+
|
|
9
|
+
- описывать endpoint как контракт через `defineEndpoint`;
|
|
10
|
+
- валидировать `params`, `query`, `body` и `response` через Zod;
|
|
11
|
+
- стандартизировать успешные и ошибочные JSON-ответы;
|
|
12
|
+
- поднимать `ApiKitError` для ожидаемых HTTP-ошибок;
|
|
13
|
+
- накапливать OpenAPI-метаданные и генерировать спецификацию;
|
|
14
|
+
- давать `typedFetch` для клиентского кода;
|
|
15
|
+
- давать `generateQuerySchema` для query-параметров;
|
|
16
|
+
- адаптировать всё это под SvelteKit через `apiHandler`.
|
|
17
|
+
|
|
18
|
+
## Когда Он Полезен
|
|
19
|
+
|
|
20
|
+
- когда в проекте много endpoint-ов и хочется держать их в одном стиле;
|
|
21
|
+
- когда хочется, чтобы типы, валидация и OpenAPI жили из одного описания;
|
|
22
|
+
- когда нужно переиспользовать один и тот же подход в нескольких проектах;
|
|
23
|
+
- когда SvelteKit нужен только как транспорт, а не как место для всей логики API.
|
|
24
|
+
|
|
25
|
+
## Структура
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
src/core/
|
|
29
|
+
endpoint.ts # defineEndpoint и типы endpoint-контракта
|
|
30
|
+
apiRegistry.ts # OpenAPI registry и генерация документа
|
|
31
|
+
client.ts # typedFetch и вывод типов endpoint-а
|
|
32
|
+
query.ts # generateQuerySchema для URL query
|
|
33
|
+
errors.ts # ApiKitError и преобразование Zod issues
|
|
34
|
+
responses.ts # success/error response schemas
|
|
35
|
+
cache.ts # cache policy -> HTTP headers
|
|
36
|
+
|
|
37
|
+
src/sveltekit/
|
|
38
|
+
apiHandler.ts # адаптер EndpointDefinition -> SvelteKit RequestHandler
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`src/core` не зависит от SvelteKit. Вся SvelteKit-специфика остаётся в `src/sveltekit`.
|
|
42
|
+
|
|
43
|
+
## Точки Входа
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { defineEndpoint } from '@varmdev/api-kit/core';
|
|
47
|
+
import { createOpenApiRegistry } from '@varmdev/api-kit/apiRegistry';
|
|
48
|
+
import { apiHandler } from '@varmdev/api-kit/apiHandler';
|
|
49
|
+
import { typedFetch } from '@varmdev/api-kit/client';
|
|
50
|
+
import { generateQuerySchema } from '@varmdev/api-kit/query';
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Если нужен явный путь для SvelteKit-адаптера:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { apiHandler } from '@varmdev/api-kit/sveltekit/apiHandler';
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Как Это Выглядит
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { z } from 'zod';
|
|
63
|
+
import { defineEndpoint } from '@varmdev/api-kit/core';
|
|
64
|
+
import { apiHandler } from '@varmdev/api-kit/sveltekit/apiHandler';
|
|
65
|
+
|
|
66
|
+
const endpoint = defineEndpoint({
|
|
67
|
+
querySchema: z.object({
|
|
68
|
+
q: z.string().optional()
|
|
69
|
+
}),
|
|
70
|
+
responseSchema: z.object({
|
|
71
|
+
items: z.array(z.string())
|
|
72
|
+
}),
|
|
73
|
+
openapi: {
|
|
74
|
+
method: 'GET',
|
|
75
|
+
path: '/api/examples',
|
|
76
|
+
summary: 'Example endpoint',
|
|
77
|
+
tags: ['Examples']
|
|
78
|
+
},
|
|
79
|
+
handler: async ({ query }) => ({
|
|
80
|
+
items: query.q ? [query.q] : []
|
|
81
|
+
})
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
export const GET = apiHandler(endpoint);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Установка
|
|
88
|
+
|
|
89
|
+
Локально в соседнем репозитории:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
bun add @varmdev/api-kit@file:../api-kit
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Из npm:
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"dependencies": {
|
|
100
|
+
"@varmdev/api-kit": "^0.1.7"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Или через `npm`:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
npm install @varmdev/api-kit
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Статус
|
|
112
|
+
|
|
113
|
+
Пакет в ранней версии. API может немного меняться до 1.0.
|
|
114
|
+
|
|
115
|
+
## Разработка
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
bun install
|
|
119
|
+
bun run check
|
|
120
|
+
bun run build
|
|
121
|
+
```
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { OpenAPIRegistry } from '@asteasolutions/zod-to-openapi';
|
|
2
|
+
import { type ZodType } from 'zod';
|
|
3
|
+
import type { EndpointDefinition, EndpointOpenApi, HttpMethod } from './endpoint.js';
|
|
4
|
+
export type { EndpointOpenApi, HttpMethod };
|
|
5
|
+
export type ApiKitOpenApiRegistry = {
|
|
6
|
+
registry: OpenAPIRegistry;
|
|
7
|
+
registerEndpoint: (endpoint: EndpointDefinition<ZodType | null, ZodType | null, ZodType | null>) => void;
|
|
8
|
+
generateDocument: (options?: {
|
|
9
|
+
title?: string;
|
|
10
|
+
version?: string;
|
|
11
|
+
}) => unknown;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Создает изолированный OpenAPI-реестр.
|
|
15
|
+
*
|
|
16
|
+
* Обычно приложение создает один реестр и импортирует все модули эндпоинтов
|
|
17
|
+
* перед генерацией документа. Так каждый эндпоинт успевает зарегистрировать
|
|
18
|
+
* себя. Именно так сейчас работает endpoint документации API в VARM.
|
|
19
|
+
*/
|
|
20
|
+
export declare const createOpenApiRegistry: () => ApiKitOpenApiRegistry;
|
|
21
|
+
export declare const defaultOpenApi: ApiKitOpenApiRegistry;
|
|
22
|
+
export declare const openApiRegistry: OpenAPIRegistry;
|
|
23
|
+
export declare const bearerAuthScheme: {
|
|
24
|
+
name: string;
|
|
25
|
+
ref: {
|
|
26
|
+
$ref: string;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export declare const apiKeyAuthScheme: {
|
|
30
|
+
name: string;
|
|
31
|
+
ref: {
|
|
32
|
+
$ref: string;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
export declare const refreshTokenCookieScheme: {
|
|
36
|
+
name: string;
|
|
37
|
+
ref: {
|
|
38
|
+
$ref: string;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
export declare const registerEndpoint: (endpoint: EndpointDefinition<ZodType | null, ZodType | null, ZodType | null>) => void;
|
|
42
|
+
export declare const generateOpenApiSpec: (options?: {
|
|
43
|
+
title?: string;
|
|
44
|
+
version?: string;
|
|
45
|
+
}) => unknown;
|
|
46
|
+
//# sourceMappingURL=apiRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiRegistry.d.ts","sourceRoot":"","sources":["../../src/core/apiRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,eAAe,EAGf,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAK,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AAEtC,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAIrF,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,CAAC;AAE5C,MAAM,MAAM,qBAAqB,GAAG;IACnC,QAAQ,EAAE,eAAe,CAAC;IAC1B,gBAAgB,EAAE,CAAC,QAAQ,EAAE,kBAAkB,CAAC,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC;IACzG,gBAAgB,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC;CAC9E,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,QAAO,qBA+FxC,CAAC;AAEF,eAAO,MAAM,cAAc,uBAA0B,CAAC;AAEtD,eAAO,MAAM,eAAe,iBAA0B,CAAC;AAEvD,eAAO,MAAM,gBAAgB;;;;;CAQ5B,CAAC;AAEF,eAAO,MAAM,gBAAgB;;;;;CAI3B,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;CAQpC,CAAC;AAEF,eAAO,MAAM,gBAAgB,aA1IC,kBAAkB,CAAC,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC,KAAK,IA0ItC,CAAC;AAChE,eAAO,MAAM,mBAAmB,aA1IF;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,KAAK,OA0IL,CAAC"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { OpenAPIRegistry, OpenApiGeneratorV31, extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { ApiErrorResponseSchema } from './responses.js';
|
|
4
|
+
extendZodWithOpenApi(z);
|
|
5
|
+
/**
|
|
6
|
+
* Создает изолированный OpenAPI-реестр.
|
|
7
|
+
*
|
|
8
|
+
* Обычно приложение создает один реестр и импортирует все модули эндпоинтов
|
|
9
|
+
* перед генерацией документа. Так каждый эндпоинт успевает зарегистрировать
|
|
10
|
+
* себя. Именно так сейчас работает endpoint документации API в VARM.
|
|
11
|
+
*/
|
|
12
|
+
export const createOpenApiRegistry = () => {
|
|
13
|
+
const registry = new OpenAPIRegistry();
|
|
14
|
+
return {
|
|
15
|
+
registry,
|
|
16
|
+
registerEndpoint(endpoint) {
|
|
17
|
+
const { method, path, summary, description, tags, security } = endpoint.openapi;
|
|
18
|
+
const roles = Array.from(endpoint.roles ?? []);
|
|
19
|
+
const responseStatus = method === 'POST' ? 201 : method === 'DELETE' ? 204 : 200;
|
|
20
|
+
const pathDefinition = {
|
|
21
|
+
method: method.toLowerCase(),
|
|
22
|
+
path,
|
|
23
|
+
summary,
|
|
24
|
+
description: roles.length
|
|
25
|
+
? `${description ?? ''}\n\nRequired roles: ${roles.join(', ')}`.trim()
|
|
26
|
+
: description,
|
|
27
|
+
tags,
|
|
28
|
+
security,
|
|
29
|
+
responses: {
|
|
30
|
+
400: {
|
|
31
|
+
description: 'Bad request / validation error',
|
|
32
|
+
content: {
|
|
33
|
+
'application/json': {
|
|
34
|
+
schema: ApiErrorResponseSchema
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
500: {
|
|
39
|
+
description: 'Server error',
|
|
40
|
+
content: {
|
|
41
|
+
'application/json': {
|
|
42
|
+
schema: ApiErrorResponseSchema
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
if (!pathDefinition.security && (endpoint.requireAuth || roles.length)) {
|
|
49
|
+
pathDefinition.security = [{ BearerAuth: [], ApiKeyAuth: [], RefreshTokenCookie: [] }];
|
|
50
|
+
}
|
|
51
|
+
if (endpoint.paramsSchema) {
|
|
52
|
+
pathDefinition.request = {
|
|
53
|
+
...pathDefinition.request,
|
|
54
|
+
params: endpoint.paramsSchema
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (endpoint.querySchema) {
|
|
58
|
+
pathDefinition.request = {
|
|
59
|
+
...pathDefinition.request,
|
|
60
|
+
query: endpoint.querySchema
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const requestBodySchema = endpoint.docsBodySchema ?? endpoint.bodySchema;
|
|
64
|
+
if (requestBodySchema) {
|
|
65
|
+
pathDefinition.request = {
|
|
66
|
+
...pathDefinition.request,
|
|
67
|
+
body: {
|
|
68
|
+
content: {
|
|
69
|
+
[endpoint.docsBodyContentType ?? 'application/json']: {
|
|
70
|
+
schema: requestBodySchema
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (endpoint.responseSchema && responseStatus !== 204) {
|
|
77
|
+
pathDefinition.responses[responseStatus] = {
|
|
78
|
+
description: 'Successful response',
|
|
79
|
+
content: {
|
|
80
|
+
'application/json': {
|
|
81
|
+
schema: endpoint.responseSchema
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
pathDefinition.responses[responseStatus] = { description: 'Successful response' };
|
|
88
|
+
}
|
|
89
|
+
registry.registerPath(pathDefinition);
|
|
90
|
+
},
|
|
91
|
+
generateDocument(options = {}) {
|
|
92
|
+
const generator = new OpenApiGeneratorV31(registry.definitions);
|
|
93
|
+
return generator.generateDocument({
|
|
94
|
+
openapi: '3.1.0',
|
|
95
|
+
info: {
|
|
96
|
+
title: options.title ?? 'API',
|
|
97
|
+
version: options.version ?? '1.0.0'
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
export const defaultOpenApi = createOpenApiRegistry();
|
|
104
|
+
export const openApiRegistry = defaultOpenApi.registry;
|
|
105
|
+
export const bearerAuthScheme = openApiRegistry.registerComponent('securitySchemes', 'BearerAuth', {
|
|
106
|
+
type: 'http',
|
|
107
|
+
scheme: 'bearer',
|
|
108
|
+
bearerFormat: 'JWT'
|
|
109
|
+
});
|
|
110
|
+
export const apiKeyAuthScheme = openApiRegistry.registerComponent('securitySchemes', 'ApiKeyAuth', {
|
|
111
|
+
type: 'apiKey',
|
|
112
|
+
in: 'header',
|
|
113
|
+
name: 'X-API-Key'
|
|
114
|
+
});
|
|
115
|
+
export const refreshTokenCookieScheme = openApiRegistry.registerComponent('securitySchemes', 'RefreshTokenCookie', {
|
|
116
|
+
type: 'apiKey',
|
|
117
|
+
in: 'cookie',
|
|
118
|
+
name: 'refresh_token'
|
|
119
|
+
});
|
|
120
|
+
export const registerEndpoint = defaultOpenApi.registerEndpoint;
|
|
121
|
+
export const generateOpenApiSpec = defaultOpenApi.generateDocument;
|
|
122
|
+
//# sourceMappingURL=apiRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiRegistry.js","sourceRoot":"","sources":["../../src/core/apiRegistry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type ApiCachePolicy = 'no-store' | {
|
|
2
|
+
scope?: 'private' | 'public';
|
|
3
|
+
maxAge: number;
|
|
4
|
+
staleWhileRevalidate?: number;
|
|
5
|
+
mustRevalidate?: boolean;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Преобразует декларативную политику кеширования в HTTP-заголовки.
|
|
9
|
+
*
|
|
10
|
+
* Функция остается независимой от фреймворка: адаптеры могут перенести эти
|
|
11
|
+
* заголовки в SvelteKit, Hono, Bun.serve или любую другую реализацию Web Response.
|
|
12
|
+
*/
|
|
13
|
+
export declare const toCacheHeaders: (policy: ApiCachePolicy) => Record<string, string>;
|
|
14
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GACvB,UAAU,GACV;IACA,KAAK,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEL;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,cAAc,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAoB5E,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Преобразует декларативную политику кеширования в HTTP-заголовки.
|
|
3
|
+
*
|
|
4
|
+
* Функция остается независимой от фреймворка: адаптеры могут перенести эти
|
|
5
|
+
* заголовки в SvelteKit, Hono, Bun.serve или любую другую реализацию Web Response.
|
|
6
|
+
*/
|
|
7
|
+
export const toCacheHeaders = (policy) => {
|
|
8
|
+
if (policy === 'no-store') {
|
|
9
|
+
return {
|
|
10
|
+
'Cache-Control': 'no-store, no-cache, must-revalidate',
|
|
11
|
+
Pragma: 'no-cache',
|
|
12
|
+
Expires: '0'
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const directives = [
|
|
16
|
+
policy.scope ?? 'private',
|
|
17
|
+
`max-age=${Math.max(0, Math.floor(policy.maxAge))}`
|
|
18
|
+
];
|
|
19
|
+
if (policy.mustRevalidate)
|
|
20
|
+
directives.push('must-revalidate');
|
|
21
|
+
if (policy.staleWhileRevalidate != null) {
|
|
22
|
+
directives.push(`stale-while-revalidate=${Math.max(0, Math.floor(policy.staleWhileRevalidate))}`);
|
|
23
|
+
}
|
|
24
|
+
return { 'Cache-Control': directives.join(', ') };
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"AASA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAsB,EAA0B,EAAE;IAChF,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;QAC3B,OAAO;YACN,eAAe,EAAE,qCAAqC;YACtD,MAAM,EAAE,UAAU;YAClB,OAAO,EAAE,GAAG;SACZ,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG;QAClB,MAAM,CAAC,KAAK,IAAI,SAAS;QACzB,WAAW,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE;KACnD,CAAC;IACF,IAAI,MAAM,CAAC,cAAc;QAAE,UAAU,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC9D,IAAI,MAAM,CAAC,oBAAoB,IAAI,IAAI,EAAE,CAAC;QACzC,UAAU,CAAC,IAAI,CACd,0BAA0B,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAChF,CAAC;IACH,CAAC;IACD,OAAO,EAAE,eAAe,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACnD,CAAC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type z, type ZodType } from 'zod';
|
|
2
|
+
import type { EndpointDefinition } from './endpoint.js';
|
|
3
|
+
export type InferEndpointTypes<T extends EndpointDefinition<ZodType | null, ZodType | null, ZodType | null>> = {
|
|
4
|
+
params: T['paramsSchema'] extends ZodType ? z.input<T['paramsSchema']> : never;
|
|
5
|
+
query: T['querySchema'] extends ZodType ? z.input<T['querySchema']> : never;
|
|
6
|
+
body: T['bodySchema'] extends ZodType ? z.input<T['bodySchema']> : never;
|
|
7
|
+
parsed: {
|
|
8
|
+
params: T['paramsSchema'] extends ZodType ? z.output<T['paramsSchema']> : never;
|
|
9
|
+
query: T['querySchema'] extends ZodType ? z.output<T['querySchema']> : never;
|
|
10
|
+
body: T['bodySchema'] extends ZodType ? z.output<T['bodySchema']> : never;
|
|
11
|
+
};
|
|
12
|
+
response: Awaited<ReturnType<T['handler']>>;
|
|
13
|
+
};
|
|
14
|
+
type TypedFetchOptions<T extends EndpointDefinition<ZodType | null, ZodType | null, ZodType | null>> = {
|
|
15
|
+
params?: InferEndpointTypes<T>['params'];
|
|
16
|
+
query?: InferEndpointTypes<T>['query'];
|
|
17
|
+
body?: InferEndpointTypes<T>['body'];
|
|
18
|
+
init?: RequestInit;
|
|
19
|
+
baseUrl?: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Небольшой типизированный fetch-помощник для клиентов, импортирующих описания эндпоинтов.
|
|
23
|
+
*
|
|
24
|
+
* Он намеренно почти ничего не предполагает о транспорте: приложение само
|
|
25
|
+
* передает `baseUrl`, credentials, headers и остальные настройки RequestInit.
|
|
26
|
+
*/
|
|
27
|
+
export declare function typedFetch<T extends EndpointDefinition<ZodType | null, ZodType | null, ZodType | null>>(endpoint: T, options?: TypedFetchOptions<T>): Promise<InferEndpointTypes<T>['response']>;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,CAAC,EAAE,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AAC3C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,kBAAkB,CAAC,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC,IAAI;IAC9G,MAAM,EAAE,CAAC,CAAC,cAAc,CAAC,SAAS,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,GAAG,KAAK,CAAC;IAC/E,KAAK,EAAE,CAAC,CAAC,aAAa,CAAC,SAAS,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,GAAG,KAAK,CAAC;IAC5E,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,SAAS,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,GAAG,KAAK,CAAC;IACzE,MAAM,EAAE;QACP,MAAM,EAAE,CAAC,CAAC,cAAc,CAAC,SAAS,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,GAAG,KAAK,CAAC;QAChF,KAAK,EAAE,CAAC,CAAC,aAAa,CAAC,SAAS,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,GAAG,KAAK,CAAC;QAC7E,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,SAAS,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,GAAG,KAAK,CAAC;KAC1E,CAAC;IACF,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;CAC5C,CAAC;AAEF,KAAK,iBAAiB,CAAC,CAAC,SAAS,kBAAkB,CAAC,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC,IAAI;IACtG,MAAM,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IACzC,KAAK,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACvC,IAAI,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACrC,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AA2BF;;;;;GAKG;AACH,wBAAsB,UAAU,CAC/B,CAAC,SAAS,kBAAkB,CAAC,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC,EAC3E,QAAQ,EAAE,CAAC,EAAE,OAAO,GAAE,iBAAiB,CAAC,CAAC,CAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAoB7F"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import {} from 'zod';
|
|
2
|
+
const fillPathParams = (path, params) => {
|
|
3
|
+
if (!params || typeof params !== 'object')
|
|
4
|
+
return path;
|
|
5
|
+
let next = path;
|
|
6
|
+
for (const [key, value] of Object.entries(params)) {
|
|
7
|
+
next = next.replace(`:${key}`, encodeURIComponent(String(value)));
|
|
8
|
+
next = next.replace(`[${key}]`, encodeURIComponent(String(value)));
|
|
9
|
+
}
|
|
10
|
+
return next;
|
|
11
|
+
};
|
|
12
|
+
const appendQuery = (path, query) => {
|
|
13
|
+
if (!query || typeof query !== 'object')
|
|
14
|
+
return path;
|
|
15
|
+
const search = new URLSearchParams();
|
|
16
|
+
for (const [key, value] of Object.entries(query)) {
|
|
17
|
+
if (value == null)
|
|
18
|
+
continue;
|
|
19
|
+
if (Array.isArray(value)) {
|
|
20
|
+
for (const item of value)
|
|
21
|
+
search.append(key, String(item));
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
search.set(key, String(value));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const qs = search.toString();
|
|
28
|
+
return qs ? `${path}${path.includes('?') ? '&' : '?'}${qs}` : path;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Небольшой типизированный fetch-помощник для клиентов, импортирующих описания эндпоинтов.
|
|
32
|
+
*
|
|
33
|
+
* Он намеренно почти ничего не предполагает о транспорте: приложение само
|
|
34
|
+
* передает `baseUrl`, credentials, headers и остальные настройки RequestInit.
|
|
35
|
+
*/
|
|
36
|
+
export async function typedFetch(endpoint, options = {}) {
|
|
37
|
+
const method = endpoint.openapi.method;
|
|
38
|
+
const pathWithParams = fillPathParams(endpoint.openapi.path, options.params);
|
|
39
|
+
const pathWithQuery = appendQuery(pathWithParams, options.query);
|
|
40
|
+
const url = `${options.baseUrl ?? ''}${pathWithQuery}`;
|
|
41
|
+
const headers = new Headers(options.init?.headers);
|
|
42
|
+
if (options.body !== undefined && !headers.has('content-type')) {
|
|
43
|
+
headers.set('content-type', 'application/json');
|
|
44
|
+
}
|
|
45
|
+
const response = await fetch(url, {
|
|
46
|
+
...options.init,
|
|
47
|
+
method,
|
|
48
|
+
headers,
|
|
49
|
+
body: options.body !== undefined ? JSON.stringify(options.body) : options.init?.body
|
|
50
|
+
});
|
|
51
|
+
if (!response.ok)
|
|
52
|
+
throw new Error(`Request failed with ${response.status}`);
|
|
53
|
+
const payload = await response.json();
|
|
54
|
+
return (payload?.data ?? payload);
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type z, type ZodType } from 'zod';
|
|
2
|
+
import type { ApiCachePolicy } from './cache.js';
|
|
3
|
+
export type HttpMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
|
|
4
|
+
export type EndpointOpenApi = {
|
|
5
|
+
method: HttpMethod;
|
|
6
|
+
path: string;
|
|
7
|
+
summary?: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
tags?: string[];
|
|
10
|
+
security?: Record<string, string[]>[];
|
|
11
|
+
};
|
|
12
|
+
export type EndpointHandlerContext<Params, Query, Body, User = unknown, AdapterContext = unknown> = {
|
|
13
|
+
params: Params;
|
|
14
|
+
query: Query;
|
|
15
|
+
body: Body;
|
|
16
|
+
request: Request;
|
|
17
|
+
user?: User;
|
|
18
|
+
/**
|
|
19
|
+
* Контекст конкретного фреймворка.
|
|
20
|
+
*
|
|
21
|
+
* Для SvelteKit здесь лежит RequestEvent. Адаптеры Hono/Fastify/etc. могут
|
|
22
|
+
* передавать сюда свой контекст, не протаскивая эти типы в ядро пакета.
|
|
23
|
+
*/
|
|
24
|
+
adapter: AdapterContext;
|
|
25
|
+
};
|
|
26
|
+
export type EndpointDefinition<ParamsSchema extends ZodType | null = null, QuerySchema extends ZodType | null = null, BodySchema extends ZodType | null = null, Response = unknown, ResponseSchema extends ZodType | null = null, Role extends string = string, User = unknown, AdapterContext = unknown> = {
|
|
27
|
+
paramsSchema?: ParamsSchema | null;
|
|
28
|
+
querySchema?: QuerySchema | null;
|
|
29
|
+
bodySchema?: BodySchema | null;
|
|
30
|
+
/**
|
|
31
|
+
* Схема и content-type тела запроса только для документации.
|
|
32
|
+
*
|
|
33
|
+
* Используется, когда тело запроса обрабатывается в эндпоинте вручную
|
|
34
|
+
* (например, multipart/form-data), но OpenAPI все равно должен описать
|
|
35
|
+
* формат входных данных.
|
|
36
|
+
*/
|
|
37
|
+
docsBodySchema?: ZodType | null;
|
|
38
|
+
docsBodyContentType?: string;
|
|
39
|
+
responseSchema?: ResponseSchema | null;
|
|
40
|
+
requireAuth?: boolean;
|
|
41
|
+
roles?: readonly Role[];
|
|
42
|
+
cachePolicy?: ApiCachePolicy;
|
|
43
|
+
openapi: EndpointOpenApi;
|
|
44
|
+
handler: (ctx: EndpointHandlerContext<ParamsSchema extends ZodType ? z.output<ParamsSchema> : Record<string, string>, QuerySchema extends ZodType ? z.output<QuerySchema> : Record<string, string>, BodySchema extends ZodType ? z.output<BodySchema> : unknown, User, AdapterContext>) => Response | Promise<Response>;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Помощник без runtime-логики, сохраняющий вывод generic-типов эндпоинта.
|
|
48
|
+
*
|
|
49
|
+
* Если описывать эндпоинты через эту функцию, вызывающий код получает строгие
|
|
50
|
+
* типы для входа хендлера, typedFetch и проверки ответа без дополнительных
|
|
51
|
+
* действий во время выполнения.
|
|
52
|
+
*/
|
|
53
|
+
export declare const defineEndpoint: <ParamsSchema extends ZodType | null = null, QuerySchema extends ZodType | null = null, BodySchema extends ZodType | null = null, Response = unknown, ResponseSchema extends ZodType | null = null, Role extends string = string, User = unknown, AdapterContext = unknown>(definition: EndpointDefinition<ParamsSchema, QuerySchema, BodySchema, Response, ResponseSchema, Role, User, AdapterContext>) => EndpointDefinition<ParamsSchema, QuerySchema, BodySchema, Response, ResponseSchema, Role, User, AdapterContext>;
|
|
54
|
+
//# sourceMappingURL=endpoint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoint.d.ts","sourceRoot":"","sources":["../../src/core/endpoint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {} from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Помощник без runtime-логики, сохраняющий вывод generic-типов эндпоинта.
|
|
4
|
+
*
|
|
5
|
+
* Если описывать эндпоинты через эту функцию, вызывающий код получает строгие
|
|
6
|
+
* типы для входа хендлера, typedFetch и проверки ответа без дополнительных
|
|
7
|
+
* действий во время выполнения.
|
|
8
|
+
*/
|
|
9
|
+
export const defineEndpoint = (definition) => definition;
|
|
10
|
+
//# sourceMappingURL=endpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoint.js","sourceRoot":"","sources":["../../src/core/endpoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,MAAM,KAAK,CAAC;AA0E3C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAU7B,UASC,EACA,EAAE,CAAC,UAAU,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export type ApiIssue = {
|
|
3
|
+
path: string;
|
|
4
|
+
message: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Ожидаемая ошибка приложения или API.
|
|
8
|
+
*
|
|
9
|
+
* Бросайте ее из хендлеров, когда клиент должен получить конкретный HTTP-статус.
|
|
10
|
+
* Неизвестные ошибки адаптеры по-прежнему превращают в 500.
|
|
11
|
+
*/
|
|
12
|
+
export declare class ApiKitError extends Error {
|
|
13
|
+
readonly status: number;
|
|
14
|
+
readonly issues?: ApiIssue[];
|
|
15
|
+
readonly expose: boolean;
|
|
16
|
+
constructor(status: number, message: string, options?: {
|
|
17
|
+
issues?: ApiIssue[];
|
|
18
|
+
expose?: boolean;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export declare const toApiIssues: (error: z.ZodError) => ApiIssue[];
|
|
22
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,MAAM,QAAQ,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;;;GAKG;AACH,qBAAa,WAAY,SAAQ,KAAK;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;gBAEb,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAO;CAOpG;AAED,eAAO,MAAM,WAAW,GAAI,OAAO,CAAC,CAAC,QAAQ,KAAG,QAAQ,EAIpD,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Ожидаемая ошибка приложения или API.
|
|
4
|
+
*
|
|
5
|
+
* Бросайте ее из хендлеров, когда клиент должен получить конкретный HTTP-статус.
|
|
6
|
+
* Неизвестные ошибки адаптеры по-прежнему превращают в 500.
|
|
7
|
+
*/
|
|
8
|
+
export class ApiKitError extends Error {
|
|
9
|
+
status;
|
|
10
|
+
issues;
|
|
11
|
+
expose;
|
|
12
|
+
constructor(status, message, options = {}) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = 'ApiKitError';
|
|
15
|
+
this.status = status;
|
|
16
|
+
this.issues = options.issues;
|
|
17
|
+
this.expose = options.expose ?? status < 500;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export const toApiIssues = (error) => error.issues.map((issue) => ({
|
|
21
|
+
path: issue.path.join('.'),
|
|
22
|
+
message: issue.message
|
|
23
|
+
}));
|
|
24
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;;;;GAKG;AACH,MAAM,OAAO,WAAY,SAAQ,KAAK;IAC5B,MAAM,CAAS;IACf,MAAM,CAAc;IACpB,MAAM,CAAU;IAEzB,YAAY,MAAc,EAAE,OAAe,EAAE,UAAqD,EAAE;QACnG,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,MAAM,GAAG,GAAG,CAAC;IAC9C,CAAC;CACD;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAiB,EAAc,EAAE,CAC5D,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC5B,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;CACtB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
type Primitive = string | number | boolean | string[];
|
|
3
|
+
type QueryParamDef<T extends Primitive = Primitive> = T | {
|
|
4
|
+
default: T;
|
|
5
|
+
description?: string;
|
|
6
|
+
enum?: T extends string ? readonly [string, ...string[]] : never;
|
|
7
|
+
};
|
|
8
|
+
type QueryParamShape = Record<string, QueryParamDef>;
|
|
9
|
+
/**
|
|
10
|
+
* Генерирует Zod-схему для query-параметров по значениям по умолчанию.
|
|
11
|
+
*
|
|
12
|
+
* Query-параметры приходят строками, поэтому числовые, булевые и массивные
|
|
13
|
+
* значения по умолчанию также задают правила преобразования входящих строк
|
|
14
|
+
* для хендлеров эндпоинтов.
|
|
15
|
+
*/
|
|
16
|
+
export declare function generateQuerySchema<T extends QueryParamShape>(params: T): z.ZodObject<{
|
|
17
|
+
[x: string]: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
|
|
18
|
+
}, z.core.$strip>;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/core/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAgB,MAAM,KAAK,CAAC;AAEtC,KAAK,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC;AAEtD,KAAK,aAAa,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,IAC/C,CAAC,GACD;IACA,OAAO,EAAE,CAAC,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,GAAG,KAAK,CAAC;CAChE,CAAC;AAEL,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAErD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,eAAe,EAAE,MAAM,EAAE,CAAC;;kBA6CvE"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Генерирует Zod-схему для query-параметров по значениям по умолчанию.
|
|
4
|
+
*
|
|
5
|
+
* Query-параметры приходят строками, поэтому числовые, булевые и массивные
|
|
6
|
+
* значения по умолчанию также задают правила преобразования входящих строк
|
|
7
|
+
* для хендлеров эндпоинтов.
|
|
8
|
+
*/
|
|
9
|
+
export function generateQuerySchema(params) {
|
|
10
|
+
const schemaShape = {};
|
|
11
|
+
for (const [key, def] of Object.entries(params)) {
|
|
12
|
+
const isObject = typeof def === 'object' && def !== null && 'default' in def;
|
|
13
|
+
const objectDef = isObject ? def : null;
|
|
14
|
+
const defaultValue = objectDef?.default ?? def;
|
|
15
|
+
const description = objectDef?.description ?? `Query param "${key}" (default: ${String(defaultValue)})`;
|
|
16
|
+
if (objectDef?.enum && typeof defaultValue === 'string') {
|
|
17
|
+
const enumValues = objectDef.enum;
|
|
18
|
+
schemaShape[key] = z.enum(enumValues).optional().default(defaultValue).describe(description);
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (typeof defaultValue === 'string') {
|
|
22
|
+
schemaShape[key] = z.string().optional().default(defaultValue).describe(description);
|
|
23
|
+
}
|
|
24
|
+
else if (typeof defaultValue === 'number') {
|
|
25
|
+
schemaShape[key] = z
|
|
26
|
+
.string()
|
|
27
|
+
.transform((value) => (value !== undefined && value !== '' ? Number(value) : defaultValue))
|
|
28
|
+
.optional()
|
|
29
|
+
.default(defaultValue)
|
|
30
|
+
.describe(description);
|
|
31
|
+
}
|
|
32
|
+
else if (typeof defaultValue === 'boolean') {
|
|
33
|
+
schemaShape[key] = z
|
|
34
|
+
.string()
|
|
35
|
+
.transform((value) => (value === 'true' ? true : value === 'false' ? false : defaultValue))
|
|
36
|
+
.optional()
|
|
37
|
+
.default(defaultValue)
|
|
38
|
+
.describe(description);
|
|
39
|
+
}
|
|
40
|
+
else if (Array.isArray(defaultValue)) {
|
|
41
|
+
schemaShape[key] = z
|
|
42
|
+
.string()
|
|
43
|
+
.transform((value) => (value ? value.split(',') : defaultValue))
|
|
44
|
+
.optional()
|
|
45
|
+
.default(defaultValue.map(String))
|
|
46
|
+
.describe(description);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
throw new Error(`Unsupported type for query param "${key}"`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return z.object(schemaShape);
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/core/query.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z, type ZodType } from 'zod';
|
|
2
|
+
export declare const ApiErrorResponseSchema: z.ZodObject<{
|
|
3
|
+
success: z.ZodLiteral<false>;
|
|
4
|
+
error: z.ZodString;
|
|
5
|
+
code: z.ZodNumber;
|
|
6
|
+
issues: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
7
|
+
path: z.ZodString;
|
|
8
|
+
message: z.ZodString;
|
|
9
|
+
}, z.core.$strip>>>;
|
|
10
|
+
}, z.core.$strip>;
|
|
11
|
+
export declare const ApiSuccessResponseSchema: <T extends ZodType>(data: T) => z.ZodObject<{
|
|
12
|
+
success: z.ZodLiteral<true>;
|
|
13
|
+
data: T;
|
|
14
|
+
}, z.core.$strip>;
|
|
15
|
+
export type ApiErrorResponse = z.infer<typeof ApiErrorResponseSchema>;
|
|
16
|
+
export type ApiSuccessResponse<T> = {
|
|
17
|
+
success: true;
|
|
18
|
+
data: T;
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=responses.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responses.d.ts","sourceRoot":"","sources":["../../src/core/responses.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AAEtC,eAAO,MAAM,sBAAsB;;;;;;;;iBAKjC,CAAC;AAEH,eAAO,MAAM,wBAAwB,GAAI,CAAC,SAAS,OAAO,EAAE,MAAM,CAAC;;;iBAIhE,CAAC;AAEJ,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AACtE,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI;IACnC,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,CAAC,CAAC;CACR,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const ApiErrorResponseSchema = z.object({
|
|
3
|
+
success: z.literal(false),
|
|
4
|
+
error: z.string(),
|
|
5
|
+
code: z.number(),
|
|
6
|
+
issues: z.array(z.object({ path: z.string(), message: z.string() })).optional()
|
|
7
|
+
});
|
|
8
|
+
export const ApiSuccessResponseSchema = (data) => z.object({
|
|
9
|
+
success: z.literal(true),
|
|
10
|
+
data
|
|
11
|
+
});
|
|
12
|
+
//# sourceMappingURL=responses.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responses.js","sourceRoot":"","sources":["../../src/core/responses.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAgB,MAAM,KAAK,CAAC;AAEtC,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;IACzB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC/E,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAoB,IAAO,EAAE,EAAE,CACtE,CAAC,CAAC,MAAM,CAAC;IACR,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;IACxB,IAAI;CACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type RequestHandler } from '@sveltejs/kit';
|
|
2
|
+
import { type ZodType } from 'zod';
|
|
3
|
+
import { type EndpointDefinition } from '../core/index.js';
|
|
4
|
+
export type SvelteKitAdapterOptions<User = unknown, Event = Parameters<RequestHandler>[0]> = {
|
|
5
|
+
resolveUser?: (event: Event) => User | undefined | Promise<User | undefined>;
|
|
6
|
+
hasRole?: (user: User, role: string) => boolean | Promise<boolean>;
|
|
7
|
+
isAuthDisabled?: (event: Event) => boolean | Promise<boolean>;
|
|
8
|
+
onError?: (error: unknown, event: Event) => void | Promise<void>;
|
|
9
|
+
};
|
|
10
|
+
export declare const fail: (status: number, error: string, issues?: Array<{
|
|
11
|
+
path: string;
|
|
12
|
+
message: string;
|
|
13
|
+
}>) => Response;
|
|
14
|
+
/**
|
|
15
|
+
* SvelteKit-адаптер для EndpointDefinition.
|
|
16
|
+
*
|
|
17
|
+
* Адаптер отвечает только за механику фреймворка: извлечение RequestEvent,
|
|
18
|
+
* создание Response, преобразование ошибок валидации и опциональные хуки
|
|
19
|
+
* авторизации. Бизнес-логика авторизации и сессий остается в приложении.
|
|
20
|
+
*/
|
|
21
|
+
export declare const svelteKitApiHandler: <ParamsSchema extends ZodType | null = null, QuerySchema extends ZodType | null = null, BodySchema extends ZodType | null = null, Response = unknown, ResponseSchema extends ZodType | null = null, Role extends string = string, User = unknown>(endpoint: EndpointDefinition<ParamsSchema, QuerySchema, BodySchema, Response, ResponseSchema, Role, User, Parameters<RequestHandler>[0]>, options?: SvelteKitAdapterOptions<User>) => RequestHandler;
|
|
22
|
+
export { svelteKitApiHandler as apiHandler };
|
|
23
|
+
//# sourceMappingURL=apiHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiHandler.d.ts","sourceRoot":"","sources":["../../src/sveltekit/apiHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAK,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AACtC,OAAO,EAGN,KAAK,kBAAkB,EAIvB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,MAAM,uBAAuB,CAAC,IAAI,GAAG,OAAO,EAAE,KAAK,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI;IAC5F,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC;IAC7E,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnE,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjE,CAAC;AASF,eAAO,MAAM,IAAI,GAAI,QAAQ,MAAM,EAAE,OAAO,MAAM,EAAE,SAAS,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,aAIlG,CAAC;AAkBJ;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAC/B,YAAY,SAAS,OAAO,GAAG,IAAI,GAAG,IAAI,EAC1C,WAAW,SAAS,OAAO,GAAG,IAAI,GAAG,IAAI,EACzC,UAAU,SAAS,OAAO,GAAG,IAAI,GAAG,IAAI,EACxC,QAAQ,GAAG,OAAO,EAClB,cAAc,SAAS,OAAO,GAAG,IAAI,GAAG,IAAI,EAC5C,IAAI,SAAS,MAAM,GAAG,MAAM,EAC5B,IAAI,GAAG,OAAO,EAEd,UAAU,kBAAkB,CAC3B,YAAY,EACZ,WAAW,EACX,UAAU,EACV,QAAQ,EACR,cAAc,EACd,IAAI,EACJ,IAAI,EACJ,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAC7B,EACD,UAAS,uBAAuB,CAAC,IAAI,CAAM,KACzC,cA+EF,CAAC;AAEF,OAAO,EAAE,mBAAmB,IAAI,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { json } from '@sveltejs/kit';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { ApiErrorResponseSchema, ApiKitError, registerEndpoint, toApiIssues, toCacheHeaders } from '../core/index.js';
|
|
4
|
+
const parseJsonRequestBody = async (request) => {
|
|
5
|
+
const rawText = await request.text().catch(() => '');
|
|
6
|
+
const trimmed = rawText.trim();
|
|
7
|
+
if (!trimmed)
|
|
8
|
+
return undefined;
|
|
9
|
+
return JSON.parse(trimmed);
|
|
10
|
+
};
|
|
11
|
+
export const fail = (status, error, issues) => json(ApiErrorResponseSchema.parse({ success: false, error, code: status, issues }), {
|
|
12
|
+
status,
|
|
13
|
+
headers: toCacheHeaders('no-store')
|
|
14
|
+
});
|
|
15
|
+
const defaultResolveUser = (event) => event.locals.user;
|
|
16
|
+
const defaultHasRole = (user, role) => {
|
|
17
|
+
const roles = user.roles;
|
|
18
|
+
return Array.isArray(roles) && roles.includes(role);
|
|
19
|
+
};
|
|
20
|
+
const defaultIsAuthDisabled = () => globalThis.process?.env
|
|
21
|
+
?.DEMO_PUBLIC === '1';
|
|
22
|
+
/**
|
|
23
|
+
* SvelteKit-адаптер для EndpointDefinition.
|
|
24
|
+
*
|
|
25
|
+
* Адаптер отвечает только за механику фреймворка: извлечение RequestEvent,
|
|
26
|
+
* создание Response, преобразование ошибок валидации и опциональные хуки
|
|
27
|
+
* авторизации. Бизнес-логика авторизации и сессий остается в приложении.
|
|
28
|
+
*/
|
|
29
|
+
export const svelteKitApiHandler = (endpoint, options = {}) => {
|
|
30
|
+
registerEndpoint(endpoint);
|
|
31
|
+
return async (event) => {
|
|
32
|
+
const cachePolicy = endpoint.cachePolicy ?? 'no-store';
|
|
33
|
+
const responseHeaders = toCacheHeaders(cachePolicy);
|
|
34
|
+
try {
|
|
35
|
+
const user = options.resolveUser
|
|
36
|
+
? await options.resolveUser(event)
|
|
37
|
+
: defaultResolveUser(event);
|
|
38
|
+
const authDisabled = options.isAuthDisabled
|
|
39
|
+
? await options.isAuthDisabled(event)
|
|
40
|
+
: defaultIsAuthDisabled();
|
|
41
|
+
if (!authDisabled && endpoint.requireAuth) {
|
|
42
|
+
if (!user)
|
|
43
|
+
return fail(401, 'Unauthorized');
|
|
44
|
+
for (const role of endpoint.roles ?? []) {
|
|
45
|
+
const allowed = options.hasRole
|
|
46
|
+
? await options.hasRole(user, role)
|
|
47
|
+
: defaultHasRole(user, role);
|
|
48
|
+
if (!allowed)
|
|
49
|
+
return fail(403, 'Forbidden');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const paramsSchema = endpoint.paramsSchema;
|
|
53
|
+
const querySchema = endpoint.querySchema;
|
|
54
|
+
const bodySchema = endpoint.bodySchema;
|
|
55
|
+
const responseSchema = endpoint.responseSchema;
|
|
56
|
+
const parsedParams = paramsSchema ? paramsSchema.parse(event.params) : event.params;
|
|
57
|
+
const queryObject = Object.fromEntries(event.url.searchParams);
|
|
58
|
+
const parsedQuery = querySchema ? querySchema.parse(queryObject) : queryObject;
|
|
59
|
+
let parsedBody = undefined;
|
|
60
|
+
const contentType = event.request.headers.get('content-type') || '';
|
|
61
|
+
if (!contentType.includes('multipart/form-data')) {
|
|
62
|
+
const rawBody = await parseJsonRequestBody(event.request);
|
|
63
|
+
parsedBody = bodySchema ? bodySchema.parse(rawBody ?? {}) : rawBody;
|
|
64
|
+
}
|
|
65
|
+
const result = await endpoint.handler({
|
|
66
|
+
params: parsedParams,
|
|
67
|
+
query: parsedQuery,
|
|
68
|
+
body: parsedBody,
|
|
69
|
+
request: event.request,
|
|
70
|
+
user,
|
|
71
|
+
adapter: event
|
|
72
|
+
});
|
|
73
|
+
if (result instanceof Response) {
|
|
74
|
+
if (result.headers.has('cache-control'))
|
|
75
|
+
return result;
|
|
76
|
+
const headers = new Headers(result.headers);
|
|
77
|
+
for (const [key, value] of Object.entries(responseHeaders))
|
|
78
|
+
headers.set(key, value);
|
|
79
|
+
return new Response(result.body, {
|
|
80
|
+
status: result.status,
|
|
81
|
+
statusText: result.statusText,
|
|
82
|
+
headers
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
const data = responseSchema ? responseSchema.parse(result) : result;
|
|
86
|
+
const status = endpoint.openapi.method === 'POST' ? 201 : endpoint.openapi.method === 'DELETE' ? 204 : 200;
|
|
87
|
+
if (status === 204)
|
|
88
|
+
return new Response(null, { status, headers: responseHeaders });
|
|
89
|
+
return json({ success: true, data }, { status, headers: responseHeaders });
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
await options.onError?.(error, event);
|
|
93
|
+
if (error instanceof SyntaxError)
|
|
94
|
+
return fail(400, 'Invalid JSON body');
|
|
95
|
+
if (error instanceof z.ZodError)
|
|
96
|
+
return fail(400, 'Validation failed', toApiIssues(error));
|
|
97
|
+
if (error instanceof ApiKitError) {
|
|
98
|
+
return fail(error.status, error.expose ? error.message : 'Internal Server Error', error.issues);
|
|
99
|
+
}
|
|
100
|
+
return fail(500, error instanceof Error ? error.message : 'Internal Server Error');
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
export { svelteKitApiHandler as apiHandler };
|
|
105
|
+
//# sourceMappingURL=apiHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiHandler.js","sourceRoot":"","sources":["../../src/sveltekit/apiHandler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sveltekit/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sveltekit/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@varmdev/api-kit",
|
|
3
|
+
"version": "0.1.7",
|
|
4
|
+
"description": "Toolkit for typed API endpoints, Zod validation, OpenAPI generation and SvelteKit adapters.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "./dist/core/index.js",
|
|
8
|
+
"types": "./dist/core/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
"./core": {
|
|
11
|
+
"types": "./dist/core/index.d.ts",
|
|
12
|
+
"import": "./dist/core/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./core/apiRegistry": {
|
|
15
|
+
"types": "./dist/core/apiRegistry.d.ts",
|
|
16
|
+
"import": "./dist/core/apiRegistry.js"
|
|
17
|
+
},
|
|
18
|
+
"./core/client": {
|
|
19
|
+
"types": "./dist/core/client.d.ts",
|
|
20
|
+
"import": "./dist/core/client.js"
|
|
21
|
+
},
|
|
22
|
+
"./core/query": {
|
|
23
|
+
"types": "./dist/core/query.d.ts",
|
|
24
|
+
"import": "./dist/core/query.js"
|
|
25
|
+
},
|
|
26
|
+
"./sveltekit": {
|
|
27
|
+
"types": "./dist/sveltekit/index.d.ts",
|
|
28
|
+
"import": "./dist/sveltekit/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./sveltekit/apiHandler": {
|
|
31
|
+
"types": "./dist/sveltekit/apiHandler.d.ts",
|
|
32
|
+
"import": "./dist/sveltekit/apiHandler.js"
|
|
33
|
+
},
|
|
34
|
+
"./apiRegistry": {
|
|
35
|
+
"types": "./dist/core/apiRegistry.d.ts",
|
|
36
|
+
"import": "./dist/core/apiRegistry.js"
|
|
37
|
+
},
|
|
38
|
+
"./apiHandler": {
|
|
39
|
+
"types": "./dist/sveltekit/apiHandler.d.ts",
|
|
40
|
+
"import": "./dist/sveltekit/apiHandler.js"
|
|
41
|
+
},
|
|
42
|
+
"./client": {
|
|
43
|
+
"types": "./dist/core/client.d.ts",
|
|
44
|
+
"import": "./dist/core/client.js"
|
|
45
|
+
},
|
|
46
|
+
"./query": {
|
|
47
|
+
"types": "./dist/core/query.d.ts",
|
|
48
|
+
"import": "./dist/core/query.js"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"files": [
|
|
52
|
+
"dist",
|
|
53
|
+
"README.md"
|
|
54
|
+
],
|
|
55
|
+
"publishConfig": {
|
|
56
|
+
"access": "public"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsc -p tsconfig.json",
|
|
60
|
+
"check": "tsc -p tsconfig.json --noEmit",
|
|
61
|
+
"prepare": "bun run build",
|
|
62
|
+
"prepack": "bun run build"
|
|
63
|
+
},
|
|
64
|
+
"peerDependencies": {
|
|
65
|
+
"@sveltejs/kit": ">=2.0.0",
|
|
66
|
+
"zod": ">=4.0.0"
|
|
67
|
+
},
|
|
68
|
+
"peerDependenciesMeta": {
|
|
69
|
+
"@sveltejs/kit": {
|
|
70
|
+
"optional": true
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"dependencies": {
|
|
74
|
+
"@asteasolutions/zod-to-openapi": "^8.5.0"
|
|
75
|
+
},
|
|
76
|
+
"devDependencies": {
|
|
77
|
+
"@sveltejs/kit": "2.59.1",
|
|
78
|
+
"typescript": "^6.0.3",
|
|
79
|
+
"zod": "^4.4.3"
|
|
80
|
+
}
|
|
81
|
+
}
|