@l4yercak3/cli 1.0.5 → 1.1.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 +6 -0
- package/docs/microsass_production_machine/CLI_API_REFERENCE.md +1197 -0
- package/docs/microsass_production_machine/CLI_PRODUCT_VISION.md +676 -0
- package/docs/microsass_production_machine/CLI_REQUIREMENTS.md +606 -0
- package/docs/microsass_production_machine/CONNECTED_APPLICATIONS_SPEC.md +390 -0
- package/docs/microsass_production_machine/IMPLEMENTATION_ROADMAP.md +725 -0
- package/docs/microsass_production_machine/OBJECT_MAPPINGS.md +808 -0
- package/docs/microsass_production_machine/REFERENCE_IMPLEMENTATION.md +532 -0
- package/package.json +1 -1
- package/src/api/backend-client.js +62 -0
- package/src/commands/spread.js +128 -11
- package/src/generators/api-client-generator.js +13 -6
- package/src/generators/env-generator.js +14 -1
- package/src/generators/index.js +4 -4
- package/src/generators/nextauth-generator.js +14 -9
- package/src/utils/file-utils.js +117 -0
- package/tests/api-client-generator.test.js +20 -13
- package/tests/backend-client.test.js +167 -0
- package/tests/file-utils.test.js +194 -0
- package/tests/generators-index.test.js +8 -0
- package/tests/nextauth-generator.test.js +38 -14
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
# Connected Applications - Schema Specification
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The `connected_application` object type represents an external application connected to L4YERCAK3 via CLI or boilerplate deployment. It's the **parent container** that ties together API connections, model mappings, deployments, and published pages.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Object Type: `connected_application`
|
|
10
|
+
|
|
11
|
+
### Base Structure (in `objects` table)
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
{
|
|
15
|
+
_id: Id<"objects">,
|
|
16
|
+
organizationId: Id<"organizations">,
|
|
17
|
+
type: "connected_application",
|
|
18
|
+
subtype: "cli" | "boilerplate" | "manual",
|
|
19
|
+
name: string, // "HaffNet Medical Platform"
|
|
20
|
+
description: string, // "CME course registration platform"
|
|
21
|
+
status: "active" | "paused" | "disconnected" | "archived",
|
|
22
|
+
customProperties: ConnectedApplicationProperties,
|
|
23
|
+
createdBy: Id<"users">,
|
|
24
|
+
createdAt: number,
|
|
25
|
+
updatedAt: number,
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Custom Properties
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
interface ConnectedApplicationProperties {
|
|
33
|
+
// ========================================
|
|
34
|
+
// SOURCE: Where the app comes from
|
|
35
|
+
// ========================================
|
|
36
|
+
source: {
|
|
37
|
+
type: "cli" | "boilerplate" | "manual";
|
|
38
|
+
|
|
39
|
+
// CLI-specific
|
|
40
|
+
projectPathHash?: string; // SHA256 of local project path (for identification)
|
|
41
|
+
cliVersion?: string; // CLI version that registered this app
|
|
42
|
+
|
|
43
|
+
// Boilerplate-specific
|
|
44
|
+
boilerplateId?: string; // "freelancer-portal", "event-landing", etc.
|
|
45
|
+
boilerplateVersion?: string; // Version of boilerplate used
|
|
46
|
+
|
|
47
|
+
// Framework detection
|
|
48
|
+
framework: string; // "nextjs", "remix", "astro", etc.
|
|
49
|
+
frameworkVersion?: string; // "16.0.0"
|
|
50
|
+
hasTypeScript: boolean;
|
|
51
|
+
routerType?: "app" | "pages"; // For Next.js
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// ========================================
|
|
55
|
+
// CONNECTION: How app talks to L4YERCAK3
|
|
56
|
+
// ========================================
|
|
57
|
+
connection: {
|
|
58
|
+
apiKeyId?: Id<"apiKeys">; // Reference to API key used
|
|
59
|
+
apiKeyPrefix?: string; // "sk_live_xxx..." for display
|
|
60
|
+
backendUrl: string; // "https://app.l4yercak3.com"
|
|
61
|
+
|
|
62
|
+
// Features enabled for this app
|
|
63
|
+
features: Array<
|
|
64
|
+
| "crm"
|
|
65
|
+
| "events"
|
|
66
|
+
| "products"
|
|
67
|
+
| "checkout"
|
|
68
|
+
| "tickets"
|
|
69
|
+
| "invoicing"
|
|
70
|
+
| "forms"
|
|
71
|
+
| "projects"
|
|
72
|
+
| "workflows"
|
|
73
|
+
| "templates"
|
|
74
|
+
| "ai"
|
|
75
|
+
>;
|
|
76
|
+
|
|
77
|
+
// Dual-database pattern (like HaffNet)
|
|
78
|
+
hasFrontendDatabase: boolean;
|
|
79
|
+
frontendDatabaseType?: "convex" | "prisma" | "drizzle" | "other";
|
|
80
|
+
frontendDatabaseUrl?: string; // For reference only, not stored
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// ========================================
|
|
84
|
+
// MODEL MAPPINGS: How app models map to L4YERCAK3
|
|
85
|
+
// ========================================
|
|
86
|
+
modelMappings: Array<{
|
|
87
|
+
localModel: string; // "User", "Company", "Event"
|
|
88
|
+
layerCakeType: string; // "contact", "crm_organization", "event"
|
|
89
|
+
syncDirection: "push" | "pull" | "bidirectional" | "none";
|
|
90
|
+
confidence: number; // 0-100, from CLI detection
|
|
91
|
+
isAutoDetected: boolean; // true if CLI detected, false if manual
|
|
92
|
+
fieldMappings: Array<{
|
|
93
|
+
localField: string; // "email", "firstName"
|
|
94
|
+
layerCakeField: string; // "email", "customProperties.firstName"
|
|
95
|
+
transform?: string; // Optional transform expression
|
|
96
|
+
}>;
|
|
97
|
+
}>;
|
|
98
|
+
|
|
99
|
+
// ========================================
|
|
100
|
+
// DEPLOYMENT: Where app is deployed
|
|
101
|
+
// ========================================
|
|
102
|
+
deployment: {
|
|
103
|
+
// Links to deployment system (Phase 1-2 work)
|
|
104
|
+
configurationId?: Id<"objects">; // deployment_configuration object
|
|
105
|
+
|
|
106
|
+
// Quick access URLs
|
|
107
|
+
productionUrl?: string; // "https://haffnet.vercel.app"
|
|
108
|
+
stagingUrl?: string; // "https://staging.haffnet.vercel.app"
|
|
109
|
+
localDevUrl?: string; // "http://localhost:3000"
|
|
110
|
+
|
|
111
|
+
// GitHub repo
|
|
112
|
+
githubRepo?: string; // "owner/repo"
|
|
113
|
+
githubBranch?: string; // "main"
|
|
114
|
+
|
|
115
|
+
// Deployment status
|
|
116
|
+
deploymentStatus: "not_deployed" | "deploying" | "deployed" | "failed";
|
|
117
|
+
lastDeployedAt?: number;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// ========================================
|
|
121
|
+
// PAGES: Published pages owned by this app
|
|
122
|
+
// ========================================
|
|
123
|
+
pageIds: Array<Id<"objects">>; // References to published_page objects
|
|
124
|
+
|
|
125
|
+
// ========================================
|
|
126
|
+
// SYNC STATUS: Data synchronization state
|
|
127
|
+
// ========================================
|
|
128
|
+
sync: {
|
|
129
|
+
enabled: boolean;
|
|
130
|
+
lastSyncAt?: number;
|
|
131
|
+
lastSyncDirection?: "push" | "pull" | "bidirectional";
|
|
132
|
+
lastSyncStatus?: "success" | "partial" | "failed";
|
|
133
|
+
|
|
134
|
+
// Per-model sync stats
|
|
135
|
+
stats: Record<string, { // Keyed by layerCakeType
|
|
136
|
+
totalRecords: number;
|
|
137
|
+
syncedRecords: number;
|
|
138
|
+
lastSyncAt: number;
|
|
139
|
+
errors: number;
|
|
140
|
+
lastError?: string;
|
|
141
|
+
}>;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// ========================================
|
|
145
|
+
// CLI METADATA
|
|
146
|
+
// ========================================
|
|
147
|
+
cli: {
|
|
148
|
+
registeredAt: number; // When CLI first registered this app
|
|
149
|
+
registeredBy?: Id<"users">; // User who ran CLI
|
|
150
|
+
lastActivityAt: number; // Last CLI command for this app
|
|
151
|
+
cliSessionId?: string; // Current/last CLI session
|
|
152
|
+
|
|
153
|
+
// Generated files tracking
|
|
154
|
+
generatedFiles: Array<{
|
|
155
|
+
path: string; // "src/lib/layercake.ts"
|
|
156
|
+
type: string; // "api-client", "types", "env"
|
|
157
|
+
generatedAt: number;
|
|
158
|
+
hash?: string; // For change detection
|
|
159
|
+
}>;
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Object Links
|
|
167
|
+
|
|
168
|
+
### Application → API Key
|
|
169
|
+
```typescript
|
|
170
|
+
{
|
|
171
|
+
fromObjectId: applicationId,
|
|
172
|
+
toObjectId: apiKeyId, // In apiKeys table, not objects
|
|
173
|
+
linkType: "uses_api_key",
|
|
174
|
+
organizationId,
|
|
175
|
+
properties: {
|
|
176
|
+
linkedAt: number,
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Application → Published Pages
|
|
182
|
+
```typescript
|
|
183
|
+
{
|
|
184
|
+
fromObjectId: applicationId,
|
|
185
|
+
toObjectId: publishedPageId,
|
|
186
|
+
linkType: "owns_page",
|
|
187
|
+
organizationId,
|
|
188
|
+
properties: {
|
|
189
|
+
addedAt: number,
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Application → Deployment Configuration
|
|
195
|
+
```typescript
|
|
196
|
+
{
|
|
197
|
+
fromObjectId: applicationId,
|
|
198
|
+
toObjectId: deploymentConfigId,
|
|
199
|
+
linkType: "deploys_via",
|
|
200
|
+
organizationId,
|
|
201
|
+
properties: {
|
|
202
|
+
environment: "production" | "staging",
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Convex Functions Required
|
|
210
|
+
|
|
211
|
+
### Mutations
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
// Register new application (called by CLI)
|
|
215
|
+
registerConnectedApplication(args: {
|
|
216
|
+
token: string, // CLI session token
|
|
217
|
+
organizationId: Id<"organizations">,
|
|
218
|
+
name: string,
|
|
219
|
+
source: SourceConfig,
|
|
220
|
+
connection: ConnectionConfig,
|
|
221
|
+
modelMappings?: ModelMapping[],
|
|
222
|
+
deployment?: DeploymentConfig,
|
|
223
|
+
}): Promise<{
|
|
224
|
+
applicationId: Id<"objects">,
|
|
225
|
+
apiKeyId?: Id<"apiKeys">, // If new key was generated
|
|
226
|
+
}>
|
|
227
|
+
|
|
228
|
+
// Update application (called by CLI on re-run)
|
|
229
|
+
updateConnectedApplication(args: {
|
|
230
|
+
token: string,
|
|
231
|
+
applicationId: Id<"objects">,
|
|
232
|
+
updates: Partial<ConnectedApplicationProperties>,
|
|
233
|
+
}): Promise<void>
|
|
234
|
+
|
|
235
|
+
// Update sync status (called after sync operations)
|
|
236
|
+
updateApplicationSyncStatus(args: {
|
|
237
|
+
token: string,
|
|
238
|
+
applicationId: Id<"objects">,
|
|
239
|
+
syncResult: SyncResult,
|
|
240
|
+
}): Promise<void>
|
|
241
|
+
|
|
242
|
+
// Pause/resume application
|
|
243
|
+
setApplicationStatus(args: {
|
|
244
|
+
sessionId: string,
|
|
245
|
+
applicationId: Id<"objects">,
|
|
246
|
+
status: "active" | "paused",
|
|
247
|
+
}): Promise<void>
|
|
248
|
+
|
|
249
|
+
// Disconnect application (soft delete)
|
|
250
|
+
disconnectApplication(args: {
|
|
251
|
+
sessionId: string,
|
|
252
|
+
applicationId: Id<"objects">,
|
|
253
|
+
}): Promise<void>
|
|
254
|
+
|
|
255
|
+
// Link page to application
|
|
256
|
+
linkPageToApplication(args: {
|
|
257
|
+
sessionId: string,
|
|
258
|
+
applicationId: Id<"objects">,
|
|
259
|
+
pageId: Id<"objects">,
|
|
260
|
+
}): Promise<void>
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Queries
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
// List all applications for org (for Web Publishing UI)
|
|
267
|
+
getConnectedApplications(args: {
|
|
268
|
+
sessionId: string,
|
|
269
|
+
organizationId: Id<"organizations">,
|
|
270
|
+
status?: string,
|
|
271
|
+
}): Promise<ConnectedApplication[]>
|
|
272
|
+
|
|
273
|
+
// Get single application with full details
|
|
274
|
+
getConnectedApplication(args: {
|
|
275
|
+
sessionId: string,
|
|
276
|
+
applicationId: Id<"objects">,
|
|
277
|
+
}): Promise<ConnectedApplication | null>
|
|
278
|
+
|
|
279
|
+
// Get application by project path hash (for CLI to find existing)
|
|
280
|
+
getApplicationByPathHash(args: {
|
|
281
|
+
token: string,
|
|
282
|
+
organizationId: Id<"organizations">,
|
|
283
|
+
projectPathHash: string,
|
|
284
|
+
}): Promise<ConnectedApplication | null>
|
|
285
|
+
|
|
286
|
+
// Get applications using specific API key
|
|
287
|
+
getApplicationsByApiKey(args: {
|
|
288
|
+
sessionId: string,
|
|
289
|
+
apiKeyId: Id<"apiKeys">,
|
|
290
|
+
}): Promise<ConnectedApplication[]>
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## REST API Endpoints
|
|
296
|
+
|
|
297
|
+
### For CLI
|
|
298
|
+
|
|
299
|
+
```
|
|
300
|
+
POST /api/v1/cli/applications - Register application
|
|
301
|
+
GET /api/v1/cli/applications - List applications
|
|
302
|
+
GET /api/v1/cli/applications/:id - Get application
|
|
303
|
+
PATCH /api/v1/cli/applications/:id - Update application
|
|
304
|
+
DELETE /api/v1/cli/applications/:id - Disconnect application
|
|
305
|
+
POST /api/v1/cli/applications/:id/sync - Trigger/report sync
|
|
306
|
+
GET /api/v1/cli/applications/by-path - Find by project path hash
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Authentication
|
|
310
|
+
|
|
311
|
+
All CLI endpoints use Bearer token authentication:
|
|
312
|
+
```
|
|
313
|
+
Authorization: Bearer cli_session_xxx
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Web Publishing UI Changes
|
|
319
|
+
|
|
320
|
+
### New "Applications" Tab
|
|
321
|
+
|
|
322
|
+
Position: First tab (before Pages)
|
|
323
|
+
|
|
324
|
+
**Content:**
|
|
325
|
+
- List of connected applications with:
|
|
326
|
+
- Name & framework icon
|
|
327
|
+
- Status badge (active/paused/disconnected)
|
|
328
|
+
- Features enabled (icons)
|
|
329
|
+
- Last sync time
|
|
330
|
+
- Production URL (if deployed)
|
|
331
|
+
- Quick actions: View, Pause, Settings, Disconnect
|
|
332
|
+
|
|
333
|
+
**Empty State:**
|
|
334
|
+
- "No applications connected"
|
|
335
|
+
- "Use the L4YERCAK3 CLI to connect an external app, or deploy a boilerplate"
|
|
336
|
+
- Buttons: "CLI Documentation", "Deploy Boilerplate"
|
|
337
|
+
|
|
338
|
+
### Application Detail View
|
|
339
|
+
|
|
340
|
+
When clicking an application:
|
|
341
|
+
- **Overview Tab**: Status, URLs, features, last activity
|
|
342
|
+
- **Model Mappings Tab**: Visual mapping table
|
|
343
|
+
- **Sync Tab**: Sync status, stats, manual sync button
|
|
344
|
+
- **Pages Tab**: Published pages owned by this app
|
|
345
|
+
- **Settings Tab**: Edit name, features, deployment config
|
|
346
|
+
- **Logs Tab**: Recent CLI activity, sync history
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Integration with Existing Systems
|
|
351
|
+
|
|
352
|
+
### With API Keys (`apiKeys` table)
|
|
353
|
+
- Application references API key via `connection.apiKeyId`
|
|
354
|
+
- Can query "which apps use this key"
|
|
355
|
+
- Revoking key should warn about connected apps
|
|
356
|
+
|
|
357
|
+
### With Published Pages (`published_page` objects)
|
|
358
|
+
- Pages can belong to an application via `pageIds` array
|
|
359
|
+
- Page detail shows parent application (if any)
|
|
360
|
+
- Deleting app can optionally delete pages
|
|
361
|
+
|
|
362
|
+
### With Deployment System (`deployment_configuration` objects)
|
|
363
|
+
- Application links to deployment config
|
|
364
|
+
- Shares GitHub/Vercel settings
|
|
365
|
+
- Deployment status synced
|
|
366
|
+
|
|
367
|
+
### With CLI Sessions (`cliSessions` table)
|
|
368
|
+
- Application tracks which CLI session registered it
|
|
369
|
+
- Last activity updates on CLI commands
|
|
370
|
+
- Session expiry doesn't disconnect app
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Migration Strategy
|
|
375
|
+
|
|
376
|
+
1. **No existing data to migrate** - This is a new object type
|
|
377
|
+
2. **Backward compatible** - Existing pages/deployments continue to work
|
|
378
|
+
3. **Optional adoption** - Apps without CLI still function
|
|
379
|
+
4. **Gradual rollout** - UI can show "Applications" tab only when apps exist
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
## Success Criteria
|
|
384
|
+
|
|
385
|
+
- [ ] CLI can register application and see it in Web Publishing
|
|
386
|
+
- [ ] Web Publishing shows all connected applications
|
|
387
|
+
- [ ] Model mappings visible and editable
|
|
388
|
+
- [ ] Sync status accurately reflects last CLI sync
|
|
389
|
+
- [ ] Disconnecting app doesn't break existing pages
|
|
390
|
+
- [ ] API key relationship bidirectional (key → apps, app → key)
|