prapti 0.0.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 Kiran Ojha
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,153 @@
1
+ ![prapti](media/logo.png)
2
+
3
+ # Prapti 🚀
4
+
5
+ _"प्राप्ति" (Prapti) - Sanskrit for "fetch" or "obtain"_
6
+
7
+ > A minimal, type-safe HTTP client that extends the native `fetch` API with runtime schema validation.
8
+
9
+ ```typescript
10
+ // Without Prapti
11
+ const response = await safeFetch("/api/users");
12
+ const data = await response.json(); // any type
13
+ const validatedData = UserSchema.parse(data); // manual validation
14
+
15
+ // With Prapti
16
+ const { fetch: safeFetch } = createPrapti(adapters.zod);
17
+ const response = await safeFetch("/api/users", {
18
+ responseSchema: UserSchema,
19
+ });
20
+ const data = await response.json(); // fully typed + validated
21
+ ```
22
+
23
+ ## Why switch from `fetch`?
24
+
25
+ **🎯 Stop writing `any` types**
26
+ Get automatic TypeScript inference from your schemas. No more manual type assertions.
27
+
28
+ **🛡️ Catch API breaks at runtime**
29
+ Validate responses against your schema. Know immediately when APIs change unexpectedly.
30
+
31
+ **🔧 Eliminate validation boilerplate**
32
+ No more `schema.parse(await response.json())` on every API call. It's built-in.
33
+
34
+ **⚡ Drop-in replacement**
35
+ Same API as `fetch()` with optional superpowers. Add validation only where you need it.
36
+
37
+ **🎨 Use any validation library**
38
+ Bring your own: Zod, Valibot, Yup, Joi, or build custom adapters.
39
+
40
+ ## Install
41
+
42
+ ```bash
43
+ npm install prapti zod
44
+ ```
45
+
46
+ ## Usage
47
+
48
+ ```typescript
49
+ import { createPrapti, adapters } from "prapti";
50
+ import { z } from "zod";
51
+
52
+ const UserSchema = z.object({
53
+ id: z.number(),
54
+ name: z.string(),
55
+ email: z.string().email(),
56
+ });
57
+
58
+ // Create client with Zod adapter
59
+ const { fetch: safeFetch } = createPrapti(adapters.zod);
60
+
61
+ // GET with response validation
62
+ const response = await safeFetch("/api/users/1", {
63
+ responseSchema: UserSchema,
64
+ });
65
+ const user = await response.json(); // Type: { id: number, name: string, email: string }
66
+
67
+ // POST with request + response validation
68
+ const CreateUserSchema = UserSchema.omit({ id: true });
69
+
70
+ const newUser = await safeFetch("/api/users", {
71
+ method: "POST",
72
+ body: { name: "John", email: "john@example.com" },
73
+ requestSchema: CreateUserSchema,
74
+ responseSchema: UserSchema,
75
+ });
76
+ ```
77
+
78
+ ## API
79
+
80
+ ### `Prapti(adapter)`
81
+
82
+ Main client class. Pass a validation adapter for your schema library.
83
+
84
+ **Available adapters:**
85
+
86
+ - `adapters.zod` - for Zod schemas
87
+
88
+ **Methods:**
89
+
90
+ - `fetch(url, options)` - Enhanced fetch with validation
91
+
92
+ ### `PraptiOptions`
93
+
94
+ Standard fetch options plus:
95
+
96
+ - `requestSchema?` - Schema to validate request body
97
+ - `responseSchema?` - Schema to validate response data
98
+
99
+ ### `ValidatedResponse`
100
+
101
+ Enhanced Response with validation:
102
+
103
+ - `json()` - Parse and validate JSON
104
+ - `text()` - Parse and validate text
105
+ - `blob()` - Get blob (no validation)
106
+ - `arrayBuffer()` - Get buffer (no validation)
107
+ - `formData()` - Parse and validate form data
108
+
109
+ ## Custom Adapters
110
+
111
+ ```typescript
112
+ const customAdapter = {
113
+ parse: <T>(schema: MySchema, data: unknown): T => {
114
+ return schema.validate(data);
115
+ },
116
+ };
117
+
118
+ const { fetch: safeFetch } = createPrapti(customAdapter);
119
+ ```
120
+
121
+ ## Error Handling
122
+
123
+ ```typescript
124
+ try {
125
+ const response = await safeFetch("/api/users", {
126
+ responseSchema: UserSchema,
127
+ });
128
+ const users = await response.json();
129
+ } catch (error) {
130
+ // Validation errors from your schema library
131
+ // Network errors from fetch
132
+ }
133
+ ```
134
+
135
+ ## Upcoming Features
136
+
137
+ - 🔄 **Built-in adapters for Valibot, Yup, Joi, AJV**
138
+ - 🎨 **Custom adapter utilities and helpers**
139
+ - 🛡️ **Enhanced error types with validation details**
140
+ - 🎯 **Header validation with schemas**
141
+ - ⚡ **Zero-config TypeScript integration**
142
+ - 📦 **FormData and URLSearchParams validation**
143
+ - 🔄 **Streaming response validation**
144
+
145
+ ## License
146
+
147
+ MIT
148
+
149
+ ---
150
+
151
+ <div align="center">
152
+ Made with ❤️ from 🇳🇵
153
+ </div>
@@ -0,0 +1,110 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __moduleCache = /* @__PURE__ */ new WeakMap;
6
+ var __toCommonJS = (from) => {
7
+ var entry = __moduleCache.get(from), desc;
8
+ if (entry)
9
+ return entry;
10
+ entry = __defProp({}, "__esModule", { value: true });
11
+ if (from && typeof from === "object" || typeof from === "function")
12
+ __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
13
+ get: () => from[key],
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ }));
16
+ __moduleCache.set(from, entry);
17
+ return entry;
18
+ };
19
+ var __export = (target, all) => {
20
+ for (var name in all)
21
+ __defProp(target, name, {
22
+ get: all[name],
23
+ enumerable: true,
24
+ configurable: true,
25
+ set: (newValue) => all[name] = () => newValue
26
+ });
27
+ };
28
+
29
+ // src/index.ts
30
+ var exports_src = {};
31
+ __export(exports_src, {
32
+ createPrapti: () => createPrapti,
33
+ adapters: () => adapters,
34
+ ValidatedResponse: () => ValidatedResponse,
35
+ Prapti: () => Prapti
36
+ });
37
+ module.exports = __toCommonJS(exports_src);
38
+
39
+ class ValidatedResponse extends Response {
40
+ adapter;
41
+ responseSchema;
42
+ constructor(response, adapter, responseSchema) {
43
+ super(response.body, {
44
+ status: response.status,
45
+ statusText: response.statusText,
46
+ headers: response.headers
47
+ });
48
+ this.adapter = adapter;
49
+ this.responseSchema = responseSchema;
50
+ Object.setPrototypeOf(this, new.target.prototype);
51
+ }
52
+ async json() {
53
+ const data = await super.json();
54
+ return this.responseSchema ? this.adapter.parse(this.responseSchema, data) : data;
55
+ }
56
+ async text() {
57
+ const data = await super.text();
58
+ return this.responseSchema ? this.adapter.parse(this.responseSchema, data) : data;
59
+ }
60
+ async blob() {
61
+ return super.blob();
62
+ }
63
+ async arrayBuffer() {
64
+ return super.arrayBuffer();
65
+ }
66
+ async formData() {
67
+ const data = await super.formData();
68
+ if (this.responseSchema) {
69
+ const obj = Object.fromEntries(data.entries());
70
+ this.adapter.parse(this.responseSchema, obj);
71
+ }
72
+ return data;
73
+ }
74
+ }
75
+
76
+ class Prapti {
77
+ adapter;
78
+ constructor(adapter) {
79
+ this.adapter = adapter;
80
+ }
81
+ async fetch(input, options) {
82
+ const { requestSchema, responseSchema, body, ...fetchOptions } = options || {};
83
+ let finalBody;
84
+ const headers = new Headers(fetchOptions.headers);
85
+ if (requestSchema && body !== undefined && body !== null) {
86
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
87
+ const validatedBody = this.adapter.parse(requestSchema, parsedBody);
88
+ finalBody = JSON.stringify(validatedBody);
89
+ if (!headers.has("Content-Type")) {
90
+ headers.set("Content-Type", "application/json");
91
+ }
92
+ } else {
93
+ finalBody = body;
94
+ }
95
+ const response = await fetch(input, {
96
+ ...fetchOptions,
97
+ headers,
98
+ body: finalBody
99
+ });
100
+ return new ValidatedResponse(response, this.adapter, responseSchema);
101
+ }
102
+ }
103
+ function createPrapti(adapter) {
104
+ return new Prapti(adapter);
105
+ }
106
+ var adapters = {
107
+ zod: {
108
+ parse: (schema, data) => schema.parse(data)
109
+ }
110
+ };
@@ -0,0 +1,115 @@
1
+ // Generated by dts-bundle-generator v9.5.1
2
+
3
+ /**
4
+ * Prapti - Type-safe HTTP client with schema validation
5
+ * "प्राप्ति" (Prapti) - Sanskrit for "fetch" or "obtain"
6
+ */
7
+ /**
8
+ * Validation adapter interface for different schema libraries
9
+ * Supports Zod, Valibot, Yup, Joi, and other validation libraries
10
+ */
11
+ export interface ValidationAdapter<TSchema = unknown> {
12
+ /**
13
+ * Parse and validate data against the provided schema
14
+ * @param schema - The validation schema
15
+ * @param data - Data to validate
16
+ * @returns Validated and typed data
17
+ * @throws Validation error if data doesn't match schema
18
+ */
19
+ parse<T>(schema: TSchema, data: unknown): T;
20
+ }
21
+ /**
22
+ * Type helper to infer output type from various schema formats
23
+ * Supports multiple validation library conventions
24
+ */
25
+ export type InferOutput<T> = T extends {
26
+ _output: infer U;
27
+ } ? U : T extends {
28
+ _type: infer U;
29
+ } ? U : T extends (...args: any[]) => infer U ? U : unknown;
30
+ /**
31
+ * Extended fetch options with optional validation schemas
32
+ * Maintains compatibility with native RequestInit while adding validation
33
+ */
34
+ export interface PraptiOptions<TRequestSchema = unknown, TResponseSchema = unknown> extends Omit<RequestInit, "body"> {
35
+ /** Request body - can be any serializable data when using requestSchema */
36
+ body?: BodyInit | null | unknown;
37
+ /** Schema to validate request body against */
38
+ requestSchema?: TRequestSchema;
39
+ /** Schema to validate response data against */
40
+ responseSchema?: TResponseSchema;
41
+ }
42
+ /**
43
+ * Enhanced Response class with validation-aware methods
44
+ * Extends native Response to provide type-safe data parsing
45
+ */
46
+ export declare class ValidatedResponse<T = unknown> extends Response {
47
+ private adapter;
48
+ private responseSchema?;
49
+ constructor(response: Response, adapter: ValidationAdapter<any>, responseSchema?: any | undefined);
50
+ /**
51
+ * Parse JSON response and validate with schema if provided
52
+ * @returns Promise resolving to validated JSON data
53
+ */
54
+ json(): Promise<T>;
55
+ /**
56
+ * Parse text response and validate with schema if provided
57
+ * @returns Promise resolving to validated text data
58
+ */
59
+ text(): Promise<string>;
60
+ /**
61
+ * Get blob response - no validation as it's binary data
62
+ * @returns Promise resolving to Blob
63
+ */
64
+ blob(): Promise<Blob>;
65
+ /**
66
+ * Get array buffer response - no validation as it's binary data
67
+ * @returns Promise resolving to ArrayBuffer
68
+ */
69
+ arrayBuffer(): Promise<ArrayBuffer>;
70
+ /**
71
+ * Parse form data response and validate with schema if provided
72
+ * Note: Validation converts FormData to plain object for schema checking
73
+ * @returns Promise resolving to FormData
74
+ */
75
+ formData(): Promise<FormData>;
76
+ }
77
+ /**
78
+ * Type-safe HTTP client with validation capabilities
79
+ * Wraps native fetch API with schema validation support
80
+ */
81
+ export declare class Prapti<TSchema = unknown> {
82
+ private adapter;
83
+ /**
84
+ * Create a new Prapti instance
85
+ * @param adapter - Validation adapter for chosen schema library
86
+ */
87
+ constructor(adapter: ValidationAdapter<TSchema>);
88
+ /**
89
+ * Make an HTTP request with optional request/response validation
90
+ * @param input - Request URL or Request object
91
+ * @param options - Extended fetch options with validation schemas
92
+ * @returns Promise resolving to ValidatedResponse with inferred types
93
+ */
94
+ fetch<TResponseSchema extends TSchema = never>(input: RequestInfo | URL, options?: PraptiOptions<TSchema, TResponseSchema>): Promise<ValidatedResponse<TResponseSchema extends never ? unknown : InferOutput<TResponseSchema>>>;
95
+ }
96
+ /**
97
+ * Convenience function to create Prapti instance
98
+ * @param adapter - Validation adapter
99
+ * @returns New Prapti instance
100
+ */
101
+ export declare function createPrapti<TSchema>(adapter: ValidationAdapter<TSchema>): Prapti<TSchema>;
102
+ /**
103
+ * Pre-built adapters for some popular validation libraries
104
+ * TODO: add more
105
+ */
106
+ export declare const adapters: {
107
+ /**
108
+ * Zod adapter factory
109
+ * @param zod - Zod library import
110
+ * @returns ValidationAdapter for Zod schemas
111
+ */
112
+ zod: ValidationAdapter;
113
+ };
114
+
115
+ export {};
@@ -0,0 +1,79 @@
1
+ // src/index.ts
2
+ class ValidatedResponse extends Response {
3
+ adapter;
4
+ responseSchema;
5
+ constructor(response, adapter, responseSchema) {
6
+ super(response.body, {
7
+ status: response.status,
8
+ statusText: response.statusText,
9
+ headers: response.headers
10
+ });
11
+ this.adapter = adapter;
12
+ this.responseSchema = responseSchema;
13
+ Object.setPrototypeOf(this, new.target.prototype);
14
+ }
15
+ async json() {
16
+ const data = await super.json();
17
+ return this.responseSchema ? this.adapter.parse(this.responseSchema, data) : data;
18
+ }
19
+ async text() {
20
+ const data = await super.text();
21
+ return this.responseSchema ? this.adapter.parse(this.responseSchema, data) : data;
22
+ }
23
+ async blob() {
24
+ return super.blob();
25
+ }
26
+ async arrayBuffer() {
27
+ return super.arrayBuffer();
28
+ }
29
+ async formData() {
30
+ const data = await super.formData();
31
+ if (this.responseSchema) {
32
+ const obj = Object.fromEntries(data.entries());
33
+ this.adapter.parse(this.responseSchema, obj);
34
+ }
35
+ return data;
36
+ }
37
+ }
38
+
39
+ class Prapti {
40
+ adapter;
41
+ constructor(adapter) {
42
+ this.adapter = adapter;
43
+ }
44
+ async fetch(input, options) {
45
+ const { requestSchema, responseSchema, body, ...fetchOptions } = options || {};
46
+ let finalBody;
47
+ const headers = new Headers(fetchOptions.headers);
48
+ if (requestSchema && body !== undefined && body !== null) {
49
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
50
+ const validatedBody = this.adapter.parse(requestSchema, parsedBody);
51
+ finalBody = JSON.stringify(validatedBody);
52
+ if (!headers.has("Content-Type")) {
53
+ headers.set("Content-Type", "application/json");
54
+ }
55
+ } else {
56
+ finalBody = body;
57
+ }
58
+ const response = await fetch(input, {
59
+ ...fetchOptions,
60
+ headers,
61
+ body: finalBody
62
+ });
63
+ return new ValidatedResponse(response, this.adapter, responseSchema);
64
+ }
65
+ }
66
+ function createPrapti(adapter) {
67
+ return new Prapti(adapter);
68
+ }
69
+ var adapters = {
70
+ zod: {
71
+ parse: (schema, data) => schema.parse(data)
72
+ }
73
+ };
74
+ export {
75
+ createPrapti,
76
+ adapters,
77
+ ValidatedResponse,
78
+ Prapti
79
+ };
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "prapti",
3
+ "version": "0.0.1",
4
+ "description": "Type-safe HTTP client with runtime schema validation support for Zod, Valibot, Yup, and more",
5
+ "files": [
6
+ "dist/*",
7
+ "README.md",
8
+ "LICENSE"
9
+ ],
10
+ "types": "dist/index.d.ts",
11
+ "main": "dist/index.cjs.js",
12
+ "module": "dist/index.esm.js",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "require": "./dist/index.cjs.js",
17
+ "import": "./dist/index.esm.js"
18
+ }
19
+ },
20
+ "scripts": {
21
+ "build": "bun run scripts/build.ts",
22
+ "release": "npx bumpp --commit --push --tag && npm publish",
23
+ "size": "size-limit"
24
+ },
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+git@github.com:kiranojhanp/prapti.git"
28
+ },
29
+ "keywords": [
30
+ "prapti",
31
+ "fetch",
32
+ "http",
33
+ "client",
34
+ "validation",
35
+ "schema",
36
+ "typescript",
37
+ "zod",
38
+ "valibot",
39
+ "yup",
40
+ "joi",
41
+ "type-safe"
42
+ ],
43
+ "author": "Kiran Ojha",
44
+ "license": "MIT",
45
+ "bugs": {
46
+ "url": "git@github.com:kiranojhanp/prapti.git/issues"
47
+ },
48
+ "homepage": "git@github.com:kiranojhanp/prapti.git#readme",
49
+ "devDependencies": {
50
+ "@size-limit/preset-small-lib": "^11.2.0",
51
+ "@types/bun": "latest",
52
+ "bun-plugin-dts": "0.3.0",
53
+ "size-limit": "^11.2.0"
54
+ },
55
+ "peerDependencies": {
56
+ "typescript": "^5",
57
+ "zod": "^3.25.28"
58
+ },
59
+ "size-limit": [
60
+ {
61
+ "path": "dist/index.cjs.js",
62
+ "limit": "5 KB"
63
+ },
64
+ {
65
+ "path": "dist/index.esm.js",
66
+ "limit": "5 KB"
67
+ }
68
+ ]
69
+ }