@l4yercak3/cli 1.2.16 → 1.2.19
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/.claude/settings.local.json +3 -1
- package/docs/CRM-PIPELINES-SEQUENCES-SPEC.md +429 -0
- package/docs/INTEGRATION_PATHS_ARCHITECTURE.md +1543 -0
- package/package.json +1 -1
- package/src/commands/login.js +26 -7
- package/src/commands/spread.js +251 -10
- package/src/detectors/database-detector.js +245 -0
- package/src/detectors/expo-detector.js +4 -4
- package/src/detectors/index.js +17 -4
- package/src/generators/api-only/client.js +683 -0
- package/src/generators/api-only/index.js +96 -0
- package/src/generators/api-only/types.js +618 -0
- package/src/generators/api-only/webhooks.js +377 -0
- package/src/generators/env-generator.js +23 -8
- package/src/generators/expo-auth-generator.js +1009 -0
- package/src/generators/index.js +88 -2
- package/src/generators/mcp-guide-generator.js +256 -0
- package/src/generators/quickstart/components/index.js +1699 -0
- package/src/generators/quickstart/components-mobile/index.js +1440 -0
- package/src/generators/quickstart/database/convex.js +1257 -0
- package/src/generators/quickstart/database/index.js +34 -0
- package/src/generators/quickstart/database/supabase.js +1132 -0
- package/src/generators/quickstart/hooks/index.js +1065 -0
- package/src/generators/quickstart/index.js +177 -0
- package/src/generators/quickstart/pages/index.js +1466 -0
- package/src/generators/quickstart/screens/index.js +1498 -0
- package/src/mcp/registry/domains/benefits.js +798 -0
- package/src/mcp/registry/index.js +2 -0
- package/tests/database-detector.test.js +221 -0
- package/tests/expo-detector.test.js +3 -4
- package/tests/generators-index.test.js +215 -3
|
@@ -0,0 +1,683 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed API Client Generator
|
|
3
|
+
* Generates a fully-typed API client for L4YERCAK3
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const { ensureDir, writeFileWithBackup, checkFileOverwrite } = require('../../utils/file-utils');
|
|
9
|
+
|
|
10
|
+
class ClientGenerator {
|
|
11
|
+
/**
|
|
12
|
+
* Generate the typed API client
|
|
13
|
+
* @param {Object} options - Generation options
|
|
14
|
+
* @returns {Promise<string|null>} - Path to generated file or null if skipped
|
|
15
|
+
*/
|
|
16
|
+
async generate(options) {
|
|
17
|
+
const { projectPath, isTypeScript, organizationId, backendUrl } = options;
|
|
18
|
+
|
|
19
|
+
// Determine output directory
|
|
20
|
+
let outputDir;
|
|
21
|
+
if (fs.existsSync(path.join(projectPath, 'src'))) {
|
|
22
|
+
outputDir = path.join(projectPath, 'src', 'lib', 'l4yercak3');
|
|
23
|
+
} else {
|
|
24
|
+
outputDir = path.join(projectPath, 'lib', 'l4yercak3');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
ensureDir(outputDir);
|
|
28
|
+
|
|
29
|
+
const extension = isTypeScript ? 'ts' : 'js';
|
|
30
|
+
const outputPath = path.join(outputDir, `client.${extension}`);
|
|
31
|
+
|
|
32
|
+
const action = await checkFileOverwrite(outputPath);
|
|
33
|
+
if (action === 'skip') {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const content = isTypeScript
|
|
38
|
+
? this.generateTypeScriptClient({ organizationId, backendUrl })
|
|
39
|
+
: this.generateJavaScriptClient({ organizationId, backendUrl });
|
|
40
|
+
|
|
41
|
+
return writeFileWithBackup(outputPath, content, action);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
generateTypeScriptClient({ organizationId, backendUrl }) {
|
|
45
|
+
return `/**
|
|
46
|
+
* L4YERCAK3 API Client
|
|
47
|
+
* Auto-generated by @l4yercak3/cli
|
|
48
|
+
*
|
|
49
|
+
* A fully-typed API client for the L4YERCAK3 platform.
|
|
50
|
+
* Organization ID: ${organizationId}
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
import type {
|
|
54
|
+
Contact, ContactCreateInput, ContactUpdateInput,
|
|
55
|
+
Organization, OrganizationCreateInput,
|
|
56
|
+
Event, EventCreateInput,
|
|
57
|
+
Attendee,
|
|
58
|
+
Form, FormSubmission,
|
|
59
|
+
Product, Order, OrderItem,
|
|
60
|
+
Invoice, InvoiceCreateInput,
|
|
61
|
+
BenefitClaim, BenefitClaimInput,
|
|
62
|
+
CommissionPayout,
|
|
63
|
+
PaginatedResponse,
|
|
64
|
+
} from './types';
|
|
65
|
+
|
|
66
|
+
export class L4yercak3Client {
|
|
67
|
+
private apiKey: string;
|
|
68
|
+
private baseUrl: string;
|
|
69
|
+
private organizationId: string;
|
|
70
|
+
|
|
71
|
+
constructor(config: { apiKey: string; baseUrl?: string; organizationId?: string }) {
|
|
72
|
+
this.apiKey = config.apiKey;
|
|
73
|
+
this.baseUrl = config.baseUrl || '${backendUrl}';
|
|
74
|
+
this.organizationId = config.organizationId || '${organizationId}';
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ============ CRM: Contacts ============
|
|
78
|
+
|
|
79
|
+
async listContacts(params?: {
|
|
80
|
+
limit?: number;
|
|
81
|
+
offset?: number;
|
|
82
|
+
status?: 'active' | 'inactive' | 'archived';
|
|
83
|
+
subtype?: 'customer' | 'lead' | 'prospect' | 'partner';
|
|
84
|
+
search?: string;
|
|
85
|
+
tags?: string[];
|
|
86
|
+
}): Promise<PaginatedResponse<Contact>> {
|
|
87
|
+
return this.request('GET', '/api/v1/crm/contacts', { params });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async getContact(id: string, options?: {
|
|
91
|
+
includeActivities?: boolean;
|
|
92
|
+
includeNotes?: boolean;
|
|
93
|
+
includeOrganization?: boolean;
|
|
94
|
+
}): Promise<Contact> {
|
|
95
|
+
return this.request('GET', \`/api/v1/crm/contacts/\${id}\`, { params: options });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async createContact(data: ContactCreateInput): Promise<Contact> {
|
|
99
|
+
return this.request('POST', '/api/v1/crm/contacts', { body: data });
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async updateContact(id: string, data: ContactUpdateInput): Promise<Contact> {
|
|
103
|
+
return this.request('PATCH', \`/api/v1/crm/contacts/\${id}\`, { body: data });
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async deleteContact(id: string): Promise<void> {
|
|
107
|
+
return this.request('DELETE', \`/api/v1/crm/contacts/\${id}\`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async addTagsToContact(id: string, tags: string[]): Promise<Contact> {
|
|
111
|
+
return this.request('POST', \`/api/v1/crm/contacts/\${id}/tags\`, { body: { tags } });
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async removeTagsFromContact(id: string, tags: string[]): Promise<Contact> {
|
|
115
|
+
return this.request('DELETE', \`/api/v1/crm/contacts/\${id}/tags\`, { body: { tags } });
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ============ CRM: Organizations ============
|
|
119
|
+
|
|
120
|
+
async listOrganizations(params?: {
|
|
121
|
+
limit?: number;
|
|
122
|
+
offset?: number;
|
|
123
|
+
subtype?: 'customer' | 'prospect' | 'partner' | 'vendor';
|
|
124
|
+
search?: string;
|
|
125
|
+
}): Promise<PaginatedResponse<Organization>> {
|
|
126
|
+
return this.request('GET', '/api/v1/crm/organizations', { params });
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async getOrganization(id: string, options?: {
|
|
130
|
+
includeContacts?: boolean;
|
|
131
|
+
}): Promise<Organization> {
|
|
132
|
+
return this.request('GET', \`/api/v1/crm/organizations/\${id}\`, { params: options });
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async createOrganization(data: OrganizationCreateInput): Promise<Organization> {
|
|
136
|
+
return this.request('POST', '/api/v1/crm/organizations', { body: data });
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ============ Events ============
|
|
140
|
+
|
|
141
|
+
async listEvents(params?: {
|
|
142
|
+
status?: 'draft' | 'published' | 'cancelled' | 'completed';
|
|
143
|
+
fromDate?: string;
|
|
144
|
+
toDate?: string;
|
|
145
|
+
limit?: number;
|
|
146
|
+
offset?: number;
|
|
147
|
+
}): Promise<PaginatedResponse<Event>> {
|
|
148
|
+
return this.request('GET', '/api/v1/events', { params });
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async getEvent(id: string, options?: {
|
|
152
|
+
includeProducts?: boolean;
|
|
153
|
+
includeSponsors?: boolean;
|
|
154
|
+
includeForms?: boolean;
|
|
155
|
+
}): Promise<Event> {
|
|
156
|
+
return this.request('GET', \`/api/v1/events/\${id}\`, { params: options });
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async createEvent(data: EventCreateInput): Promise<Event> {
|
|
160
|
+
return this.request('POST', '/api/v1/events', { body: data });
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
async updateEvent(id: string, data: Partial<EventCreateInput>): Promise<Event> {
|
|
164
|
+
return this.request('PATCH', \`/api/v1/events/\${id}\`, { body: data });
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async getEventAttendees(eventId: string, params?: {
|
|
168
|
+
status?: 'registered' | 'checked_in' | 'cancelled' | 'no_show';
|
|
169
|
+
limit?: number;
|
|
170
|
+
offset?: number;
|
|
171
|
+
}): Promise<PaginatedResponse<Attendee>> {
|
|
172
|
+
return this.request('GET', \`/api/v1/events/\${eventId}/attendees\`, { params });
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async checkInAttendee(eventId: string, attendeeId: string): Promise<Attendee> {
|
|
176
|
+
return this.request('POST', \`/api/v1/events/\${eventId}/attendees/\${attendeeId}/check-in\`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// ============ Forms ============
|
|
180
|
+
|
|
181
|
+
async listForms(params?: {
|
|
182
|
+
status?: 'draft' | 'published' | 'closed';
|
|
183
|
+
eventId?: string;
|
|
184
|
+
subtype?: 'registration' | 'survey' | 'application' | 'feedback' | 'contact';
|
|
185
|
+
limit?: number;
|
|
186
|
+
}): Promise<PaginatedResponse<Form>> {
|
|
187
|
+
return this.request('GET', '/api/v1/forms', { params });
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async getForm(id: string): Promise<Form> {
|
|
191
|
+
return this.request('GET', \`/api/v1/forms/\${id}\`);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async submitForm(formId: string, data: Record<string, unknown>): Promise<FormSubmission> {
|
|
195
|
+
return this.request('POST', \`/api/v1/forms/\${formId}/submit\`, { body: data });
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async getFormResponses(formId: string, params?: {
|
|
199
|
+
status?: 'submitted' | 'reviewed' | 'approved' | 'rejected';
|
|
200
|
+
limit?: number;
|
|
201
|
+
offset?: number;
|
|
202
|
+
}): Promise<PaginatedResponse<FormSubmission>> {
|
|
203
|
+
return this.request('GET', \`/api/v1/forms/\${formId}/responses\`, { params });
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ============ Products ============
|
|
207
|
+
|
|
208
|
+
async listProducts(params?: {
|
|
209
|
+
eventId?: string;
|
|
210
|
+
status?: 'active' | 'sold_out' | 'hidden';
|
|
211
|
+
category?: string;
|
|
212
|
+
limit?: number;
|
|
213
|
+
}): Promise<PaginatedResponse<Product>> {
|
|
214
|
+
return this.request('GET', '/api/v1/products', { params });
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async getProduct(id: string): Promise<Product> {
|
|
218
|
+
return this.request('GET', \`/api/v1/products/\${id}\`);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ============ Checkout ============
|
|
222
|
+
|
|
223
|
+
async createCheckoutSession(data: {
|
|
224
|
+
items: Array<{ productId: string; quantity: number }>;
|
|
225
|
+
contactId?: string;
|
|
226
|
+
email?: string;
|
|
227
|
+
successUrl: string;
|
|
228
|
+
cancelUrl: string;
|
|
229
|
+
metadata?: Record<string, string>;
|
|
230
|
+
}): Promise<{ sessionId: string; checkoutUrl: string }> {
|
|
231
|
+
return this.request('POST', '/api/v1/checkout/sessions', { body: data });
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
async getCheckoutSession(sessionId: string): Promise<{
|
|
235
|
+
sessionId: string;
|
|
236
|
+
status: 'open' | 'complete' | 'expired';
|
|
237
|
+
order?: Order;
|
|
238
|
+
}> {
|
|
239
|
+
return this.request('GET', \`/api/v1/checkout/sessions/\${sessionId}\`);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ============ Orders ============
|
|
243
|
+
|
|
244
|
+
async listOrders(params?: {
|
|
245
|
+
contactId?: string;
|
|
246
|
+
status?: 'pending' | 'paid' | 'refunded' | 'cancelled';
|
|
247
|
+
fromDate?: string;
|
|
248
|
+
toDate?: string;
|
|
249
|
+
limit?: number;
|
|
250
|
+
}): Promise<PaginatedResponse<Order>> {
|
|
251
|
+
return this.request('GET', '/api/v1/orders', { params });
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async getOrder(id: string): Promise<Order> {
|
|
255
|
+
return this.request('GET', \`/api/v1/orders/\${id}\`);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// ============ Invoicing ============
|
|
259
|
+
|
|
260
|
+
async listInvoices(params?: {
|
|
261
|
+
contactId?: string;
|
|
262
|
+
organizationId?: string;
|
|
263
|
+
status?: 'draft' | 'sent' | 'paid' | 'overdue' | 'cancelled';
|
|
264
|
+
type?: 'b2b' | 'b2c';
|
|
265
|
+
limit?: number;
|
|
266
|
+
}): Promise<PaginatedResponse<Invoice>> {
|
|
267
|
+
return this.request('GET', '/api/v1/invoices', { params });
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
async getInvoice(id: string): Promise<Invoice> {
|
|
271
|
+
return this.request('GET', \`/api/v1/invoices/\${id}\`);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async createInvoice(data: InvoiceCreateInput): Promise<Invoice> {
|
|
275
|
+
return this.request('POST', '/api/v1/invoices', { body: data });
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
async sendInvoice(id: string, options?: {
|
|
279
|
+
emailTo?: string;
|
|
280
|
+
message?: string;
|
|
281
|
+
}): Promise<void> {
|
|
282
|
+
return this.request('POST', \`/api/v1/invoices/\${id}/send\`, { body: options });
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
async markInvoicePaid(id: string, data?: {
|
|
286
|
+
paidAt?: string;
|
|
287
|
+
paymentMethod?: string;
|
|
288
|
+
paymentReference?: string;
|
|
289
|
+
}): Promise<Invoice> {
|
|
290
|
+
return this.request('POST', \`/api/v1/invoices/\${id}/mark-paid\`, { body: data });
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
async getInvoicePdf(id: string): Promise<{ pdfUrl: string }> {
|
|
294
|
+
return this.request('GET', \`/api/v1/invoices/\${id}/pdf\`);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// ============ Benefits ============
|
|
298
|
+
|
|
299
|
+
async listBenefitClaims(params?: {
|
|
300
|
+
memberId?: string;
|
|
301
|
+
status?: 'pending' | 'approved' | 'rejected' | 'paid' | 'cancelled';
|
|
302
|
+
benefitType?: string;
|
|
303
|
+
limit?: number;
|
|
304
|
+
}): Promise<PaginatedResponse<BenefitClaim>> {
|
|
305
|
+
return this.request('GET', '/api/v1/benefits/claims', { params });
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
async getBenefitClaim(id: string): Promise<BenefitClaim> {
|
|
309
|
+
return this.request('GET', \`/api/v1/benefits/claims/\${id}\`);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
async createBenefitClaim(data: BenefitClaimInput): Promise<BenefitClaim> {
|
|
313
|
+
return this.request('POST', '/api/v1/benefits/claims', { body: data });
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
async approveBenefitClaim(id: string, notes?: string): Promise<BenefitClaim> {
|
|
317
|
+
return this.request('POST', \`/api/v1/benefits/claims/\${id}/approve\`, { body: { notes } });
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
async rejectBenefitClaim(id: string, reason: string): Promise<BenefitClaim> {
|
|
321
|
+
return this.request('POST', \`/api/v1/benefits/claims/\${id}/reject\`, { body: { reason } });
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
async listCommissionPayouts(params?: {
|
|
325
|
+
memberId?: string;
|
|
326
|
+
status?: 'pending' | 'processing' | 'completed' | 'failed';
|
|
327
|
+
limit?: number;
|
|
328
|
+
}): Promise<PaginatedResponse<CommissionPayout>> {
|
|
329
|
+
return this.request('GET', '/api/v1/benefits/commissions', { params });
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// ============ Projects ============
|
|
333
|
+
|
|
334
|
+
async listProjects(params?: {
|
|
335
|
+
status?: 'active' | 'completed' | 'archived';
|
|
336
|
+
limit?: number;
|
|
337
|
+
}): Promise<PaginatedResponse<{ id: string; name: string; status: string }>> {
|
|
338
|
+
return this.request('GET', '/api/v1/projects', { params });
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
async getProject(id: string): Promise<{ id: string; name: string; status: string; tasks: unknown[] }> {
|
|
342
|
+
return this.request('GET', \`/api/v1/projects/\${id}\`);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// ============ Internal Request Handler ============
|
|
346
|
+
|
|
347
|
+
private async request<T>(
|
|
348
|
+
method: string,
|
|
349
|
+
path: string,
|
|
350
|
+
options?: {
|
|
351
|
+
params?: Record<string, unknown>;
|
|
352
|
+
body?: unknown;
|
|
353
|
+
}
|
|
354
|
+
): Promise<T> {
|
|
355
|
+
const url = new URL(path, this.baseUrl);
|
|
356
|
+
|
|
357
|
+
if (options?.params) {
|
|
358
|
+
Object.entries(options.params).forEach(([key, value]) => {
|
|
359
|
+
if (value !== undefined && value !== null) {
|
|
360
|
+
if (Array.isArray(value)) {
|
|
361
|
+
value.forEach(v => url.searchParams.append(key, String(v)));
|
|
362
|
+
} else {
|
|
363
|
+
url.searchParams.set(key, String(value));
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const response = await fetch(url.toString(), {
|
|
370
|
+
method,
|
|
371
|
+
headers: {
|
|
372
|
+
'Authorization': \`Bearer \${this.apiKey}\`,
|
|
373
|
+
'Content-Type': 'application/json',
|
|
374
|
+
'X-Organization-Id': this.organizationId,
|
|
375
|
+
},
|
|
376
|
+
body: options?.body ? JSON.stringify(options.body) : undefined,
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
if (!response.ok) {
|
|
380
|
+
const error = await response.json().catch(() => ({}));
|
|
381
|
+
throw new L4yercak3Error(
|
|
382
|
+
response.status,
|
|
383
|
+
error.message || \`Request failed: \${response.status}\`,
|
|
384
|
+
error.code,
|
|
385
|
+
error
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Handle 204 No Content
|
|
390
|
+
if (response.status === 204) {
|
|
391
|
+
return undefined as T;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return response.json();
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
export class L4yercak3Error extends Error {
|
|
399
|
+
constructor(
|
|
400
|
+
public status: number,
|
|
401
|
+
message: string,
|
|
402
|
+
public code?: string,
|
|
403
|
+
public details?: unknown
|
|
404
|
+
) {
|
|
405
|
+
super(message);
|
|
406
|
+
this.name = 'L4yercak3Error';
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Singleton instance
|
|
411
|
+
let client: L4yercak3Client | null = null;
|
|
412
|
+
|
|
413
|
+
export function getL4yercak3Client(): L4yercak3Client {
|
|
414
|
+
if (!client) {
|
|
415
|
+
const apiKey = process.env.L4YERCAK3_API_KEY;
|
|
416
|
+
if (!apiKey) {
|
|
417
|
+
throw new Error('L4YERCAK3_API_KEY environment variable is required');
|
|
418
|
+
}
|
|
419
|
+
client = new L4yercak3Client({ apiKey });
|
|
420
|
+
}
|
|
421
|
+
return client;
|
|
422
|
+
}
|
|
423
|
+
`;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
generateJavaScriptClient({ organizationId, backendUrl }) {
|
|
427
|
+
return `/**
|
|
428
|
+
* L4YERCAK3 API Client
|
|
429
|
+
* Auto-generated by @l4yercak3/cli
|
|
430
|
+
*
|
|
431
|
+
* A typed API client for the L4YERCAK3 platform.
|
|
432
|
+
* Organization ID: ${organizationId}
|
|
433
|
+
*/
|
|
434
|
+
|
|
435
|
+
class L4yercak3Client {
|
|
436
|
+
/**
|
|
437
|
+
* @param {Object} config
|
|
438
|
+
* @param {string} config.apiKey
|
|
439
|
+
* @param {string} [config.baseUrl]
|
|
440
|
+
* @param {string} [config.organizationId]
|
|
441
|
+
*/
|
|
442
|
+
constructor(config) {
|
|
443
|
+
this.apiKey = config.apiKey;
|
|
444
|
+
this.baseUrl = config.baseUrl || '${backendUrl}';
|
|
445
|
+
this.organizationId = config.organizationId || '${organizationId}';
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// ============ CRM: Contacts ============
|
|
449
|
+
|
|
450
|
+
/** @returns {Promise<{items: Array, total: number, hasMore: boolean}>} */
|
|
451
|
+
async listContacts(params) {
|
|
452
|
+
return this.request('GET', '/api/v1/crm/contacts', { params });
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
async getContact(id, options) {
|
|
456
|
+
return this.request('GET', \`/api/v1/crm/contacts/\${id}\`, { params: options });
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
async createContact(data) {
|
|
460
|
+
return this.request('POST', '/api/v1/crm/contacts', { body: data });
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
async updateContact(id, data) {
|
|
464
|
+
return this.request('PATCH', \`/api/v1/crm/contacts/\${id}\`, { body: data });
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
async deleteContact(id) {
|
|
468
|
+
return this.request('DELETE', \`/api/v1/crm/contacts/\${id}\`);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// ============ CRM: Organizations ============
|
|
472
|
+
|
|
473
|
+
async listOrganizations(params) {
|
|
474
|
+
return this.request('GET', '/api/v1/crm/organizations', { params });
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
async getOrganization(id, options) {
|
|
478
|
+
return this.request('GET', \`/api/v1/crm/organizations/\${id}\`, { params: options });
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
async createOrganization(data) {
|
|
482
|
+
return this.request('POST', '/api/v1/crm/organizations', { body: data });
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// ============ Events ============
|
|
486
|
+
|
|
487
|
+
async listEvents(params) {
|
|
488
|
+
return this.request('GET', '/api/v1/events', { params });
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
async getEvent(id, options) {
|
|
492
|
+
return this.request('GET', \`/api/v1/events/\${id}\`, { params: options });
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
async createEvent(data) {
|
|
496
|
+
return this.request('POST', '/api/v1/events', { body: data });
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
async getEventAttendees(eventId, params) {
|
|
500
|
+
return this.request('GET', \`/api/v1/events/\${eventId}/attendees\`, { params });
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
async checkInAttendee(eventId, attendeeId) {
|
|
504
|
+
return this.request('POST', \`/api/v1/events/\${eventId}/attendees/\${attendeeId}/check-in\`);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// ============ Forms ============
|
|
508
|
+
|
|
509
|
+
async listForms(params) {
|
|
510
|
+
return this.request('GET', '/api/v1/forms', { params });
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
async getForm(id) {
|
|
514
|
+
return this.request('GET', \`/api/v1/forms/\${id}\`);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
async submitForm(formId, data) {
|
|
518
|
+
return this.request('POST', \`/api/v1/forms/\${formId}/submit\`, { body: data });
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
async getFormResponses(formId, params) {
|
|
522
|
+
return this.request('GET', \`/api/v1/forms/\${formId}/responses\`, { params });
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// ============ Products ============
|
|
526
|
+
|
|
527
|
+
async listProducts(params) {
|
|
528
|
+
return this.request('GET', '/api/v1/products', { params });
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
async getProduct(id) {
|
|
532
|
+
return this.request('GET', \`/api/v1/products/\${id}\`);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// ============ Checkout ============
|
|
536
|
+
|
|
537
|
+
async createCheckoutSession(data) {
|
|
538
|
+
return this.request('POST', '/api/v1/checkout/sessions', { body: data });
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
async getCheckoutSession(sessionId) {
|
|
542
|
+
return this.request('GET', \`/api/v1/checkout/sessions/\${sessionId}\`);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// ============ Orders ============
|
|
546
|
+
|
|
547
|
+
async listOrders(params) {
|
|
548
|
+
return this.request('GET', '/api/v1/orders', { params });
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
async getOrder(id) {
|
|
552
|
+
return this.request('GET', \`/api/v1/orders/\${id}\`);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// ============ Invoicing ============
|
|
556
|
+
|
|
557
|
+
async listInvoices(params) {
|
|
558
|
+
return this.request('GET', '/api/v1/invoices', { params });
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
async getInvoice(id) {
|
|
562
|
+
return this.request('GET', \`/api/v1/invoices/\${id}\`);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
async createInvoice(data) {
|
|
566
|
+
return this.request('POST', '/api/v1/invoices', { body: data });
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
async sendInvoice(id, options) {
|
|
570
|
+
return this.request('POST', \`/api/v1/invoices/\${id}/send\`, { body: options });
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
async markInvoicePaid(id, data) {
|
|
574
|
+
return this.request('POST', \`/api/v1/invoices/\${id}/mark-paid\`, { body: data });
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
// ============ Benefits ============
|
|
578
|
+
|
|
579
|
+
async listBenefitClaims(params) {
|
|
580
|
+
return this.request('GET', '/api/v1/benefits/claims', { params });
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
async createBenefitClaim(data) {
|
|
584
|
+
return this.request('POST', '/api/v1/benefits/claims', { body: data });
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
async approveBenefitClaim(id, notes) {
|
|
588
|
+
return this.request('POST', \`/api/v1/benefits/claims/\${id}/approve\`, { body: { notes } });
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
async rejectBenefitClaim(id, reason) {
|
|
592
|
+
return this.request('POST', \`/api/v1/benefits/claims/\${id}/reject\`, { body: { reason } });
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// ============ Projects ============
|
|
596
|
+
|
|
597
|
+
async listProjects(params) {
|
|
598
|
+
return this.request('GET', '/api/v1/projects', { params });
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
async getProject(id) {
|
|
602
|
+
return this.request('GET', \`/api/v1/projects/\${id}\`);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// ============ Internal Request Handler ============
|
|
606
|
+
|
|
607
|
+
async request(method, path, options = {}) {
|
|
608
|
+
const url = new URL(path, this.baseUrl);
|
|
609
|
+
|
|
610
|
+
if (options.params) {
|
|
611
|
+
Object.entries(options.params).forEach(([key, value]) => {
|
|
612
|
+
if (value !== undefined && value !== null) {
|
|
613
|
+
if (Array.isArray(value)) {
|
|
614
|
+
value.forEach(v => url.searchParams.append(key, String(v)));
|
|
615
|
+
} else {
|
|
616
|
+
url.searchParams.set(key, String(value));
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
const response = await fetch(url.toString(), {
|
|
623
|
+
method,
|
|
624
|
+
headers: {
|
|
625
|
+
'Authorization': \`Bearer \${this.apiKey}\`,
|
|
626
|
+
'Content-Type': 'application/json',
|
|
627
|
+
'X-Organization-Id': this.organizationId,
|
|
628
|
+
},
|
|
629
|
+
body: options.body ? JSON.stringify(options.body) : undefined,
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
if (!response.ok) {
|
|
633
|
+
const error = await response.json().catch(() => ({}));
|
|
634
|
+
throw new L4yercak3Error(
|
|
635
|
+
response.status,
|
|
636
|
+
error.message || \`Request failed: \${response.status}\`,
|
|
637
|
+
error.code,
|
|
638
|
+
error
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
if (response.status === 204) {
|
|
643
|
+
return undefined;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
return response.json();
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
class L4yercak3Error extends Error {
|
|
651
|
+
constructor(status, message, code, details) {
|
|
652
|
+
super(message);
|
|
653
|
+
this.name = 'L4yercak3Error';
|
|
654
|
+
this.status = status;
|
|
655
|
+
this.code = code;
|
|
656
|
+
this.details = details;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
// Singleton instance
|
|
661
|
+
let client = null;
|
|
662
|
+
|
|
663
|
+
function getL4yercak3Client() {
|
|
664
|
+
if (!client) {
|
|
665
|
+
const apiKey = process.env.L4YERCAK3_API_KEY;
|
|
666
|
+
if (!apiKey) {
|
|
667
|
+
throw new Error('L4YERCAK3_API_KEY environment variable is required');
|
|
668
|
+
}
|
|
669
|
+
client = new L4yercak3Client({ apiKey });
|
|
670
|
+
}
|
|
671
|
+
return client;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
module.exports = {
|
|
675
|
+
L4yercak3Client,
|
|
676
|
+
L4yercak3Error,
|
|
677
|
+
getL4yercak3Client,
|
|
678
|
+
};
|
|
679
|
+
`;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
module.exports = new ClientGenerator();
|