typecompass 1.0.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.

Potentially problematic release.


This version of typecompass might be problematic. Click here for more details.

Files changed (2) hide show
  1. package/README.md +364 -0
  2. package/package.json +50 -0
package/README.md ADDED
@@ -0,0 +1,364 @@
1
+ # TypeCompass
2
+
3
+ **Navigate your API with type-safe precision** 🧭
4
+
5
+ TypeCompass is a lightweight TypeScript library that lets you define API contracts once and use them everywhere — with full type safety, automatic OpenAPI generation, and zero runtime overhead.
6
+
7
+ ## Features
8
+
9
+ ✨ **Type-Safe Contracts** - Define routes with Zod schemas, get full TypeScript inference
10
+ 🔄 **Client & Server** - Use the same contract for backend validation and frontend calls
11
+ 📚 **Auto OpenAPI** - Generate OpenAPI 3.0 specs automatically from your contracts
12
+ 🎯 **Zero Runtime Cost** - Contracts are just types on the client side
13
+ 🔗 **Combinable** - Merge multiple service contracts into one unified API
14
+ 🎨 **Framework Agnostic** - Works with Express, Fastify, Hono, or any Node.js framework
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install typecompass zod
20
+ ```
21
+
22
+ ## Quick Start
23
+
24
+ ### 1. Define a Contract
25
+
26
+ ```typescript
27
+ // contracts/auth.contract.ts
28
+ import { defineRoutes } from 'typecompass'
29
+ import { z } from 'zod'
30
+
31
+ export const AuthContract = defineRoutes({
32
+ login: {
33
+ method: "POST",
34
+ path: "/auth/login",
35
+ summary: "User Login",
36
+ tags: ["Auth"],
37
+ body: z.object({
38
+ email: z.string().email(),
39
+ password: z.string().min(8),
40
+ }),
41
+ responses: {
42
+ 200: {
43
+ schema: z.object({
44
+ token: z.string(),
45
+ user: z.object({
46
+ id: z.string(),
47
+ email: z.string(),
48
+ }),
49
+ }),
50
+ },
51
+ },
52
+ },
53
+
54
+ register: {
55
+ method: "POST",
56
+ path: "/auth/register",
57
+ summary: "User Registration",
58
+ tags: ["Auth"],
59
+ body: z.object({
60
+ email: z.string().email(),
61
+ password: z.string().min(8),
62
+ name: z.string(),
63
+ }),
64
+ },
65
+ })
66
+ ```
67
+
68
+ ### 2. Use on the Backend
69
+
70
+ ```typescript
71
+ // server.ts
72
+ import express from 'express'
73
+ import { AuthContract } from './contracts/auth.contract'
74
+
75
+ const app = express()
76
+
77
+ app.post('/auth/login', async (req, res) => {
78
+ // Validate with the contract schema
79
+ const data = AuthContract.login.body.parse(req.body)
80
+
81
+ // TypeScript knows the shape of data!
82
+ const user = await loginUser(data.email, data.password)
83
+
84
+ res.json({ token: user.token, user })
85
+ })
86
+
87
+ // Generate OpenAPI documentation
88
+ app.get('/openapi.json', (req, res) => {
89
+ const spec = AuthContract.generateOpenApi({
90
+ title: "Auth API",
91
+ version: "1.0.0",
92
+ servers: [{ url: "https://api.example.com", description: "Production" }],
93
+ })
94
+ res.json(spec)
95
+ })
96
+ ```
97
+
98
+ ### 3. Use on the Frontend
99
+
100
+ ```typescript
101
+ // api/client.ts
102
+ import { AuthContract } from '@mychange/api-contracts'
103
+ import { initClient } from 'typecompass/client'
104
+ import axios from 'axios'
105
+
106
+ const axiosInstance = axios.create({
107
+ baseURL: 'https://api.example.com',
108
+ })
109
+
110
+ const client = initClient(AuthContract, axiosInstance)
111
+
112
+ // Fully typed API calls!
113
+ const response = await client.login({
114
+ body: {
115
+ email: "user@example.com",
116
+ password: "secret123",
117
+ }
118
+ })
119
+
120
+ // TypeScript knows response.data.token exists
121
+ console.log(response.data.token)
122
+ ```
123
+
124
+ ## Combining Multiple Contracts
125
+
126
+ For larger applications with multiple services:
127
+
128
+ ```typescript
129
+ // contracts/index.ts
130
+ import { combineContracts } from 'typecompass'
131
+ import { AuthContract } from './auth.contract'
132
+ import { UsersContract } from './users.contract'
133
+ import { PaymentsContract } from './payments.contract'
134
+
135
+ export const ApiContract = combineContracts({
136
+ auth: AuthContract,
137
+ users: UsersContract,
138
+ payments: PaymentsContract,
139
+ })
140
+
141
+ // Generate unified OpenAPI spec
142
+ export const openApiSpec = ApiContract.generateOpenApi({
143
+ title: "MyChange API",
144
+ version: "1.0.0",
145
+ servers: [
146
+ { url: "https://api.mychange.com", description: "Production" },
147
+ { url: "http://localhost:3000", description: "Development" },
148
+ ],
149
+ securitySchemes: {
150
+ BearerAuth: {
151
+ type: "http",
152
+ scheme: "bearer",
153
+ },
154
+ },
155
+ defaultSecurity: ["BearerAuth"],
156
+ })
157
+ ```
158
+
159
+ ### Client with Combined Contracts
160
+
161
+ ```typescript
162
+ // Frontend usage
163
+ import { ApiContract } from '@mychange/api-contracts'
164
+ import { initCombinedClient } from 'typecompass/client'
165
+
166
+ const client = initCombinedClient(ApiContract, axiosInstance)
167
+
168
+ // Namespaced by service
169
+ await client.auth.login({ body: {...} })
170
+ await client.users.getProfile({ params: { id: "123" } })
171
+ await client.payments.createCharge({ body: {...} })
172
+ ```
173
+
174
+ ## Advanced Features
175
+
176
+ ### Path Parameters
177
+
178
+ ```typescript
179
+ const UsersContract = defineRoutes({
180
+ getUser: {
181
+ method: "GET",
182
+ path: "/users/:id",
183
+ summary: "Get User by ID",
184
+ params: z.object({
185
+ id: z.string(),
186
+ }),
187
+ },
188
+ })
189
+
190
+ // Client usage
191
+ await client.getUser({ params: { id: "user-123" } })
192
+ ```
193
+
194
+ ### Query Parameters
195
+
196
+ ```typescript
197
+ const ProductsContract = defineRoutes({
198
+ searchProducts: {
199
+ method: "GET",
200
+ path: "/products",
201
+ summary: "Search Products",
202
+ query: z.object({
203
+ q: z.string(),
204
+ category: z.string().optional(),
205
+ limit: z.number().default(10),
206
+ }),
207
+ },
208
+ })
209
+
210
+ // Client usage
211
+ await client.searchProducts({
212
+ query: { q: "laptop", category: "electronics", limit: 20 }
213
+ })
214
+ ```
215
+
216
+ ### Custom Security
217
+
218
+ ```typescript
219
+ const AdminContract = defineRoutes({
220
+ deleteUser: {
221
+ method: "DELETE",
222
+ path: "/admin/users/:id",
223
+ summary: "Delete User",
224
+ tags: ["Admin"],
225
+ security: ["BearerAuth", "AdminRole"],
226
+ params: z.object({
227
+ id: z.string(),
228
+ }),
229
+ },
230
+ })
231
+ ```
232
+
233
+ ### Schema Examples
234
+
235
+ Add examples to your schemas for better documentation:
236
+
237
+ ```typescript
238
+ import { z } from 'zod'
239
+
240
+ const createUserSchema = z.object({
241
+ email: z.string().email().example("john@example.com"),
242
+ name: z.string().example("John Doe"),
243
+ age: z.number().min(18).example(25),
244
+ })
245
+ ```
246
+
247
+ ## Publishing Contracts
248
+
249
+ For teams with separate frontend/backend repos, publish your contracts as an npm package:
250
+
251
+ ### 1. Create Contracts Package
252
+ packages/api-contracts/package.json
253
+ ```json
254
+
255
+ {
256
+ "name": "@mychange/api-contracts",
257
+ "version": "1.0.0",
258
+ "private": true,
259
+ "main": "./dist/index.js",
260
+ "types": "./dist/index.d.ts",
261
+ "dependencies": {
262
+ "typecompass": "^1.0.0"
263
+ },
264
+ "peerDependencies": {
265
+ "zod": "^3.0.0"
266
+ }
267
+ }
268
+ ```
269
+
270
+ ### 2. Export Combined Contract
271
+
272
+ ```typescript
273
+ // packages/api-contracts/src/index.ts
274
+ export { ApiContract } from './contracts'
275
+ export type { ApiContract as ApiContractType } from './contracts'
276
+ ```
277
+
278
+ ### 3. Install in Frontend
279
+
280
+ ```bash
281
+ npm install @mychange/api-contracts
282
+ ```
283
+
284
+ ```typescript
285
+ import { ApiContract } from '@mychange/api-contracts'
286
+ import { initCombinedClient } from 'typecompass/client'
287
+
288
+ const api = initCombinedClient(ApiContract, axiosInstance)
289
+ ```
290
+
291
+ ## API Reference
292
+
293
+ ### `defineRoutes(routes)`
294
+
295
+ Define a single service contract.
296
+
297
+ **Parameters:**
298
+ - `routes` - Object mapping route names to route configurations
299
+
300
+ **Returns:** `Contract<T>`
301
+
302
+ ### `combineContracts(contracts)`
303
+
304
+ Combine multiple contracts into one.
305
+
306
+ **Parameters:**
307
+ - `contracts` - Object mapping namespace to contracts
308
+
309
+ **Returns:** `CombinedContract<T>`
310
+
311
+ ### `generateOpenApi(contract, config)`
312
+
313
+ Generate OpenAPI 3.0 specification.
314
+
315
+ **Parameters:**
316
+ - `contract` - Contract or CombinedContract
317
+ - `config` - OpenAPI configuration (title, version, servers, etc.)
318
+
319
+ **Returns:** OpenAPI JSON object
320
+
321
+ ### `initClient(contract, api)`
322
+
323
+ Initialize type-safe client for a single contract.
324
+
325
+ **Parameters:**
326
+ - `contract` - Contract to use
327
+ - `api` - Axios-like API provider
328
+
329
+ **Returns:** Typed client object
330
+
331
+ ### `initCombinedClient(contract, api)`
332
+
333
+ Initialize type-safe client for combined contracts.
334
+
335
+ **Parameters:**
336
+ - `contract` - CombinedContract to use
337
+ - `api` - Axios-like API provider
338
+
339
+ **Returns:** Namespaced typed client object
340
+
341
+ ## Route Configuration
342
+
343
+ ```typescript
344
+ interface RouteConfig {
345
+ method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE"
346
+ path: string // e.g., "/users/:id"
347
+ summary: string // Short description
348
+ tags?: string[] // For OpenAPI grouping
349
+ security?: string[] // Security scheme names
350
+ body?: z.ZodType // Request body schema
351
+ query?: z.ZodType // Query parameters schema
352
+ params?: z.ZodType // Path parameters schema
353
+ responses?: Record<number, ResponseConfig>
354
+ description?: string // Long description
355
+ }
356
+ ```
357
+
358
+ ## License
359
+
360
+ MIT © MyChange
361
+
362
+ ## Contributing
363
+
364
+ Contributions welcome! Please open an issue or PR.
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "typecompass",
3
+ "version": "1.0.0",
4
+ "description": "Type-safe API contracts with OpenAPI generation for TypeScript",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "require": "./dist/index.js"
12
+ },
13
+ "./client": {
14
+ "types": "./dist/client.d.ts",
15
+ "import": "./dist/client.js",
16
+ "require": "./dist/client.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "README.md",
22
+ "LICENSE"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsc",
26
+ "dev": "tsc --watch",
27
+ "prepublishOnly": "bun run build"
28
+ },
29
+ "keywords": [
30
+ "openapi",
31
+ "typescript",
32
+ "api",
33
+ "contract",
34
+ "type-safe",
35
+ "zod",
36
+ "rest",
37
+ "client",
38
+ "server"
39
+ ],
40
+ "author": "MyChange",
41
+ "license": "MIT",
42
+ "peerDependencies": {
43
+ "zod": "^4.3.6"
44
+ },
45
+ "devDependencies": {
46
+ "@types/bun": "^1.3.8",
47
+ "typescript": "^5.0.0",
48
+ "zod": "^4.3.6"
49
+ }
50
+ }