@l4yercak3/cli 1.2.21 → 1.3.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/bin/cli.js +25 -0
- package/docs/CLI_PAGE_DETECTION_REQUIREMENTS.md +519 -0
- package/package.json +1 -1
- package/src/api/backend-client.js +149 -0
- package/src/commands/connect.js +243 -0
- package/src/commands/pages.js +317 -0
- package/src/commands/scaffold.js +409 -0
- package/src/commands/spread.js +59 -181
- package/src/commands/sync.js +169 -0
- package/src/detectors/index.js +13 -0
- package/src/detectors/mapping-suggestor.js +119 -0
- package/src/detectors/model-detector.js +318 -0
- package/src/detectors/page-detector.js +480 -0
- package/src/generators/manifest-generator.js +154 -0
- package/src/utils/init-helpers.js +243 -0
- package/tests/page-detector.test.js +371 -0
package/bin/cli.js
CHANGED
|
@@ -18,6 +18,10 @@ const apiKeysCommand = require('../src/commands/api-keys');
|
|
|
18
18
|
const upgradeCommand = require('../src/commands/upgrade');
|
|
19
19
|
const mcpServerCommand = require('../src/commands/mcp-server');
|
|
20
20
|
const mcpSetupCommand = require('../src/commands/mcp-setup');
|
|
21
|
+
const pagesCommand = require('../src/commands/pages');
|
|
22
|
+
const connectCommand = require('../src/commands/connect');
|
|
23
|
+
const scaffoldCommand = require('../src/commands/scaffold');
|
|
24
|
+
const syncCommand = require('../src/commands/sync');
|
|
21
25
|
|
|
22
26
|
// Create CLI program
|
|
23
27
|
const program = new Command();
|
|
@@ -78,6 +82,27 @@ program
|
|
|
78
82
|
.description(mcpSetupCommand.description)
|
|
79
83
|
.action(mcpSetupCommand.handler);
|
|
80
84
|
|
|
85
|
+
program
|
|
86
|
+
.command(connectCommand.command)
|
|
87
|
+
.description(connectCommand.description)
|
|
88
|
+
.action(connectCommand.handler);
|
|
89
|
+
|
|
90
|
+
program
|
|
91
|
+
.command(scaffoldCommand.command)
|
|
92
|
+
.description(scaffoldCommand.description)
|
|
93
|
+
.action(scaffoldCommand.handler);
|
|
94
|
+
|
|
95
|
+
program
|
|
96
|
+
.command(syncCommand.command)
|
|
97
|
+
.description(syncCommand.description)
|
|
98
|
+
.action(syncCommand.handler);
|
|
99
|
+
|
|
100
|
+
program
|
|
101
|
+
.command(pagesCommand.command)
|
|
102
|
+
.description(pagesCommand.description)
|
|
103
|
+
.argument('[subcommand]', 'sync, list, or detect')
|
|
104
|
+
.action((subcommand) => pagesCommand.handler([subcommand]));
|
|
105
|
+
|
|
81
106
|
// Show logo and welcome message if no command provided
|
|
82
107
|
if (process.argv.length === 2) {
|
|
83
108
|
console.log(''); // initial spacing
|
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
# CLI Page Auto-Detection Requirements
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The CLI needs to auto-detect pages/screens in connected applications and sync them to the L4YERCAK3 backend. This enables the Activity Protocol to track data flow per-page and allows users to configure object bindings for each page.
|
|
6
|
+
|
|
7
|
+
## Backend API Endpoints (HTTP)
|
|
8
|
+
|
|
9
|
+
**Base URL**: `https://your-deployment.convex.site/api/v1/activity`
|
|
10
|
+
|
|
11
|
+
**Authentication**: All endpoints require authentication via one of:
|
|
12
|
+
- CLI session token: `Authorization: Bearer <cli_session_token>`
|
|
13
|
+
- API key: `X-API-Key: <api_key>`
|
|
14
|
+
- OAuth token: `Authorization: Bearer <oauth_token>`
|
|
15
|
+
|
|
16
|
+
**Required Scopes**:
|
|
17
|
+
- Read operations: `activity:read` or `applications:read`
|
|
18
|
+
- Write operations: `activity:write` or `applications:write`
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
### 1. Bulk Register Pages (Recommended for Auto-Detection)
|
|
23
|
+
|
|
24
|
+
**POST** `/api/v1/activity/pages/bulk`
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
curl -X POST "https://your-deployment.convex.site/api/v1/activity/pages/bulk" \
|
|
28
|
+
-H "Authorization: Bearer <cli_session_token>" \
|
|
29
|
+
-H "Content-Type: application/json" \
|
|
30
|
+
-d '{
|
|
31
|
+
"applicationId": "k1234567890abcdef",
|
|
32
|
+
"pages": [
|
|
33
|
+
{ "path": "/", "name": "Home", "pageType": "static" },
|
|
34
|
+
{ "path": "/dashboard", "name": "Dashboard", "pageType": "static" },
|
|
35
|
+
{ "path": "/dashboard/[id]", "name": "Dashboard Detail", "pageType": "dynamic" },
|
|
36
|
+
{ "path": "/api/users", "name": "API: Users", "pageType": "api_route" }
|
|
37
|
+
]
|
|
38
|
+
}'
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Request Body**:
|
|
42
|
+
```typescript
|
|
43
|
+
{
|
|
44
|
+
applicationId: string, // The connected_application object ID
|
|
45
|
+
pages: Array<{
|
|
46
|
+
path: string, // Route path, e.g., "/dashboard", "/checkout/[id]"
|
|
47
|
+
name: string, // Display name, e.g., "Dashboard", "Checkout Page"
|
|
48
|
+
pageType?: string, // "static", "dynamic", "api_route"
|
|
49
|
+
}>
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Response** (200 OK):
|
|
54
|
+
```typescript
|
|
55
|
+
{
|
|
56
|
+
success: true,
|
|
57
|
+
results: Array<{
|
|
58
|
+
path: string,
|
|
59
|
+
pageId: string, // Object ID for the page
|
|
60
|
+
created: boolean // true if new, false if updated
|
|
61
|
+
}>,
|
|
62
|
+
total: number,
|
|
63
|
+
created: number, // Count of newly created pages
|
|
64
|
+
updated: number // Count of updated pages
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
### 2. Register Single Page
|
|
71
|
+
|
|
72
|
+
**POST** `/api/v1/activity/pages`
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
curl -X POST "https://your-deployment.convex.site/api/v1/activity/pages" \
|
|
76
|
+
-H "Authorization: Bearer <cli_session_token>" \
|
|
77
|
+
-H "Content-Type: application/json" \
|
|
78
|
+
-d '{
|
|
79
|
+
"applicationId": "k1234567890abcdef",
|
|
80
|
+
"path": "/checkout/[productId]",
|
|
81
|
+
"name": "Checkout",
|
|
82
|
+
"detectionMethod": "cli_auto",
|
|
83
|
+
"pageType": "dynamic",
|
|
84
|
+
"objectBindings": [
|
|
85
|
+
{
|
|
86
|
+
"objectType": "product",
|
|
87
|
+
"accessMode": "read",
|
|
88
|
+
"syncEnabled": true,
|
|
89
|
+
"syncDirection": "pull"
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}'
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Request Body**:
|
|
96
|
+
```typescript
|
|
97
|
+
{
|
|
98
|
+
applicationId: string,
|
|
99
|
+
path: string,
|
|
100
|
+
name: string,
|
|
101
|
+
detectionMethod: "cli_auto" | "manual" | "runtime",
|
|
102
|
+
pageType?: string,
|
|
103
|
+
objectBindings?: Array<{
|
|
104
|
+
objectType: string,
|
|
105
|
+
accessMode: "read" | "write" | "read_write",
|
|
106
|
+
boundObjectIds?: string[],
|
|
107
|
+
syncEnabled: boolean,
|
|
108
|
+
syncDirection?: "push" | "pull" | "bidirectional"
|
|
109
|
+
}>
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Response** (201 Created / 200 Updated):
|
|
114
|
+
```typescript
|
|
115
|
+
{
|
|
116
|
+
success: true,
|
|
117
|
+
pageId: string,
|
|
118
|
+
created: boolean
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
### 3. Get Application Pages
|
|
125
|
+
|
|
126
|
+
**GET** `/api/v1/activity/pages?applicationId=<id>`
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
curl -X GET "https://your-deployment.convex.site/api/v1/activity/pages?applicationId=k1234567890abcdef" \
|
|
130
|
+
-H "Authorization: Bearer <cli_session_token>"
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Query Parameters**:
|
|
134
|
+
- `applicationId` (required): The connected application ID
|
|
135
|
+
- `status` (optional): Filter by status (e.g., "active", "archived")
|
|
136
|
+
|
|
137
|
+
**Response** (200 OK):
|
|
138
|
+
```typescript
|
|
139
|
+
{
|
|
140
|
+
success: true,
|
|
141
|
+
pages: Array<{
|
|
142
|
+
id: string,
|
|
143
|
+
name: string,
|
|
144
|
+
path: string,
|
|
145
|
+
detectionMethod: string,
|
|
146
|
+
pageType: string,
|
|
147
|
+
objectBindings: Array<{...}>,
|
|
148
|
+
status: string,
|
|
149
|
+
createdAt: number,
|
|
150
|
+
updatedAt: number
|
|
151
|
+
}>,
|
|
152
|
+
total: number
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### 4. Log Activity Events
|
|
159
|
+
|
|
160
|
+
**POST** `/api/v1/activity/events`
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
curl -X POST "https://your-deployment.convex.site/api/v1/activity/events" \
|
|
164
|
+
-H "Authorization: Bearer <cli_session_token>" \
|
|
165
|
+
-H "Content-Type: application/json" \
|
|
166
|
+
-d '{
|
|
167
|
+
"applicationId": "k1234567890abcdef",
|
|
168
|
+
"eventType": "object_created",
|
|
169
|
+
"severity": "info",
|
|
170
|
+
"category": "object",
|
|
171
|
+
"summary": "Contact '\''John Smith'\'' created",
|
|
172
|
+
"details": {
|
|
173
|
+
"objectType": "contact",
|
|
174
|
+
"objectName": "John Smith",
|
|
175
|
+
"durationMs": 125,
|
|
176
|
+
"correlationId": "req_abc123"
|
|
177
|
+
}
|
|
178
|
+
}'
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Request Body**:
|
|
182
|
+
```typescript
|
|
183
|
+
{
|
|
184
|
+
applicationId: string,
|
|
185
|
+
eventType: string, // "api_request", "object_created", "sync_started", etc.
|
|
186
|
+
severity: "debug" | "info" | "warning" | "error",
|
|
187
|
+
category: string, // "api", "sync", "object", "webhook", "transform"
|
|
188
|
+
summary: string, // Human-readable: "Contact 'John Smith' created"
|
|
189
|
+
pageId?: string, // Optional: link event to a specific page
|
|
190
|
+
details?: {
|
|
191
|
+
requestId?: string,
|
|
192
|
+
method?: string, // HTTP method
|
|
193
|
+
endpoint?: string, // API endpoint
|
|
194
|
+
statusCode?: number,
|
|
195
|
+
objectType?: string,
|
|
196
|
+
objectId?: string,
|
|
197
|
+
objectName?: string,
|
|
198
|
+
inputSummary?: string,
|
|
199
|
+
outputSummary?: string,
|
|
200
|
+
syncDirection?: string,
|
|
201
|
+
recordsAffected?: number,
|
|
202
|
+
durationMs?: number,
|
|
203
|
+
errorCode?: string,
|
|
204
|
+
errorMessage?: string,
|
|
205
|
+
stackTrace?: string,
|
|
206
|
+
sourceFile?: string,
|
|
207
|
+
sourceLine?: number,
|
|
208
|
+
correlationId?: string, // Group related events
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**Response** (201 Created):
|
|
214
|
+
```typescript
|
|
215
|
+
{
|
|
216
|
+
success: true,
|
|
217
|
+
eventId: string,
|
|
218
|
+
timestamp: number
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
### 5. Get Activity Events
|
|
225
|
+
|
|
226
|
+
**GET** `/api/v1/activity/events?applicationId=<id>`
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
curl -X GET "https://your-deployment.convex.site/api/v1/activity/events?applicationId=k1234567890abcdef&severity=error&limit=50" \
|
|
230
|
+
-H "Authorization: Bearer <cli_session_token>"
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Query Parameters**:
|
|
234
|
+
- `applicationId` (required): The connected application ID
|
|
235
|
+
- `severity` (optional): Filter by severity (debug, info, warning, error)
|
|
236
|
+
- `category` (optional): Filter by category (api, sync, object, webhook, transform)
|
|
237
|
+
- `debugMode` (optional): Include debug-level events (true/false)
|
|
238
|
+
- `limit` (optional): Max results, default 50, max 200
|
|
239
|
+
|
|
240
|
+
**Response** (200 OK):
|
|
241
|
+
```typescript
|
|
242
|
+
{
|
|
243
|
+
success: true,
|
|
244
|
+
events: Array<{
|
|
245
|
+
_id: string,
|
|
246
|
+
eventType: string,
|
|
247
|
+
severity: string,
|
|
248
|
+
category: string,
|
|
249
|
+
summary: string,
|
|
250
|
+
timestamp: number,
|
|
251
|
+
details?: {...}
|
|
252
|
+
}>,
|
|
253
|
+
hasMore: boolean,
|
|
254
|
+
nextCursor: string | null
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
### 6. Get Activity Statistics
|
|
261
|
+
|
|
262
|
+
**GET** `/api/v1/activity/stats?applicationId=<id>`
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
curl -X GET "https://your-deployment.convex.site/api/v1/activity/stats?applicationId=k1234567890abcdef&timeRange=24h" \
|
|
266
|
+
-H "Authorization: Bearer <cli_session_token>"
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**Query Parameters**:
|
|
270
|
+
- `applicationId` (required): The connected application ID
|
|
271
|
+
- `timeRange` (optional): "1h", "24h", or "7d" (default: "24h")
|
|
272
|
+
|
|
273
|
+
**Response** (200 OK):
|
|
274
|
+
```typescript
|
|
275
|
+
{
|
|
276
|
+
success: true,
|
|
277
|
+
stats: {
|
|
278
|
+
total: number,
|
|
279
|
+
bySeverity: { debug: number, info: number, warning: number, error: number },
|
|
280
|
+
byCategory: { [category: string]: number },
|
|
281
|
+
recentErrors: Array<{ summary: string, timestamp: number, errorMessage?: string }>
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
### 7. Activity Settings
|
|
289
|
+
|
|
290
|
+
**GET** `/api/v1/activity/settings?applicationId=<id>`
|
|
291
|
+
|
|
292
|
+
**PATCH** `/api/v1/activity/settings`
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
# Update settings
|
|
296
|
+
curl -X PATCH "https://your-deployment.convex.site/api/v1/activity/settings" \
|
|
297
|
+
-H "Authorization: Bearer <cli_session_token>" \
|
|
298
|
+
-H "Content-Type: application/json" \
|
|
299
|
+
-d '{
|
|
300
|
+
"applicationId": "k1234567890abcdef",
|
|
301
|
+
"enabled": true,
|
|
302
|
+
"debugModeDefault": false,
|
|
303
|
+
"retentionDays": 7,
|
|
304
|
+
"alertsEnabled": true
|
|
305
|
+
}'
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## CLI Implementation Requirements
|
|
311
|
+
|
|
312
|
+
### Phase 1: Page Detection
|
|
313
|
+
|
|
314
|
+
The CLI should scan the connected application and detect pages based on framework:
|
|
315
|
+
|
|
316
|
+
#### Next.js (App Router)
|
|
317
|
+
```
|
|
318
|
+
app/
|
|
319
|
+
├── page.tsx → "/"
|
|
320
|
+
├── about/
|
|
321
|
+
│ └── page.tsx → "/about"
|
|
322
|
+
├── dashboard/
|
|
323
|
+
│ ├── page.tsx → "/dashboard"
|
|
324
|
+
│ └── [id]/
|
|
325
|
+
│ └── page.tsx → "/dashboard/[id]"
|
|
326
|
+
└── api/
|
|
327
|
+
└── users/
|
|
328
|
+
└── route.ts → "/api/users" (api_route)
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
#### Next.js (Pages Router)
|
|
332
|
+
```
|
|
333
|
+
pages/
|
|
334
|
+
├── index.tsx → "/"
|
|
335
|
+
├── about.tsx → "/about"
|
|
336
|
+
├── dashboard/
|
|
337
|
+
│ ├── index.tsx → "/dashboard"
|
|
338
|
+
│ └── [id].tsx → "/dashboard/[id]"
|
|
339
|
+
└── api/
|
|
340
|
+
└── users.ts → "/api/users" (api_route)
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
#### Remix
|
|
344
|
+
```
|
|
345
|
+
app/routes/
|
|
346
|
+
├── _index.tsx → "/"
|
|
347
|
+
├── about.tsx → "/about"
|
|
348
|
+
├── dashboard._index.tsx → "/dashboard"
|
|
349
|
+
└── dashboard.$id.tsx → "/dashboard/$id"
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
#### Astro
|
|
353
|
+
```
|
|
354
|
+
src/pages/
|
|
355
|
+
├── index.astro → "/"
|
|
356
|
+
├── about.astro → "/about"
|
|
357
|
+
└── blog/
|
|
358
|
+
└── [slug].astro → "/blog/[slug]"
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Phase 2: Page Name Generation
|
|
362
|
+
|
|
363
|
+
Convert paths to human-readable names:
|
|
364
|
+
- `/` → "Home"
|
|
365
|
+
- `/about` → "About"
|
|
366
|
+
- `/dashboard` → "Dashboard"
|
|
367
|
+
- `/dashboard/[id]` → "Dashboard Detail"
|
|
368
|
+
- `/api/users` → "API: Users"
|
|
369
|
+
- `/checkout/[productId]` → "Checkout"
|
|
370
|
+
|
|
371
|
+
### Phase 3: Page Type Detection
|
|
372
|
+
|
|
373
|
+
- `page.tsx`, `index.tsx`, `.astro` → "static" or "dynamic"
|
|
374
|
+
- `route.ts`, `api/*.ts` → "api_route"
|
|
375
|
+
- Files with `[param]` → "dynamic"
|
|
376
|
+
|
|
377
|
+
### Phase 4: Sync Command
|
|
378
|
+
|
|
379
|
+
```bash
|
|
380
|
+
# Detect and sync pages
|
|
381
|
+
l4yercak3 pages sync
|
|
382
|
+
|
|
383
|
+
# Output:
|
|
384
|
+
# Scanning for pages...
|
|
385
|
+
# Found 12 pages in Next.js App Router
|
|
386
|
+
#
|
|
387
|
+
# Syncing to L4YERCAK3...
|
|
388
|
+
# ✓ / (Home) - created
|
|
389
|
+
# ✓ /about (About) - created
|
|
390
|
+
# ✓ /dashboard (Dashboard) - created
|
|
391
|
+
# ✓ /dashboard/[id] (Dashboard Detail) - created
|
|
392
|
+
# ✓ /api/users (API: Users) - created
|
|
393
|
+
# ...
|
|
394
|
+
#
|
|
395
|
+
# Done! 12 pages synced.
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Phase 5: Activity Logging (Optional Enhancement)
|
|
399
|
+
|
|
400
|
+
The CLI could generate code to automatically log activity events:
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
// Generated: lib/l4yercak3-activity.ts
|
|
404
|
+
const L4YERCAK3_API_URL = process.env.L4YERCAK3_API_URL;
|
|
405
|
+
const L4YERCAK3_API_KEY = process.env.L4YERCAK3_API_KEY;
|
|
406
|
+
const L4YERCAK3_APP_ID = process.env.L4YERCAK3_APPLICATION_ID;
|
|
407
|
+
|
|
408
|
+
export async function logActivity(context: {
|
|
409
|
+
eventType: string;
|
|
410
|
+
category: string;
|
|
411
|
+
summary: string;
|
|
412
|
+
severity?: 'debug' | 'info' | 'warning' | 'error';
|
|
413
|
+
details?: Record<string, unknown>;
|
|
414
|
+
}) {
|
|
415
|
+
try {
|
|
416
|
+
await fetch(`${L4YERCAK3_API_URL}/api/v1/activity/events`, {
|
|
417
|
+
method: 'POST',
|
|
418
|
+
headers: {
|
|
419
|
+
'Content-Type': 'application/json',
|
|
420
|
+
'X-API-Key': L4YERCAK3_API_KEY!,
|
|
421
|
+
},
|
|
422
|
+
body: JSON.stringify({
|
|
423
|
+
applicationId: L4YERCAK3_APP_ID,
|
|
424
|
+
eventType: context.eventType,
|
|
425
|
+
severity: context.severity || 'info',
|
|
426
|
+
category: context.category,
|
|
427
|
+
summary: context.summary,
|
|
428
|
+
details: context.details,
|
|
429
|
+
}),
|
|
430
|
+
});
|
|
431
|
+
} catch (error) {
|
|
432
|
+
// Fire-and-forget logging, don't block the application
|
|
433
|
+
console.error('[L4YERCAK3] Failed to log activity:', error);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
export async function withActivityLogging<T>(
|
|
438
|
+
operation: () => Promise<T>,
|
|
439
|
+
context: {
|
|
440
|
+
eventType: string;
|
|
441
|
+
category: string;
|
|
442
|
+
summary: string;
|
|
443
|
+
objectType?: string;
|
|
444
|
+
}
|
|
445
|
+
): Promise<T> {
|
|
446
|
+
const correlationId = crypto.randomUUID();
|
|
447
|
+
const startTime = Date.now();
|
|
448
|
+
|
|
449
|
+
try {
|
|
450
|
+
const result = await operation();
|
|
451
|
+
logActivity({
|
|
452
|
+
...context,
|
|
453
|
+
severity: 'info',
|
|
454
|
+
details: {
|
|
455
|
+
correlationId,
|
|
456
|
+
durationMs: Date.now() - startTime,
|
|
457
|
+
objectType: context.objectType,
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
return result;
|
|
461
|
+
} catch (error: unknown) {
|
|
462
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
463
|
+
logActivity({
|
|
464
|
+
...context,
|
|
465
|
+
severity: 'error',
|
|
466
|
+
details: {
|
|
467
|
+
correlationId,
|
|
468
|
+
durationMs: Date.now() - startTime,
|
|
469
|
+
errorMessage,
|
|
470
|
+
objectType: context.objectType,
|
|
471
|
+
}
|
|
472
|
+
});
|
|
473
|
+
throw error;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
## Data Flow
|
|
479
|
+
|
|
480
|
+
```
|
|
481
|
+
┌─────────────────┐ ┌──────────────────────────────┐ ┌─────────────────┐
|
|
482
|
+
│ CLI Tool │────▶│ HTTP API Endpoints │────▶│ Objects DB │
|
|
483
|
+
│ │ │ │ │ │
|
|
484
|
+
│ • Scan pages │ │ POST /api/v1/activity/pages/bulk │ type= │
|
|
485
|
+
│ • Detect types │ │ POST /api/v1/activity/pages │ │ application_page│
|
|
486
|
+
│ • Generate names│ │ POST /api/v1/activity/events │ │ │
|
|
487
|
+
└─────────────────┘ └──────────────────────────────┘ └─────────────────┘
|
|
488
|
+
│
|
|
489
|
+
▼
|
|
490
|
+
┌──────────────────┐
|
|
491
|
+
│ Activity Events │
|
|
492
|
+
│ (Rolling Window)│
|
|
493
|
+
│ 7-day default │
|
|
494
|
+
└──────────────────┘
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
## Testing
|
|
498
|
+
|
|
499
|
+
1. Create a test Next.js app with various page structures
|
|
500
|
+
2. Run `l4yercak3 pages sync`
|
|
501
|
+
3. Verify pages appear in L4YERCAK3 Web Publishing → Applications → [App] → Pages & Bindings
|
|
502
|
+
4. Test that updates (re-running sync) update existing pages rather than creating duplicates
|
|
503
|
+
|
|
504
|
+
## Open Questions for CLI Team
|
|
505
|
+
|
|
506
|
+
1. **Incremental vs Full Sync**: Should we detect deleted pages and mark them as archived?
|
|
507
|
+
2. **Watch Mode**: Should we support `l4yercak3 pages watch` for real-time detection?
|
|
508
|
+
3. **Config File**: Should page detection be configurable via `.l4yercak3/pages.json`?
|
|
509
|
+
4. **Exclusions**: How do we handle pages that shouldn't be tracked (e.g., internal admin routes)?
|
|
510
|
+
|
|
511
|
+
## Error Codes
|
|
512
|
+
|
|
513
|
+
| Code | Description |
|
|
514
|
+
|------|-------------|
|
|
515
|
+
| `INVALID_SESSION` | Authentication failed - token expired or invalid |
|
|
516
|
+
| `INSUFFICIENT_PERMISSIONS` | Missing required scope |
|
|
517
|
+
| `VALIDATION_ERROR` | Missing or invalid request parameters |
|
|
518
|
+
| `NOT_FOUND` | Resource not found |
|
|
519
|
+
| `INTERNAL_ERROR` | Server error |
|