routesync 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.
- package/README.md +289 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +436 -0
- package/dist/core.d.mts +206 -0
- package/dist/core.d.ts +206 -0
- package/dist/core.js +353 -0
- package/dist/core.mjs +307 -0
- package/dist/react.d.mts +95 -0
- package/dist/react.d.ts +95 -0
- package/dist/react.js +77 -0
- package/dist/react.mjs +48 -0
- package/dist/sdk.d.mts +269 -0
- package/dist/sdk.d.ts +269 -0
- package/dist/sdk.js +519 -0
- package/dist/sdk.mjs +476 -0
- package/dist/vue.d.mts +108 -0
- package/dist/vue.d.ts +108 -0
- package/dist/vue.js +66 -0
- package/dist/vue.mjs +40 -0
- package/package.json +98 -0
package/README.md
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# RouteSync
|
|
2
|
+
|
|
3
|
+
> Laravel routes to typed frontend SDKs.
|
|
4
|
+
|
|
5
|
+
Modern API SDK ecosystem for Laravel and PHP with typed clients, hooks, route syncing, and code generation.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Packages
|
|
10
|
+
|
|
11
|
+
| Package | Description |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `@routesync/core` | HTTP client engine, auth, routing, error handling |
|
|
14
|
+
| `@routesync/sdk` | Developer-facing API: `defineApi`, `createService` |
|
|
15
|
+
| `@routesync/cli` | CLI: scan routes, generate SDK, types, hooks |
|
|
16
|
+
| `@routesync/react` | React Query hooks factory |
|
|
17
|
+
| `@routesync/vue` | Vue Query composables factory |
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
### 1. Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install @routesync/sdk
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 2. Define your API
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { defineApi, resource } from '@routesync/sdk'
|
|
33
|
+
|
|
34
|
+
// CartSchema, CartMapper, CheckoutSchema, and CheckoutMapper are your own
|
|
35
|
+
// endpoint-level contracts.
|
|
36
|
+
export const api = defineApi(
|
|
37
|
+
{
|
|
38
|
+
auth: {
|
|
39
|
+
login: { method: 'POST', path: '/login' },
|
|
40
|
+
logout: { method: 'POST', path: '/logout', auth: true }
|
|
41
|
+
},
|
|
42
|
+
produk: {
|
|
43
|
+
list: { method: 'GET', path: '/produk' },
|
|
44
|
+
detail: { method: 'GET', path: '/produk/:id' }
|
|
45
|
+
},
|
|
46
|
+
cart: {
|
|
47
|
+
addItem: { method: 'POST', path: '/cart/items', auth: true },
|
|
48
|
+
removeItem: { method: 'DELETE', path: '/cart/items/:produkItemId', auth: true }
|
|
49
|
+
},
|
|
50
|
+
cartItems: resource({
|
|
51
|
+
path: '/cart/items',
|
|
52
|
+
endpoints: {
|
|
53
|
+
list: {
|
|
54
|
+
method: 'GET',
|
|
55
|
+
schema: CartSchema.list,
|
|
56
|
+
mapper: CartMapper.list
|
|
57
|
+
},
|
|
58
|
+
show: {
|
|
59
|
+
method: 'GET',
|
|
60
|
+
path: '/:id',
|
|
61
|
+
schema: CartSchema.show,
|
|
62
|
+
mapper: CartMapper.show
|
|
63
|
+
},
|
|
64
|
+
create: {
|
|
65
|
+
method: 'POST',
|
|
66
|
+
schema: CartSchema.create,
|
|
67
|
+
mapper: CartMapper.create
|
|
68
|
+
},
|
|
69
|
+
update: {
|
|
70
|
+
method: 'PATCH',
|
|
71
|
+
path: '/:id',
|
|
72
|
+
schema: CartSchema.update,
|
|
73
|
+
mapper: CartMapper.update
|
|
74
|
+
},
|
|
75
|
+
checkout: {
|
|
76
|
+
method: 'POST',
|
|
77
|
+
path: '/checkout',
|
|
78
|
+
schema: CheckoutSchema.create,
|
|
79
|
+
mapper: CheckoutMapper.create
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
baseURL: 'http://localhost:8000/api'
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 3. Use it
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
// Login
|
|
94
|
+
await api.auth.login({ body: { email, password } })
|
|
95
|
+
|
|
96
|
+
// Get product list
|
|
97
|
+
await api.produk.list({ query: { page: 1, search: 'kaos' } })
|
|
98
|
+
|
|
99
|
+
// Get product detail (auto path param)
|
|
100
|
+
await api.produk.detail({ params: { id: 10 } })
|
|
101
|
+
// → GET /produk/10
|
|
102
|
+
|
|
103
|
+
// Add to cart
|
|
104
|
+
await api.cart.addItem({ body: { produk_id: 1, qty: 2 } })
|
|
105
|
+
|
|
106
|
+
// Remove from cart
|
|
107
|
+
await api.cart.removeItem({ params: { produkItemId: 5 } })
|
|
108
|
+
// → DELETE /cart/items/5
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## CLI: Auto-generate from Laravel Routes
|
|
114
|
+
|
|
115
|
+
### Install CLI
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
npm install -g @routesync/cli
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Sync in one command
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
npx routesync sync \
|
|
125
|
+
--input routes/api.php \
|
|
126
|
+
--output src/api \
|
|
127
|
+
--baseURL https://api.myapp.com/api
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Output:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
routesync sync
|
|
134
|
+
|
|
135
|
+
✔ Scanning Laravel routes (24 routes)
|
|
136
|
+
✔ Generating types
|
|
137
|
+
✔ Generating SDK
|
|
138
|
+
✔ Generating hooks
|
|
139
|
+
|
|
140
|
+
Sync complete!
|
|
141
|
+
|
|
142
|
+
Output: src/api
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Generated files:
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
src/api/
|
|
149
|
+
├── api.ts ← Typed API client
|
|
150
|
+
├── types.ts ← Response/request types
|
|
151
|
+
└── hooks.ts ← React Query hooks
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Available Commands
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
npx routesync scan # Scan routes → manifest JSON
|
|
158
|
+
npx routesync generate # Generate SDK from manifest
|
|
159
|
+
npx routesync sync # Scan + generate in one step
|
|
160
|
+
npx routesync watch # Watch and auto-sync on changes
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## React Query Hooks
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
npm install @routesync/react
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
import { z } from 'zod'
|
|
173
|
+
import { createHooks } from '@routesync/react'
|
|
174
|
+
import { createService } from '@routesync/sdk'
|
|
175
|
+
import type { CamelCasedPropertiesDeep } from '@routesync/sdk'
|
|
176
|
+
|
|
177
|
+
type BackendProduct = {
|
|
178
|
+
id: number
|
|
179
|
+
product_name: string
|
|
180
|
+
created_at: string
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
type Product = CamelCasedPropertiesDeep<BackendProduct>
|
|
184
|
+
|
|
185
|
+
type ProductInput = {
|
|
186
|
+
productName: string
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const backendProductSchema = z.object({
|
|
190
|
+
id: z.number(),
|
|
191
|
+
product_name: z.string(),
|
|
192
|
+
created_at: z.string()
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
const productInputSchema = z.object({
|
|
196
|
+
productName: z.string().min(1)
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
const productService = createService<Product, ProductInput>(client, '/produk', {
|
|
200
|
+
entitySchema: backendProductSchema,
|
|
201
|
+
listSchema: z.array(backendProductSchema),
|
|
202
|
+
createSchema: productInputSchema
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
const { useList, useDetail, useCreate } = createHooks(productService, 'produk')
|
|
206
|
+
|
|
207
|
+
// In component:
|
|
208
|
+
const { data, isLoading } = useList({ page: 1 })
|
|
209
|
+
const mutation = useCreate()
|
|
210
|
+
|
|
211
|
+
// Frontend camelCase payload is validated with Zod, then sent as snake_case.
|
|
212
|
+
mutation.mutate({ productName: 'Product Baru' })
|
|
213
|
+
|
|
214
|
+
// Backend snake_case response becomes frontend camelCase.
|
|
215
|
+
data?.[0].productName
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Vue Query Composables
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
npm install @routesync/vue
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
import { createVueComposables } from '@routesync/vue'
|
|
228
|
+
|
|
229
|
+
const { useList, useCreate } = createVueComposables(productService, 'produk')
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Authorization
|
|
235
|
+
|
|
236
|
+
```ts
|
|
237
|
+
import { createClient } from '@routesync/sdk'
|
|
238
|
+
|
|
239
|
+
const { setToken, clearToken } = createClient({
|
|
240
|
+
baseURL: 'https://api.myapp.com/api'
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
// After login:
|
|
244
|
+
setToken(response.data.token)
|
|
245
|
+
|
|
246
|
+
// After logout:
|
|
247
|
+
clearToken()
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Routes with `auth: true` automatically get `Authorization: Bearer TOKEN` injected.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Multi-Backend Support
|
|
255
|
+
|
|
256
|
+
```ts
|
|
257
|
+
// Laravel
|
|
258
|
+
const laravel = defineApi(routes, { baseURL: 'https://laravel-app.com/api' })
|
|
259
|
+
|
|
260
|
+
// CodeIgniter
|
|
261
|
+
const ci = defineApi(routes, { baseURL: 'https://ci-app.com/api' })
|
|
262
|
+
|
|
263
|
+
// Native PHP
|
|
264
|
+
const php = defineApi(routes, { baseURL: 'https://native-php.com/api' })
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Ecosystem Flow
|
|
270
|
+
|
|
271
|
+
```
|
|
272
|
+
Laravel Backend
|
|
273
|
+
↓
|
|
274
|
+
npx routesync sync
|
|
275
|
+
↓
|
|
276
|
+
Route Manifest (JSON)
|
|
277
|
+
↓
|
|
278
|
+
SDK Generator
|
|
279
|
+
↓
|
|
280
|
+
Typed Client + Types + Hooks
|
|
281
|
+
↓
|
|
282
|
+
React / Vue / Next.js / Mobile / AI Agent
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## License
|
|
288
|
+
|
|
289
|
+
MIT
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|