routesync 1.0.26 → 1.0.28
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 +245 -206
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Stop writing API clients by hand.
|
|
4
4
|
|
|
5
|
-
RouteSync syncs your Laravel (or PHP) routes to a fully-typed frontend SDK — complete with TypeScript types, a camelCase mapper,
|
|
5
|
+
RouteSync syncs your Laravel (or PHP) routes to a fully-typed frontend SDK — complete with TypeScript types, a camelCase mapper, React/Vue Query hooks, and Next.js Server Actions. One command. Zero boilerplate.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -13,21 +13,26 @@ You've been there. The backend ships a new endpoint. You update the route, write
|
|
|
13
13
|
RouteSync does all of that. You point it at `routes/api.php` and it generates the whole thing.
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
# Step 1 — in your Laravel folder
|
|
17
|
+
npx routesync scan --input routes/api.php --models
|
|
18
18
|
|
|
19
|
+
# Step 2 — in your frontend folder
|
|
20
|
+
npx routesync generate --manifest routesync.manifest.json --output src/api --next-actions --zod
|
|
19
21
|
```
|
|
20
|
-
routesync sync
|
|
21
|
-
|
|
22
|
-
✔ Scanning Laravel routes (24 routes)
|
|
23
|
-
✔ Generating types
|
|
24
|
-
✔ Generating SDK
|
|
25
|
-
✔ Generating hooks
|
|
26
22
|
|
|
27
|
-
|
|
23
|
+
```
|
|
24
|
+
✔ Found 35 routes, 19 models → routesync.manifest.json
|
|
25
|
+
|
|
26
|
+
✔ SDK generated → src/api
|
|
27
|
+
api.ts Typed API client
|
|
28
|
+
types.ts TypeScript interfaces (from real DB columns)
|
|
29
|
+
hooks.ts React Query hooks
|
|
30
|
+
actions.ts Next.js Server Actions
|
|
31
|
+
schemas.ts Zod validation schemas
|
|
32
|
+
index.ts Barrel export
|
|
28
33
|
```
|
|
29
34
|
|
|
30
|
-
That's it. Your frontend has a typed client,
|
|
35
|
+
That's it. Your frontend has a typed client, real DB-derived types, Zod schemas, and ready-to-use hooks — and you didn't write any of it.
|
|
31
36
|
|
|
32
37
|
---
|
|
33
38
|
|
|
@@ -35,10 +40,10 @@ That's it. Your frontend has a typed client, response types, and ready-to-use ho
|
|
|
35
40
|
|
|
36
41
|
| Package | What it does |
|
|
37
42
|
|---|---|
|
|
38
|
-
| `@routesync/sdk` | The core developer API. `defineApi`, `
|
|
43
|
+
| `@routesync/sdk` | The core developer API. `defineApi`, `endpoint`, `resource`, `createService`. |
|
|
39
44
|
| `@routesync/core` | HTTP client engine, auth, path resolution, error handling. |
|
|
40
|
-
| `@routesync/cli` | Scans routes, generates types + SDK + hooks. |
|
|
41
|
-
| `@routesync/react` |
|
|
45
|
+
| `@routesync/cli` | Scans routes + models, generates types + SDK + hooks + actions. |
|
|
46
|
+
| `@routesync/react` | `useApiQuery` / `useApiMutation` hooks built on TanStack Query. |
|
|
42
47
|
| `@routesync/vue` | Vue Query composables, same idea. |
|
|
43
48
|
|
|
44
49
|
---
|
|
@@ -46,304 +51,338 @@ That's it. Your frontend has a typed client, response types, and ready-to-use ho
|
|
|
46
51
|
## Install
|
|
47
52
|
|
|
48
53
|
```bash
|
|
49
|
-
# SDK
|
|
50
|
-
npm install @
|
|
54
|
+
# SDK + React hooks
|
|
55
|
+
npm install routesync @tanstack/react-query
|
|
51
56
|
|
|
52
|
-
#
|
|
53
|
-
npm install
|
|
57
|
+
# Vue composables
|
|
58
|
+
npm install routesync @tanstack/vue-query
|
|
54
59
|
|
|
55
|
-
# With
|
|
56
|
-
npm install
|
|
57
|
-
|
|
58
|
-
# CLI (route scanner + code generator)
|
|
59
|
-
npm install -g @routesync/cli
|
|
60
|
+
# With Zod validation
|
|
61
|
+
npm install routesync zod
|
|
60
62
|
```
|
|
61
63
|
|
|
62
64
|
---
|
|
63
65
|
|
|
64
|
-
##
|
|
65
|
-
|
|
66
|
-
### Option A — Define routes manually
|
|
66
|
+
## Full Workflow (Laravel + Next.js)
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
### 1. Scan routes & models
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
import { defineApi } from '@routesync/sdk'
|
|
72
|
-
|
|
73
|
-
export const api = defineApi(
|
|
74
|
-
{
|
|
75
|
-
auth: {
|
|
76
|
-
login: { method: 'POST', path: '/login' },
|
|
77
|
-
logout: { method: 'POST', path: '/logout', auth: true },
|
|
78
|
-
},
|
|
79
|
-
products: {
|
|
80
|
-
list: { method: 'GET', path: '/products' },
|
|
81
|
-
detail: { method: 'GET', path: '/products/:id' },
|
|
82
|
-
create: { method: 'POST', path: '/products', auth: true },
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
{ baseURL: 'https://api.myapp.com/api' }
|
|
86
|
-
)
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
Then call it:
|
|
90
|
-
|
|
91
|
-
```ts
|
|
92
|
-
// GET /products?page=1&search=kaos
|
|
93
|
-
await api.products.list({ query: { page: 1, search: 'kaos' } })
|
|
70
|
+
Run this from your **Laravel project root**:
|
|
94
71
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
// POST /products
|
|
99
|
-
await api.products.create({ body: { name: 'Kaos Polos', price: 89000 } })
|
|
72
|
+
```bash
|
|
73
|
+
npx routesync scan --input routes/api.php --models
|
|
100
74
|
```
|
|
101
75
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
76
|
+
| Option | Default | Description |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| `--input` | `routes/api.php` | Path to your Laravel routes file |
|
|
79
|
+
| `--output` | `routesync.manifest.json` | Where to save the manifest |
|
|
80
|
+
| `--baseURL` | `http://localhost/api` | API base URL |
|
|
81
|
+
| `--models` | off | Also scan `app/Models/` for real DB column types |
|
|
82
|
+
|
|
83
|
+
> **`--models` requirement:** PHP must be available in your terminal and your database must be accessible (`.env` configured). The scanner runs a temporary PHP script via Laravel's bootstrap to read `Schema::getColumns()` from each Eloquent model.
|
|
84
|
+
|
|
85
|
+
> **Important — manifest location:** The manifest is saved in whichever folder you run `scan` from. If you run it from your Laravel root, copy the manifest to your frontend folder before running `generate`:
|
|
86
|
+
>
|
|
87
|
+
> ```bash
|
|
88
|
+
> # Windows PowerShell
|
|
89
|
+
> copy ..\routesync.manifest.json .
|
|
90
|
+
>
|
|
91
|
+
> # macOS / Linux
|
|
92
|
+
> cp ../backend/routesync.manifest.json .
|
|
93
|
+
> ```
|
|
105
94
|
|
|
106
|
-
###
|
|
95
|
+
### 2. Generate the SDK
|
|
107
96
|
|
|
108
|
-
|
|
97
|
+
Run this from your **frontend project root**:
|
|
109
98
|
|
|
110
99
|
```bash
|
|
111
|
-
npx routesync
|
|
112
|
-
--
|
|
100
|
+
npx routesync generate \
|
|
101
|
+
--manifest routesync.manifest.json \
|
|
113
102
|
--output src/api \
|
|
114
|
-
--
|
|
103
|
+
--next-actions \
|
|
104
|
+
--zod
|
|
115
105
|
```
|
|
116
106
|
|
|
117
|
-
|
|
107
|
+
| Option | Default | Description |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| `--manifest` | `routesync.manifest.json` | Path to manifest from step 1 |
|
|
110
|
+
| `--output` | `src/api` | Output folder |
|
|
111
|
+
| `--next-actions` | off | Generate `actions.ts` (Next.js Server Actions) |
|
|
112
|
+
| `--zod` | off | Generate `schemas.ts` (Zod validation) |
|
|
113
|
+
| `--no-hooks` | off | Skip generating `hooks.ts` |
|
|
114
|
+
| `--msw` | off | Generate MSW mock handlers |
|
|
115
|
+
|
|
116
|
+
> **Windows PowerShell note:** Do not use backslash `\` for line continuation — PowerShell treats it differently. Run the command on a single line:
|
|
117
|
+
>
|
|
118
|
+
> ```powershell
|
|
119
|
+
> npx routesync generate --manifest routesync.manifest.json --output src/api --next-actions --zod
|
|
120
|
+
> ```
|
|
121
|
+
|
|
122
|
+
### Generated files
|
|
118
123
|
|
|
119
124
|
```
|
|
120
125
|
src/api/
|
|
121
|
-
├── api.ts
|
|
122
|
-
├── types.ts
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
npx routesync watch --input routes/api.php --output src/api
|
|
126
|
+
├── api.ts ← defineApi() with all endpoints + Contract types
|
|
127
|
+
├── types.ts ← TypeScript interfaces (real DB columns when --models used)
|
|
128
|
+
├── hooks.ts ← useApiQuery / useApiMutation per endpoint
|
|
129
|
+
├── actions.ts ← Next.js Server Actions (--next-actions)
|
|
130
|
+
├── schemas.ts ← Zod schemas from FormRequest rules (--zod)
|
|
131
|
+
├── index.ts ← Barrel re-export
|
|
132
|
+
└── core/
|
|
133
|
+
└── models.ts ← Raw Eloquent model interfaces (when --models used)
|
|
130
134
|
```
|
|
131
135
|
|
|
132
|
-
|
|
136
|
+
### 3. Initialize the client
|
|
133
137
|
|
|
134
|
-
|
|
138
|
+
Call `createClient` once at app startup (e.g. in your layout or provider):
|
|
135
139
|
|
|
136
140
|
```ts
|
|
137
|
-
|
|
141
|
+
// src/lib/api-client.ts
|
|
142
|
+
import { createClient } from 'routesync'
|
|
138
143
|
|
|
139
|
-
|
|
140
|
-
baseURL:
|
|
144
|
+
createClient({
|
|
145
|
+
baseURL: process.env.NEXT_PUBLIC_API_URL!, // e.g. http://localhost:8000/api
|
|
146
|
+
withCredentials: true,
|
|
141
147
|
})
|
|
142
|
-
|
|
143
|
-
// After login:
|
|
144
|
-
setToken(response.data.token)
|
|
145
|
-
|
|
146
|
-
// On logout:
|
|
147
|
-
clearToken()
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
-
|
|
150
|
+
### 4. Use in components
|
|
151
151
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
```ts
|
|
157
|
-
import { createService } from '@routesync/sdk'
|
|
158
|
-
import { createHooks } from '@routesync/react'
|
|
159
|
-
import { z } from 'zod'
|
|
160
|
-
|
|
161
|
-
const productSchema = z.object({
|
|
162
|
-
id: z.number(),
|
|
163
|
-
product_name: z.string(),
|
|
164
|
-
price: z.number(),
|
|
165
|
-
})
|
|
152
|
+
```tsx
|
|
153
|
+
import { useApiQuery, useApiMutation } from 'routesync/react'
|
|
154
|
+
import { api } from '@/api/api'
|
|
166
155
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
156
|
+
// GET — fetch data
|
|
157
|
+
function ProdukList() {
|
|
158
|
+
const { data, isLoading } = useApiQuery(api.produk.get, {
|
|
159
|
+
query: { page: 1, search: 'kaos' }
|
|
160
|
+
})
|
|
171
161
|
|
|
172
|
-
|
|
173
|
-
|
|
162
|
+
if (isLoading) return <p>Loading...</p>
|
|
163
|
+
return <ul>{data?.map(p => <li key={p.id}>{p.nama}</li>)}</ul>
|
|
164
|
+
}
|
|
174
165
|
|
|
175
|
-
|
|
166
|
+
// GET with path params
|
|
167
|
+
function ProdukDetail({ id }: { id: string }) {
|
|
168
|
+
const { data } = useApiQuery(api.produk.getId, { params: { id } })
|
|
169
|
+
return <div>{data?.nama}</div>
|
|
170
|
+
}
|
|
176
171
|
|
|
177
|
-
|
|
178
|
-
function
|
|
179
|
-
const
|
|
180
|
-
const mutation = useCreate()
|
|
172
|
+
// POST / mutation
|
|
173
|
+
function AddToCart({ produkItemId }: { produkItemId: string }) {
|
|
174
|
+
const mutation = useApiMutation(api.cart.postItems)
|
|
181
175
|
|
|
182
176
|
return (
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
Add Product
|
|
187
|
-
</button>
|
|
188
|
-
</>
|
|
177
|
+
<button onClick={() => mutation.mutate({ body: { produk_item_id: produkItemId, qty: 1 } })}>
|
|
178
|
+
Tambah ke Keranjang
|
|
179
|
+
</button>
|
|
189
180
|
)
|
|
190
181
|
}
|
|
191
182
|
```
|
|
192
183
|
|
|
193
|
-
|
|
184
|
+
### 5. Use Server Actions (Next.js)
|
|
194
185
|
|
|
195
|
-
|
|
186
|
+
```ts
|
|
187
|
+
// In a Server Component or form action
|
|
188
|
+
import { produkGetAction, cartPostItemsAction } from '@/api/actions'
|
|
196
189
|
|
|
197
|
-
|
|
190
|
+
// GET — no params needed
|
|
191
|
+
const result = await produkGetAction({ query: { page: 1 } })
|
|
192
|
+
if (result.success) console.log(result.data)
|
|
198
193
|
|
|
199
|
-
|
|
200
|
-
|
|
194
|
+
// POST — with body
|
|
195
|
+
const result = await cartPostItemsAction({ body: { produk_item_id: '5', qty: 1 } })
|
|
201
196
|
|
|
202
|
-
|
|
197
|
+
// GET with path params — params are required
|
|
198
|
+
const result = await produkGetIdAction({ params: { id: '42' } })
|
|
203
199
|
```
|
|
204
200
|
|
|
205
|
-
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Data Transformation
|
|
204
|
+
|
|
205
|
+
RouteSync handles all data mapping automatically:
|
|
206
|
+
|
|
207
|
+
| Direction | What happens | Where |
|
|
208
|
+
|---|---|---|
|
|
209
|
+
| Response (backend → frontend) | `snake_case` → `camelCase` keys | `HttpClient` interceptor |
|
|
210
|
+
| Request (frontend → backend) | `camelCase` → `snake_case` keys | `HttpClient` interceptor |
|
|
211
|
+
| Response unwrap | `{ data: T, message, meta }` → `T` | `HttpClient` `.get()` / `.post()` etc. |
|
|
212
|
+
| Zod validation | Parse + validate response shape | Per-endpoint `responseSchema` |
|
|
213
|
+
|
|
214
|
+
No extra config needed. `product_name` from Laravel becomes `productName` in your component automatically.
|
|
206
215
|
|
|
207
216
|
---
|
|
208
217
|
|
|
209
|
-
|
|
218
|
+
## Manual Route Definitions
|
|
210
219
|
|
|
211
|
-
|
|
220
|
+
If you don't have a Laravel backend, define routes manually:
|
|
212
221
|
|
|
213
222
|
```ts
|
|
214
|
-
import { defineApi, resource } from '
|
|
223
|
+
import { defineApi, endpoint, resource } from 'routesync'
|
|
224
|
+
|
|
225
|
+
createClient({ baseURL: 'https://api.myapp.com/api' })
|
|
215
226
|
|
|
216
|
-
const api = defineApi({
|
|
227
|
+
export const api = defineApi({
|
|
228
|
+
// Basic endpoint
|
|
229
|
+
auth: {
|
|
230
|
+
login: endpoint<{ token: string }>({ method: 'POST', path: '/login' }),
|
|
231
|
+
logout: endpoint({ method: 'POST', path: '/logout', auth: true }),
|
|
232
|
+
},
|
|
233
|
+
|
|
234
|
+
// With path params
|
|
235
|
+
produk: {
|
|
236
|
+
list: endpoint<ProdukItem[]>({ method: 'GET', path: '/produk' }),
|
|
237
|
+
detail: endpoint<ProdukItem, { id: string }>({ method: 'GET', path: '/produk/:id' }),
|
|
238
|
+
create: endpoint<ProdukItem, unknown, CreateProdukBody>({
|
|
239
|
+
method: 'POST', path: '/produk', auth: true
|
|
240
|
+
}),
|
|
241
|
+
},
|
|
242
|
+
|
|
243
|
+
// resource() — shared auth/headers for a group
|
|
217
244
|
cart: resource({
|
|
218
|
-
auth: true,
|
|
245
|
+
auth: true,
|
|
219
246
|
endpoints: {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
remove: { method: 'DELETE', path: '/cart/items/:id' },
|
|
225
|
-
checkout: { method: 'POST', path: '/cart/checkout' },
|
|
247
|
+
get: { method: 'GET', path: '/cart' },
|
|
248
|
+
add: { method: 'POST', path: '/cart/items' },
|
|
249
|
+
update: { method: 'PATCH', path: '/cart/items/:id' },
|
|
250
|
+
remove: { method: 'DELETE', path: '/cart/items/:id' },
|
|
226
251
|
}
|
|
227
252
|
})
|
|
228
|
-
}
|
|
253
|
+
})
|
|
229
254
|
```
|
|
230
255
|
|
|
231
|
-
|
|
256
|
+
`endpoint<TResponse, TParams, TBody>` — generic order:
|
|
257
|
+
1. **TResponse** — shape returned by the backend
|
|
258
|
+
2. **TParams** — path params like `{ id: string }`
|
|
259
|
+
3. **TBody** — POST/PUT/PATCH body shape
|
|
232
260
|
|
|
233
|
-
|
|
261
|
+
---
|
|
234
262
|
|
|
235
|
-
|
|
263
|
+
## Authentication
|
|
236
264
|
|
|
237
265
|
```ts
|
|
238
|
-
import {
|
|
239
|
-
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}, config)
|
|
266
|
+
import { createClient } from 'routesync'
|
|
267
|
+
|
|
268
|
+
const client = createClient({ baseURL: 'https://api.myapp.com/api' })
|
|
269
|
+
|
|
270
|
+
// After login — set token
|
|
271
|
+
client.setToken(response.token)
|
|
272
|
+
|
|
273
|
+
// On logout — clear token
|
|
274
|
+
client.removeToken()
|
|
250
275
|
```
|
|
251
276
|
|
|
252
|
-
|
|
253
|
-
>
|
|
254
|
-
> **Important:** To ensure your schemas are detected automatically, you **must use Laravel `FormRequest` classes**. Inline `$request->validate([...])` calls inside Controller methods cannot be reliably extracted.
|
|
255
|
-
>
|
|
256
|
-
> ```php
|
|
257
|
-
> // ✅ DO THIS: RouteSync will generate Zod schemas automatically
|
|
258
|
-
> public function store(StoreProductRequest $request)
|
|
259
|
-
>
|
|
260
|
-
> // ❌ AVOID THIS: Validation rules will be ignored
|
|
261
|
-
> public function store(Request $request) {
|
|
262
|
-
> $request->validate([...]);
|
|
263
|
-
> }
|
|
264
|
-
> ```
|
|
277
|
+
Any endpoint with `auth: true` automatically gets `Authorization: Bearer TOKEN` injected. For Next.js Server Actions, the generated `actions.ts` reads the token from cookies automatically via `getAuthHeaders()`.
|
|
265
278
|
|
|
266
279
|
---
|
|
267
280
|
|
|
268
|
-
|
|
281
|
+
## React Query Hooks
|
|
269
282
|
|
|
270
|
-
|
|
283
|
+
### Auto-generated hooks (from CLI)
|
|
271
284
|
|
|
272
285
|
```ts
|
|
273
|
-
import {
|
|
274
|
-
import {
|
|
286
|
+
import { useApiQuery, useApiMutation } from 'routesync/react'
|
|
287
|
+
import { api } from '@/api/api'
|
|
275
288
|
|
|
276
|
-
|
|
277
|
-
const {
|
|
289
|
+
// GET
|
|
290
|
+
const { data, isLoading } = useApiQuery(api.orders.get)
|
|
291
|
+
|
|
292
|
+
// GET with params + query
|
|
293
|
+
const { data } = useApiQuery(api.orders.getId, { params: { id: '1' } })
|
|
294
|
+
|
|
295
|
+
// Mutation
|
|
296
|
+
const mutation = useApiMutation(api.cart.postItems)
|
|
297
|
+
mutation.mutate({ body: { produk_item_id: '5', qty: 1 } })
|
|
278
298
|
```
|
|
279
299
|
|
|
280
|
-
|
|
300
|
+
### Generate hooks for entire api at once
|
|
281
301
|
|
|
282
|
-
|
|
302
|
+
```ts
|
|
303
|
+
import { generateHooks } from 'routesync'
|
|
283
304
|
|
|
284
|
-
|
|
305
|
+
const hooks = generateHooks(api)
|
|
306
|
+
const { useOrdersGet, useCartPostItems } = hooks
|
|
307
|
+
// GET/DELETE → useQuery, everything else → useMutation
|
|
308
|
+
```
|
|
285
309
|
|
|
286
|
-
|
|
310
|
+
### createHooks — per group
|
|
287
311
|
|
|
288
312
|
```ts
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
const
|
|
313
|
+
import { createHooks } from 'routesync/react'
|
|
314
|
+
|
|
315
|
+
const cartHooks = createHooks(api.cart)
|
|
316
|
+
const { usePostItems, usePatchItemsProdukItemId } = cartHooks
|
|
292
317
|
```
|
|
293
318
|
|
|
294
|
-
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## Zod Schema Validation
|
|
322
|
+
|
|
323
|
+
When using `--zod` with `routesync generate`, `schemas.ts` is generated from your Laravel `FormRequest` rules.
|
|
324
|
+
|
|
325
|
+
> **Requirement:** You must use Laravel `FormRequest` classes for rules to be detected:
|
|
326
|
+
>
|
|
327
|
+
> ```php
|
|
328
|
+
> // ✅ RouteSync will auto-generate Zod schema
|
|
329
|
+
> public function store(StoreProductRequest $request) { ... }
|
|
330
|
+
>
|
|
331
|
+
> // ❌ Rules will not be detected
|
|
332
|
+
> public function store(Request $request) {
|
|
333
|
+
> $request->validate([...]);
|
|
334
|
+
> }
|
|
335
|
+
> ```
|
|
295
336
|
|
|
296
337
|
---
|
|
297
338
|
|
|
298
|
-
## CLI
|
|
339
|
+
## CLI Reference
|
|
299
340
|
|
|
300
341
|
```bash
|
|
301
|
-
# Scan routes
|
|
342
|
+
# Scan Laravel routes only
|
|
302
343
|
npx routesync scan --input routes/api.php
|
|
303
344
|
|
|
345
|
+
# Scan routes + Eloquent models (recommended)
|
|
346
|
+
npx routesync scan --input routes/api.php --models
|
|
347
|
+
|
|
304
348
|
# Generate SDK from manifest
|
|
305
|
-
npx routesync generate --manifest routesync.json --output src/api
|
|
349
|
+
npx routesync generate --manifest routesync.manifest.json --output src/api
|
|
306
350
|
|
|
307
|
-
#
|
|
308
|
-
npx routesync
|
|
351
|
+
# Generate everything
|
|
352
|
+
npx routesync generate --manifest routesync.manifest.json --output src/api --next-actions --zod
|
|
309
353
|
|
|
310
|
-
# Watch mode — auto-
|
|
354
|
+
# Watch mode — auto re-generates on route file change
|
|
311
355
|
npx routesync watch --input routes/api.php --output src/api
|
|
312
356
|
```
|
|
313
357
|
|
|
314
358
|
---
|
|
315
359
|
|
|
316
|
-
## How
|
|
360
|
+
## How It Works
|
|
317
361
|
|
|
318
362
|
```
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
routesync
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
363
|
+
routes/api.php + app/Models/
|
|
364
|
+
↓ routesync scan --models
|
|
365
|
+
routesync.manifest.json
|
|
366
|
+
↓ routesync generate
|
|
367
|
+
src/api/
|
|
368
|
+
├── api.ts ← defineApi + endpoints
|
|
369
|
+
├── types.ts ← interfaces from DB columns
|
|
370
|
+
├── hooks.ts ← TanStack Query hooks
|
|
371
|
+
├── actions.ts ← Next.js Server Actions
|
|
372
|
+
└── schemas.ts ← Zod schemas
|
|
373
|
+
↓
|
|
374
|
+
React / Vue / Next.js
|
|
328
375
|
```
|
|
329
376
|
|
|
330
|
-
The CLI parses your route file, builds a language-agnostic manifest, then feeds it to
|
|
331
|
-
|
|
332
|
-
---
|
|
333
|
-
|
|
334
|
-
## Roadmap
|
|
335
|
-
|
|
336
|
-
- [ ] OpenAPI export from the manifest
|
|
337
|
-
- [ ] SWR adapter alongside React Query
|
|
338
|
-
- [ ] Solid.js composables
|
|
339
|
-
- [ ] First-class Next.js Server Actions integration
|
|
340
|
-
- [ ] VSCode extension — IntelliSense on `api.` without importing
|
|
377
|
+
The CLI parses your route file via PHP reflection (using Laravel's own bootstrap), builds a language-agnostic manifest, then feeds it to independent generators. Each generator can be used standalone.
|
|
341
378
|
|
|
342
379
|
---
|
|
343
380
|
|
|
344
381
|
## Requirements
|
|
345
382
|
|
|
346
|
-
- Node.js >=
|
|
383
|
+
- Node.js >= 20
|
|
384
|
+
- PHP available in PATH (for `scan --models`)
|
|
385
|
+
- Laravel project with database accessible (for `scan --models`)
|
|
347
386
|
|
|
348
387
|
## License
|
|
349
388
|
|