@startsimpli/api 0.2.2 → 0.2.4

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/dist/index.mjs DELETED
@@ -1,2010 +0,0 @@
1
- import DOMPurify from 'isomorphic-dompurify';
2
- import { z } from 'zod';
3
- import { useState, useRef, useCallback, useEffect } from 'react';
4
-
5
- // src/utils/url-builder.ts
6
- function buildUrl({ baseUrl, endpoint, params, id }) {
7
- const cleanBase = baseUrl.replace(/\/$/, "");
8
- const cleanEndpoint = endpoint.replace(/^\//, "");
9
- let path = `${cleanBase}/${cleanEndpoint}`;
10
- if (id !== void 0) {
11
- path += `/${id}`;
12
- }
13
- if (!path.endsWith("/")) {
14
- path += "/";
15
- }
16
- if (params && Object.keys(params).length > 0) {
17
- const queryString = buildQueryString(params);
18
- if (queryString) {
19
- path += `?${queryString}`;
20
- }
21
- }
22
- return path;
23
- }
24
- function buildQueryString(params) {
25
- const searchParams = new URLSearchParams();
26
- Object.entries(params).forEach(([key, value]) => {
27
- if (value === void 0 || value === null) {
28
- return;
29
- }
30
- if (Array.isArray(value)) {
31
- value.forEach((item) => {
32
- searchParams.append(key, String(item));
33
- });
34
- } else if (typeof value === "object") {
35
- searchParams.append(key, JSON.stringify(value));
36
- } else {
37
- searchParams.append(key, String(value));
38
- }
39
- });
40
- return searchParams.toString();
41
- }
42
- function resolveApiUrl(path, baseUrl = "") {
43
- if (/^https?:\/\//i.test(path)) return path;
44
- const normalized = path.startsWith("/") ? path : `/${path}`;
45
- if (!baseUrl) return normalized;
46
- if (/^https?:\/\//i.test(baseUrl)) {
47
- return new URL(normalized, baseUrl).toString();
48
- }
49
- const cleanBase = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
50
- return `${cleanBase}${normalized}`;
51
- }
52
- function normalizeId(id) {
53
- if (typeof id === "string" && id.includes("/")) {
54
- const parts = id.split("/").filter(Boolean);
55
- return parts[parts.length - 1];
56
- }
57
- return id;
58
- }
59
-
60
- // src/utils/query-params.ts
61
- function buildFilterParams(filters) {
62
- const params = {};
63
- Object.entries(filters).forEach(([key, value]) => {
64
- if (value === void 0 || value === null) {
65
- return;
66
- }
67
- if (typeof value === "boolean") {
68
- params[key] = value;
69
- return;
70
- }
71
- if (Array.isArray(value)) {
72
- if (value.length > 0) {
73
- params[`${key}__in`] = value.join(",");
74
- }
75
- return;
76
- }
77
- if (key.endsWith("_gte") || key.endsWith("_lte") || key.endsWith("_gt") || key.endsWith("_lt")) {
78
- params[key] = value;
79
- return;
80
- }
81
- params[key] = value;
82
- });
83
- return params;
84
- }
85
- function buildOrderingParam(field, direction = "asc") {
86
- if (!field) {
87
- return void 0;
88
- }
89
- return direction === "desc" ? `-${field}` : field;
90
- }
91
- function mergeQueryParams(pagination, sorting, filters) {
92
- return {
93
- ...filters,
94
- ...pagination,
95
- ...sorting
96
- };
97
- }
98
-
99
- // src/utils/validate-response.ts
100
- function validateApiResponse(data, schema, context) {
101
- const result = schema.safeParse(data);
102
- if (!result.success) {
103
- const label = context ? `[${context}]` : "[API validation]";
104
- console.warn(
105
- `${label} Schema mismatch \u2014 returning raw data.`,
106
- result.error.flatten().fieldErrors
107
- );
108
- return data;
109
- }
110
- return result.data;
111
- }
112
-
113
- // src/utils/entity-query-builder.ts
114
- var EntityQueryBuilder = class {
115
- constructor() {
116
- this.params = /* @__PURE__ */ new Map();
117
- }
118
- /**
119
- * Filter by entity type
120
- */
121
- entityType(type) {
122
- this.params.set("entity_type", type);
123
- return this;
124
- }
125
- /**
126
- * Add tag filters (compact format: "category:name")
127
- *
128
- * @example
129
- * .withTags('quality:tier_1', 'status:prospect')
130
- * // produces: tags=quality:tier_1,status:prospect
131
- */
132
- withTags(...tags) {
133
- if (tags.length > 0) {
134
- const existing = this.params.get("tags");
135
- const combined = existing ? `${existing},${tags.join(",")}` : tags.join(",");
136
- this.params.set("tags", combined);
137
- }
138
- return this;
139
- }
140
- /**
141
- * Add metric filters (compact format: "type:subtype__operator:value")
142
- *
143
- * @example
144
- * .withMetrics('financial:aum__gte:100000000', 'check_size:min__gte:1000000')
145
- */
146
- withMetrics(...metrics) {
147
- if (metrics.length > 0) {
148
- const existing = this.params.get("metrics");
149
- const combined = existing ? `${existing},${metrics.join(",")}` : metrics.join(",");
150
- this.params.set("metrics", combined);
151
- }
152
- return this;
153
- }
154
- /**
155
- * Add profile filters (compact format: "type:subtype")
156
- *
157
- * @example
158
- * .withProfiles('professional:linkedin', 'social:twitter')
159
- */
160
- withProfiles(...profiles) {
161
- if (profiles.length > 0) {
162
- const existing = this.params.get("profiles");
163
- const combined = existing ? `${existing},${profiles.join(",")}` : profiles.join(",");
164
- this.params.set("profiles", combined);
165
- }
166
- return this;
167
- }
168
- /**
169
- * Add attribute filters (compact format: "type:subtype:value")
170
- *
171
- * @example
172
- * .withAttributes('demographic:location:san_francisco')
173
- */
174
- withAttributes(...attrs) {
175
- if (attrs.length > 0) {
176
- const existing = this.params.get("attributes");
177
- const combined = existing ? `${existing},${attrs.join(",")}` : attrs.join(",");
178
- this.params.set("attributes", combined);
179
- }
180
- return this;
181
- }
182
- /**
183
- * Set pagination parameters
184
- */
185
- paginate(page, pageSize) {
186
- this.params.set("page", String(page));
187
- this.params.set("page_size", String(pageSize));
188
- return this;
189
- }
190
- /**
191
- * Set search query
192
- */
193
- search(query) {
194
- const trimmed = query.trim();
195
- if (trimmed) {
196
- this.params.set("search", trimmed);
197
- }
198
- return this;
199
- }
200
- /**
201
- * Set sort field and direction (maps to Django's `ordering` param)
202
- */
203
- sort(field, direction = "asc") {
204
- const prefix = direction === "desc" ? "-" : "";
205
- this.params.set("ordering", `${prefix}${field}`);
206
- return this;
207
- }
208
- /**
209
- * Add a date range filter on a given field
210
- *
211
- * @example
212
- * .withDateRange('created', new Date('2024-01-01'), new Date('2024-12-31'))
213
- * // produces: created_after=2024-01-01&created_before=2024-12-31
214
- */
215
- withDateRange(field, from, to) {
216
- if (from) {
217
- this.params.set(`${field}_after`, from.toISOString().split("T")[0]);
218
- }
219
- if (to) {
220
- this.params.set(`${field}_before`, to.toISOString().split("T")[0]);
221
- }
222
- return this;
223
- }
224
- /**
225
- * Set an arbitrary query parameter
226
- */
227
- param(key, value) {
228
- this.params.set(key, value);
229
- return this;
230
- }
231
- /**
232
- * Build as a plain object (suitable for URLSearchParams or fetch helpers)
233
- */
234
- build() {
235
- const result = {};
236
- this.params.forEach((value, key) => {
237
- result[key] = value;
238
- });
239
- return result;
240
- }
241
- /**
242
- * Build as a query string (includes leading `?`)
243
- * Returns empty string if no params.
244
- */
245
- toQueryString() {
246
- if (this.params.size === 0) return "";
247
- const searchParams = new URLSearchParams();
248
- this.params.forEach((value, key) => {
249
- searchParams.set(key, value);
250
- });
251
- return `?${searchParams.toString()}`;
252
- }
253
- /**
254
- * Reset all parameters
255
- */
256
- clear() {
257
- this.params.clear();
258
- return this;
259
- }
260
- };
261
-
262
- // src/utils/drf-transforms.ts
263
- function normalizePaginated(response, page, pageSize) {
264
- const total = response.count || 0;
265
- return {
266
- items: response.results || [],
267
- total,
268
- page,
269
- pageSize,
270
- hasNext: response.next !== null,
271
- hasPrev: response.previous !== null
272
- };
273
- }
274
- function isDRFPaginatedResponse(response) {
275
- return typeof response === "object" && response !== null && "results" in response && "count" in response;
276
- }
277
-
278
- // src/lib/error-handler.ts
279
- var ApiException = class extends Error {
280
- constructor(message, options) {
281
- super(message);
282
- this.name = "ApiException";
283
- this.status = options?.status;
284
- this.statusText = options?.statusText;
285
- this.errors = options?.errors;
286
- this.detail = options?.detail;
287
- }
288
- toJSON() {
289
- return {
290
- message: this.message,
291
- detail: this.detail,
292
- status: this.status,
293
- statusText: this.statusText,
294
- errors: this.errors
295
- };
296
- }
297
- };
298
- async function parseErrorResponse(response) {
299
- const contentType = response.headers?.get("content-type");
300
- if (contentType?.includes("application/json")) {
301
- try {
302
- const data = await response.json();
303
- if (data.detail) {
304
- return {
305
- detail: data.detail,
306
- message: data.detail,
307
- status: response.status,
308
- statusText: response.statusText
309
- };
310
- }
311
- if (typeof data === "object") {
312
- return {
313
- errors: data,
314
- message: "Validation error",
315
- status: response.status,
316
- statusText: response.statusText
317
- };
318
- }
319
- return {
320
- message: JSON.stringify(data),
321
- status: response.status,
322
- statusText: response.statusText
323
- };
324
- } catch {
325
- }
326
- }
327
- const text = await response.text().catch(() => response.statusText);
328
- return {
329
- message: text || response.statusText || "Unknown error",
330
- status: response.status,
331
- statusText: response.statusText
332
- };
333
- }
334
- function handleFetchError(error) {
335
- if (error instanceof ApiException) {
336
- throw error;
337
- }
338
- if (error instanceof TypeError && error.message.includes("fetch")) {
339
- throw new ApiException("Network error - please check your connection", {
340
- status: 0,
341
- statusText: "Network Error"
342
- });
343
- }
344
- if (error instanceof Error) {
345
- throw new ApiException(error.message, {
346
- status: 0,
347
- statusText: "Client Error"
348
- });
349
- }
350
- throw new ApiException("Unknown error occurred", {
351
- status: 0,
352
- statusText: "Unknown Error"
353
- });
354
- }
355
- function isApiException(error) {
356
- return error instanceof ApiException;
357
- }
358
- function isValidationError(error) {
359
- return isApiException(error) && error.status === 400 && !!error.errors;
360
- }
361
- function isAuthError(error) {
362
- return isApiException(error) && (error.status === 401 || error.status === 403);
363
- }
364
- function isNotFoundError(error) {
365
- return isApiException(error) && error.status === 404;
366
- }
367
-
368
- // src/lib/fetch-wrapper.ts
369
- var FetchWrapper = class _FetchWrapper {
370
- constructor(config) {
371
- this.isRefreshing = false;
372
- this.refreshPromise = null;
373
- this.config = config;
374
- }
375
- /**
376
- * Build headers with auth token
377
- */
378
- async buildHeaders(customHeaders) {
379
- const headers = new Headers(this.config.defaultHeaders);
380
- if (customHeaders) {
381
- const customHeadersObj = new Headers(customHeaders);
382
- customHeadersObj.forEach((value, key) => {
383
- headers.set(key, value);
384
- });
385
- }
386
- if (this.config.getToken) {
387
- const token = await this.config.getToken();
388
- if (token) {
389
- headers.set("Authorization", `Bearer ${token}`);
390
- }
391
- }
392
- if (!headers.has("Content-Type")) {
393
- headers.set("Content-Type", "application/json");
394
- }
395
- return headers;
396
- }
397
- /**
398
- * Execute fetch request
399
- */
400
- async execute(method, endpoint, options) {
401
- try {
402
- const { params, headers: customHeaders, ...fetchOptions } = options || {};
403
- const url = buildUrl({
404
- baseUrl: this.config.baseUrl ?? "",
405
- endpoint,
406
- params
407
- });
408
- const headers = await this.buildHeaders(customHeaders);
409
- let response = await fetch(url, {
410
- method,
411
- headers,
412
- credentials: "include",
413
- ...fetchOptions
414
- });
415
- if (response.status === 401) {
416
- if (this.config.onTokenRefresh) {
417
- if (!this.isRefreshing) {
418
- this.isRefreshing = true;
419
- this.refreshPromise = this.config.onTokenRefresh().finally(() => {
420
- this.isRefreshing = false;
421
- this.refreshPromise = null;
422
- });
423
- }
424
- const newToken = await this.refreshPromise;
425
- if (newToken) {
426
- const retryHeaders = new Headers(headers);
427
- retryHeaders.set("Authorization", `Bearer ${newToken}`);
428
- response = await fetch(url, {
429
- method,
430
- headers: retryHeaders,
431
- credentials: "include",
432
- ...fetchOptions
433
- });
434
- } else if (this.config.onUnauthorized) {
435
- this.config.onUnauthorized();
436
- }
437
- } else if (this.config.onUnauthorized) {
438
- this.config.onUnauthorized();
439
- }
440
- }
441
- if (!response.ok) {
442
- const error = await parseErrorResponse(response);
443
- throw new ApiException(error.message || "Request failed", error);
444
- }
445
- if (response.status === 204) {
446
- return void 0;
447
- }
448
- return await response.json();
449
- } catch (error) {
450
- handleFetchError(error);
451
- }
452
- }
453
- /**
454
- * Return a new FetchWrapper with selected config fields overridden.
455
- */
456
- reconfigure(partial) {
457
- return new _FetchWrapper({ ...this.config, ...partial });
458
- }
459
- /**
460
- * GET request
461
- */
462
- async get(endpoint, options) {
463
- return this.execute("GET", endpoint, options);
464
- }
465
- /**
466
- * POST request
467
- */
468
- async post(endpoint, data, options) {
469
- return this.execute("POST", endpoint, {
470
- ...options,
471
- body: data ? JSON.stringify(data) : void 0
472
- });
473
- }
474
- /**
475
- * PUT request
476
- */
477
- async put(endpoint, data, options) {
478
- return this.execute("PUT", endpoint, {
479
- ...options,
480
- body: data ? JSON.stringify(data) : void 0
481
- });
482
- }
483
- /**
484
- * PATCH request
485
- */
486
- async patch(endpoint, data, options) {
487
- return this.execute("PATCH", endpoint, {
488
- ...options,
489
- body: data ? JSON.stringify(data) : void 0
490
- });
491
- }
492
- /**
493
- * DELETE request
494
- */
495
- async delete(endpoint, options) {
496
- return this.execute("DELETE", endpoint, options);
497
- }
498
- };
499
-
500
- // src/lib/api-client.ts
501
- var ApiClient = class {
502
- constructor(config) {
503
- this.baseUrl = config.baseUrl ?? "";
504
- this.fetcher = new FetchWrapper({
505
- baseUrl: config.baseUrl,
506
- getToken: config.getToken,
507
- onUnauthorized: config.onUnauthorized,
508
- onTokenRefresh: config.onTokenRefresh,
509
- defaultHeaders: {
510
- "Content-Type": "application/json",
511
- "Accept": "application/json"
512
- }
513
- });
514
- }
515
- /**
516
- * Get the fetch wrapper instance for direct access
517
- */
518
- get fetch() {
519
- return this.fetcher;
520
- }
521
- /**
522
- * Update auth token getter
523
- */
524
- setTokenGetter(getToken) {
525
- this.fetcher = this.fetcher.reconfigure({ getToken });
526
- }
527
- /**
528
- * Update unauthorized handler
529
- */
530
- setUnauthorizedHandler(onUnauthorized) {
531
- this.fetcher = this.fetcher.reconfigure({ onUnauthorized });
532
- }
533
- /**
534
- * Convenience HTTP methods that delegate to FetchWrapper
535
- */
536
- async get(endpoint, options) {
537
- return this.fetcher.get(endpoint, options);
538
- }
539
- async post(endpoint, data, options) {
540
- return this.fetcher.post(endpoint, data, options);
541
- }
542
- async patch(endpoint, data, options) {
543
- return this.fetcher.patch(endpoint, data, options);
544
- }
545
- async delete(endpoint, options) {
546
- return this.fetcher.delete(endpoint, options);
547
- }
548
- };
549
- function createApiClient(config) {
550
- return new ApiClient(config);
551
- }
552
-
553
- // src/constants/endpoints.ts
554
- var ENDPOINTS = {
555
- // Contacts
556
- CONTACTS: "contacts",
557
- CONTACTS_BULK: "contacts/bulk",
558
- CONTACT: (id) => `contacts/${id}`,
559
- // Organizations
560
- ORGANIZATIONS: "organizations",
561
- ORGANIZATIONS_BULK: "organizations/bulk",
562
- ORGANIZATION: (id) => `organizations/${id}`,
563
- // Core entities
564
- TAGS: "core/tags",
565
- TAG: (id) => `core/tags/${id}`,
566
- ENTITY_TAGS: "core/entity-tags",
567
- ENTITY_TAG: (id) => `core/entity-tags/${id}`,
568
- METRICS: "core/metrics",
569
- METRIC: (id) => `core/metrics/${id}`,
570
- PROFILES: "core/profiles",
571
- PROFILE: (id) => `core/profiles/${id}`,
572
- ATTRIBUTES: "core/attributes",
573
- ATTRIBUTE: (id) => `core/attributes/${id}`,
574
- RELATIONSHIPS: "core/relationships",
575
- RELATIONSHIP: (id) => `core/relationships/${id}`,
576
- // Workflows
577
- WORKFLOWS: "workflows",
578
- WORKFLOW: (id) => `workflows/${id}`,
579
- WORKFLOW_EXECUTE: (id) => `workflows/${id}/execute`,
580
- // Messages
581
- MESSAGES: "messages",
582
- MESSAGE: (id) => `messages/${id}`,
583
- MESSAGE_SEND: (id) => `messages/${id}/send`,
584
- // Funnels
585
- FUNNELS: "funnels",
586
- FUNNEL: (id) => `funnels/${id}`,
587
- FUNNEL_RUN: (id) => `funnels/${id}/run`,
588
- FUNNEL_RUNS: (id) => `funnels/${id}/runs`,
589
- FUNNEL_RUN_ITEM: (funnelId, runId) => `funnels/${funnelId}/runs/${runId}`,
590
- FUNNEL_PREVIEW: (id) => `funnels/${id}/preview`,
591
- FUNNEL_RESULTS: (id) => `funnels/${id}/results`,
592
- FUNNEL_TEMPLATES: "funnels/templates",
593
- FUNNEL_RUN_BY_ID: (runId) => `funnel-runs/${runId}`,
594
- FUNNEL_RUN_CANCEL: (runId) => `funnel-runs/${runId}/cancel`,
595
- FUNNEL_RUNS_GLOBAL: "funnel-runs"
596
- };
597
-
598
- // src/lib/contacts-api.ts
599
- var ContactsApi = class {
600
- constructor(client) {
601
- this.client = client;
602
- }
603
- /**
604
- * List contacts with pagination and filters
605
- */
606
- async list(filters, pagination, sorting) {
607
- const params = mergeQueryParams(
608
- pagination,
609
- sorting,
610
- filters ? buildFilterParams(filters) : void 0
611
- );
612
- return this.client.fetch.get(ENDPOINTS.CONTACTS, { params });
613
- }
614
- /**
615
- * Get contact by ID
616
- */
617
- async get(id) {
618
- return this.client.fetch.get(ENDPOINTS.CONTACT(id));
619
- }
620
- /**
621
- * Create new contact
622
- */
623
- async create(data) {
624
- return this.client.fetch.post(ENDPOINTS.CONTACTS, data);
625
- }
626
- /**
627
- * Update contact
628
- */
629
- async update(id, data) {
630
- return this.client.fetch.patch(ENDPOINTS.CONTACT(id), data);
631
- }
632
- /**
633
- * Delete contact
634
- */
635
- async delete(id) {
636
- return this.client.fetch.delete(ENDPOINTS.CONTACT(id));
637
- }
638
- /**
639
- * Bulk create contacts
640
- */
641
- async bulkCreate(data) {
642
- return this.client.fetch.post(ENDPOINTS.CONTACTS_BULK, data);
643
- }
644
- /**
645
- * Search contacts by name, email, or company
646
- */
647
- async search(query, pagination) {
648
- return this.list({ search: query }, pagination);
649
- }
650
- /**
651
- * Get contacts by tier
652
- */
653
- async getByTier(tier, pagination) {
654
- return this.list({ tier }, pagination);
655
- }
656
- /**
657
- * Get contacts by firm
658
- */
659
- async getByFirm(firmId, pagination) {
660
- return this.list({ firmId }, pagination);
661
- }
662
- /**
663
- * Get contacts with LinkedIn profiles
664
- */
665
- async getWithLinkedIn(pagination) {
666
- return this.list({ hasLinkedin: true }, pagination);
667
- }
668
- };
669
-
670
- // src/lib/organizations-api.ts
671
- var OrganizationsApi = class {
672
- constructor(client) {
673
- this.client = client;
674
- }
675
- /**
676
- * List organizations with pagination and filters
677
- */
678
- async list(filters, pagination, sorting) {
679
- const params = mergeQueryParams(
680
- pagination,
681
- sorting,
682
- filters ? buildFilterParams(filters) : void 0
683
- );
684
- return this.client.fetch.get(ENDPOINTS.ORGANIZATIONS, {
685
- params
686
- });
687
- }
688
- /**
689
- * Get organization by ID
690
- */
691
- async get(id) {
692
- return this.client.fetch.get(ENDPOINTS.ORGANIZATION(id));
693
- }
694
- /**
695
- * Create new organization
696
- */
697
- async create(data) {
698
- return this.client.fetch.post(ENDPOINTS.ORGANIZATIONS, data);
699
- }
700
- /**
701
- * Update organization
702
- */
703
- async update(id, data) {
704
- return this.client.fetch.patch(ENDPOINTS.ORGANIZATION(id), data);
705
- }
706
- /**
707
- * Delete organization
708
- */
709
- async delete(id) {
710
- return this.client.fetch.delete(ENDPOINTS.ORGANIZATION(id));
711
- }
712
- /**
713
- * Bulk create organizations
714
- */
715
- async bulkCreate(data) {
716
- return this.client.fetch.post(ENDPOINTS.ORGANIZATIONS_BULK, data);
717
- }
718
- /**
719
- * Search organizations by name, domain, or location
720
- */
721
- async search(query, pagination) {
722
- return this.list({ search: query }, pagination);
723
- }
724
- /**
725
- * Get organizations by tier
726
- */
727
- async getByTier(tier, pagination) {
728
- return this.list({ tier }, pagination);
729
- }
730
- /**
731
- * Get organizations by stage
732
- */
733
- async getByStage(stage, pagination) {
734
- return this.list({ stage }, pagination);
735
- }
736
- /**
737
- * Get organizations by focus area
738
- */
739
- async getByFocusArea(focusArea, pagination) {
740
- return this.list({ focusArea }, pagination);
741
- }
742
- /**
743
- * Get organizations by check size range
744
- */
745
- async getByCheckSizeRange(min, max, pagination) {
746
- const filters = {};
747
- if (min !== void 0) {
748
- filters.checkSizeMinGte = min;
749
- }
750
- if (max !== void 0) {
751
- filters.checkSizeMaxLte = max;
752
- }
753
- return this.list(filters, pagination);
754
- }
755
- };
756
-
757
- // src/lib/entities-api.ts
758
- var EntitiesApi = class {
759
- constructor(client) {
760
- this.client = client;
761
- }
762
- /**
763
- * Tags
764
- */
765
- async listTags(pagination) {
766
- const params = mergeQueryParams(pagination);
767
- return this.client.fetch.get(ENDPOINTS.TAGS, { params });
768
- }
769
- async getTag(id) {
770
- return this.client.fetch.get(ENDPOINTS.TAG(String(id)));
771
- }
772
- async createTag(data) {
773
- return this.client.fetch.post(ENDPOINTS.TAGS, data);
774
- }
775
- /**
776
- * Entity Tags
777
- */
778
- async listEntityTags(pagination, filters) {
779
- const params = mergeQueryParams(pagination, void 0, filters);
780
- return this.client.fetch.get(ENDPOINTS.ENTITY_TAGS, {
781
- params
782
- });
783
- }
784
- async getEntityTag(id) {
785
- return this.client.fetch.get(ENDPOINTS.ENTITY_TAG(String(id)));
786
- }
787
- /**
788
- * Metrics
789
- */
790
- async listMetrics(pagination, filters) {
791
- const params = mergeQueryParams(pagination, void 0, filters);
792
- return this.client.fetch.get(ENDPOINTS.METRICS, { params });
793
- }
794
- async getMetric(id) {
795
- return this.client.fetch.get(ENDPOINTS.METRIC(String(id)));
796
- }
797
- /**
798
- * Profiles
799
- */
800
- async listProfiles(pagination, filters) {
801
- const params = mergeQueryParams(pagination, void 0, filters);
802
- return this.client.fetch.get(ENDPOINTS.PROFILES, { params });
803
- }
804
- async getProfile(id) {
805
- return this.client.fetch.get(ENDPOINTS.PROFILE(String(id)));
806
- }
807
- /**
808
- * Attributes
809
- */
810
- async listAttributes(pagination, filters) {
811
- const params = mergeQueryParams(pagination, void 0, filters);
812
- return this.client.fetch.get(ENDPOINTS.ATTRIBUTES, {
813
- params
814
- });
815
- }
816
- async getAttribute(id) {
817
- return this.client.fetch.get(ENDPOINTS.ATTRIBUTE(String(id)));
818
- }
819
- /**
820
- * Relationships
821
- */
822
- async listRelationships(pagination, filters) {
823
- const params = mergeQueryParams(pagination, void 0, filters);
824
- return this.client.fetch.get(ENDPOINTS.RELATIONSHIPS, {
825
- params
826
- });
827
- }
828
- async getRelationship(id) {
829
- return this.client.fetch.get(ENDPOINTS.RELATIONSHIP(String(id)));
830
- }
831
- };
832
-
833
- // src/lib/workflows-api.ts
834
- var WorkflowsApi = class {
835
- constructor(client) {
836
- this.client = client;
837
- }
838
- /**
839
- * List workflows with optional filters
840
- */
841
- async list(filters) {
842
- const params = new URLSearchParams();
843
- if (filters?.team) params.append("team", filters.team);
844
- if (filters?.isActive !== void 0) params.append("isActive", String(filters.isActive));
845
- if (filters?.isTemplate !== void 0) params.append("isTemplate", String(filters.isTemplate));
846
- if (filters?.page) params.append("page", String(filters.page));
847
- if (filters?.pageSize) params.append("pageSize", String(filters.pageSize));
848
- if (filters?.ordering) params.append("ordering", filters.ordering);
849
- return this.client.get(
850
- `/api/v1/workflows/?${params.toString()}`
851
- );
852
- }
853
- /**
854
- * Get workflow by ID
855
- */
856
- async get(id) {
857
- return this.client.get(`/api/v1/workflows/${id}/`);
858
- }
859
- /**
860
- * Create a new workflow
861
- */
862
- async create(data) {
863
- return this.client.post("/api/v1/workflows/", data);
864
- }
865
- /**
866
- * Update workflow
867
- */
868
- async update(id, data) {
869
- return this.client.patch(`/api/v1/workflows/${id}/`, data);
870
- }
871
- /**
872
- * Delete workflow
873
- */
874
- async delete(id) {
875
- return this.client.delete(`/api/v1/workflows/${id}/`);
876
- }
877
- /**
878
- * Execute workflow
879
- */
880
- async execute(id, input) {
881
- return this.client.post(
882
- `/api/v1/workflows/${id}/execute/`,
883
- input || {}
884
- );
885
- }
886
- /**
887
- * Get workflow templates
888
- */
889
- async templates() {
890
- return this.client.get("/api/v1/workflows/templates/");
891
- }
892
- /**
893
- * List workflow executions
894
- */
895
- async listExecutions(filters) {
896
- const params = new URLSearchParams();
897
- if (filters?.workflow) params.append("workflow", filters.workflow);
898
- if (filters?.status) params.append("status", filters.status);
899
- if (filters?.page) params.append("page", String(filters.page));
900
- if (filters?.pageSize) params.append("pageSize", String(filters.pageSize));
901
- return this.client.get(
902
- `/api/v1/workflow-executions/?${params.toString()}`
903
- );
904
- }
905
- /**
906
- * Get workflow execution details
907
- */
908
- async getExecution(id) {
909
- return this.client.get(`/api/v1/workflow-executions/${id}/`);
910
- }
911
- };
912
-
913
- // src/lib/messages-api.ts
914
- var MessagesApi = class {
915
- constructor(client) {
916
- this.client = client;
917
- }
918
- /**
919
- * List messages with optional filters
920
- */
921
- async list(filters) {
922
- const params = new URLSearchParams();
923
- if (filters?.status) params.append("status", filters.status);
924
- if (filters?.contentType) params.append("contentType", filters.contentType);
925
- if (filters?.scheduledAfter) params.append("scheduledAfter", filters.scheduledAfter);
926
- if (filters?.scheduledBefore) params.append("scheduledBefore", filters.scheduledBefore);
927
- if (filters?.sentAfter) params.append("sentAfter", filters.sentAfter);
928
- if (filters?.sentBefore) params.append("sentBefore", filters.sentBefore);
929
- if (filters?.search) params.append("search", filters.search);
930
- if (filters?.page) params.append("page", String(filters.page));
931
- if (filters?.pageSize) params.append("pageSize", String(filters.pageSize));
932
- if (filters?.ordering) params.append("ordering", filters.ordering);
933
- return this.client.get(
934
- `/api/v1/messages/?${params.toString()}`
935
- );
936
- }
937
- /**
938
- * Get message by ID
939
- */
940
- async get(id) {
941
- return this.client.get(`/api/v1/messages/${id}/`);
942
- }
943
- /**
944
- * Create a new message
945
- */
946
- async create(data) {
947
- return this.client.post("/api/v1/messages/", data);
948
- }
949
- /**
950
- * Update message (draft only)
951
- */
952
- async update(id, data) {
953
- return this.client.patch(`/api/v1/messages/${id}/`, data);
954
- }
955
- /**
956
- * Delete message (draft only)
957
- */
958
- async delete(id) {
959
- return this.client.delete(`/api/v1/messages/${id}/`);
960
- }
961
- /**
962
- * Schedule message for future sending
963
- */
964
- async schedule(id, input) {
965
- return this.client.post(
966
- `/api/v1/messages/${id}/schedule/`,
967
- input
968
- );
969
- }
970
- /**
971
- * Send message immediately
972
- */
973
- async sendNow(id) {
974
- return this.client.post(
975
- `/api/v1/messages/${id}/send_now/`,
976
- {}
977
- );
978
- }
979
- /**
980
- * Send test message
981
- */
982
- async sendTest(id, input) {
983
- return this.client.post(
984
- `/api/v1/messages/${id}/send_test/`,
985
- input || {}
986
- );
987
- }
988
- /**
989
- * Preview message rendering
990
- */
991
- async preview(id) {
992
- return this.client.get(`/api/v1/messages/${id}/preview/`);
993
- }
994
- /**
995
- * List recipients for a message
996
- */
997
- async getRecipients(id, page, pageSize) {
998
- const params = new URLSearchParams();
999
- if (page) params.append("page", String(page));
1000
- if (pageSize) params.append("pageSize", String(pageSize));
1001
- return this.client.get(
1002
- `/api/v1/messages/${id}/recipients/?${params.toString()}`
1003
- );
1004
- }
1005
- /**
1006
- * Add recipients to a message
1007
- */
1008
- async addRecipients(id, recipients) {
1009
- return this.client.post(`/api/v1/messages/${id}/add_recipients/`, { recipients });
1010
- }
1011
- /**
1012
- * Get available messaging channels
1013
- */
1014
- async getChannels() {
1015
- return this.client.get("/api/v1/messages/channels/");
1016
- }
1017
- };
1018
-
1019
- // src/lib/funnels-api.ts
1020
- function isFunnelRunConflict(error) {
1021
- return isApiException(error) && error.status === 409;
1022
- }
1023
- function isFunnelValidationError(error) {
1024
- return isApiException(error) && error.status === 400 && !!error.errors;
1025
- }
1026
- var FunnelsApi = class {
1027
- constructor(client) {
1028
- this.client = client;
1029
- }
1030
- /**
1031
- * List funnels with optional filters.
1032
- * Tags are passed as repeated query params: ?tags=campaign:abc&tags=product:market-simpli
1033
- */
1034
- async list(filters) {
1035
- const params = new URLSearchParams();
1036
- if (filters?.status) params.append("status", filters.status);
1037
- if (filters?.entityType) params.append("entityType", filters.entityType);
1038
- if (filters?.search) params.append("search", filters.search);
1039
- if (filters?.createdBy) params.append("createdBy", filters.createdBy);
1040
- if (filters?.page) params.append("page", String(filters.page));
1041
- if (filters?.pageSize) params.append("pageSize", String(filters.pageSize));
1042
- if (filters?.ordering) params.append("ordering", filters.ordering);
1043
- if (filters?.tags?.length) {
1044
- for (const tag of filters.tags) {
1045
- params.append("tags", tag);
1046
- }
1047
- }
1048
- const query = params.toString();
1049
- const endpoint = query ? `${ENDPOINTS.FUNNELS}?${query}` : ENDPOINTS.FUNNELS;
1050
- return this.client.get(endpoint);
1051
- }
1052
- /**
1053
- * Get funnel by ID
1054
- */
1055
- async get(id) {
1056
- return this.client.get(ENDPOINTS.FUNNEL(id));
1057
- }
1058
- /**
1059
- * Create a new funnel
1060
- */
1061
- async create(data) {
1062
- return this.client.post(ENDPOINTS.FUNNELS, data);
1063
- }
1064
- /**
1065
- * Update funnel (partial)
1066
- */
1067
- async update(id, data) {
1068
- return this.client.patch(ENDPOINTS.FUNNEL(id), data);
1069
- }
1070
- /**
1071
- * Delete funnel
1072
- */
1073
- async delete(id) {
1074
- return this.client.delete(ENDPOINTS.FUNNEL(id));
1075
- }
1076
- /**
1077
- * Execute a funnel run
1078
- */
1079
- async run(id, input) {
1080
- return this.client.post(ENDPOINTS.FUNNEL_RUN(id), input ?? {});
1081
- }
1082
- /**
1083
- * List run history for a funnel
1084
- */
1085
- async getRuns(funnelId, filters) {
1086
- const params = new URLSearchParams();
1087
- if (filters?.page) params.append("page", String(filters.page));
1088
- if (filters?.pageSize) params.append("pageSize", String(filters.pageSize));
1089
- if (filters?.status) params.append("status", filters.status);
1090
- if (filters?.ordering) params.append("ordering", filters.ordering);
1091
- const query = params.toString();
1092
- const endpoint = query ? `${ENDPOINTS.FUNNEL_RUNS(funnelId)}?${query}` : ENDPOINTS.FUNNEL_RUNS(funnelId);
1093
- return this.client.get(endpoint);
1094
- }
1095
- /**
1096
- * Get a specific run by ID. funnelId param is ignored (runs are accessed globally).
1097
- */
1098
- async getRun(_funnelId, runId) {
1099
- return this.client.get(ENDPOINTS.FUNNEL_RUN_BY_ID(runId));
1100
- }
1101
- // BEAD: fund-your-startup-rgi4 - funnels/{id}/results endpoint missing from Django FunnelViewSet
1102
- async getResults(_funnelId, _pagination) {
1103
- throw new Error("Not implemented - BEAD: fund-your-startup-rgi4. funnels/{id}/results action does not exist in Django.");
1104
- }
1105
- // BEAD: fund-your-startup-rgi4 - funnels/{id}/preview endpoint missing. Django has /funnels/preview-icp/ (different signature).
1106
- async preview(_funnelId, _stages) {
1107
- throw new Error("Not implemented - BEAD: fund-your-startup-rgi4. funnels/{id}/preview action does not exist in Django.");
1108
- }
1109
- /**
1110
- * List all funnel runs globally (across all funnels, scoped to current user)
1111
- */
1112
- async listRunsGlobal(filters) {
1113
- const params = new URLSearchParams();
1114
- if (filters?.funnel) params.append("funnel", filters.funnel);
1115
- if (filters?.status) params.append("status", filters.status);
1116
- if (filters?.page) params.append("page", String(filters.page));
1117
- if (filters?.pageSize) params.append("pageSize", String(filters.pageSize));
1118
- if (filters?.startedAfter) params.append("startedAfter", filters.startedAfter);
1119
- if (filters?.startedBefore) params.append("startedBefore", filters.startedBefore);
1120
- const query = params.toString();
1121
- const endpoint = query ? `${ENDPOINTS.FUNNEL_RUNS_GLOBAL}?${query}` : ENDPOINTS.FUNNEL_RUNS_GLOBAL;
1122
- return this.client.get(endpoint);
1123
- }
1124
- /**
1125
- * Cancel a running funnel run.
1126
- */
1127
- async cancelRun(runId) {
1128
- return this.client.post(ENDPOINTS.FUNNEL_RUN_CANCEL(runId), {});
1129
- }
1130
- /**
1131
- * List available funnel templates
1132
- */
1133
- async listTemplates(filters) {
1134
- const params = new URLSearchParams();
1135
- if (filters?.category) params.append("category", filters.category);
1136
- if (filters?.page) params.append("page", String(filters.page));
1137
- if (filters?.pageSize) params.append("pageSize", String(filters.pageSize));
1138
- const query = params.toString();
1139
- const endpoint = query ? `${ENDPOINTS.FUNNEL_TEMPLATES}?${query}` : ENDPOINTS.FUNNEL_TEMPLATES;
1140
- return this.client.get(endpoint);
1141
- }
1142
- };
1143
-
1144
- // src/lib/errors.ts
1145
- var AppErrorCode = /* @__PURE__ */ ((AppErrorCode2) => {
1146
- AppErrorCode2["VALIDATION_ERROR"] = "VALIDATION_ERROR";
1147
- AppErrorCode2["AUTHENTICATION_REQUIRED"] = "AUTHENTICATION_REQUIRED";
1148
- AppErrorCode2["INVALID_CREDENTIALS"] = "INVALID_CREDENTIALS";
1149
- AppErrorCode2["SESSION_EXPIRED"] = "SESSION_EXPIRED";
1150
- AppErrorCode2["FORBIDDEN"] = "FORBIDDEN";
1151
- AppErrorCode2["INSUFFICIENT_PERMISSIONS"] = "INSUFFICIENT_PERMISSIONS";
1152
- AppErrorCode2["NOT_FOUND"] = "NOT_FOUND";
1153
- AppErrorCode2["RESOURCE_NOT_FOUND"] = "RESOURCE_NOT_FOUND";
1154
- AppErrorCode2["CONFLICT"] = "CONFLICT";
1155
- AppErrorCode2["DUPLICATE_RESOURCE"] = "DUPLICATE_RESOURCE";
1156
- AppErrorCode2["RATE_LIMITED"] = "RATE_LIMITED";
1157
- AppErrorCode2["BAD_REQUEST"] = "BAD_REQUEST";
1158
- AppErrorCode2["INTERNAL_ERROR"] = "INTERNAL_ERROR";
1159
- AppErrorCode2["DATABASE_ERROR"] = "DATABASE_ERROR";
1160
- AppErrorCode2["EXTERNAL_SERVICE_ERROR"] = "EXTERNAL_SERVICE_ERROR";
1161
- AppErrorCode2["SERVICE_UNAVAILABLE"] = "SERVICE_UNAVAILABLE";
1162
- return AppErrorCode2;
1163
- })(AppErrorCode || {});
1164
- var AppError = class _AppError extends Error {
1165
- constructor(message, code = "INTERNAL_ERROR" /* INTERNAL_ERROR */, statusCode = 500, details, isOperational = true) {
1166
- super(message);
1167
- this.name = "AppError";
1168
- this.code = code;
1169
- this.statusCode = statusCode;
1170
- this.details = details;
1171
- this.isOperational = isOperational;
1172
- Error.captureStackTrace(this, this.constructor);
1173
- }
1174
- /**
1175
- * Serialize error for API response
1176
- */
1177
- toResponse() {
1178
- return {
1179
- error: {
1180
- code: this.code,
1181
- message: this.message,
1182
- ...this.details && { details: this.details }
1183
- }
1184
- };
1185
- }
1186
- /**
1187
- * Check if an error is an operational error (expected) vs programming error
1188
- */
1189
- static isOperationalError(error) {
1190
- return error instanceof _AppError && error.isOperational;
1191
- }
1192
- };
1193
- var ValidationError = class _ValidationError extends AppError {
1194
- constructor(message = "Validation failed", fieldErrors = {}) {
1195
- super(
1196
- message,
1197
- "VALIDATION_ERROR" /* VALIDATION_ERROR */,
1198
- 400,
1199
- { fields: fieldErrors }
1200
- );
1201
- this.name = "ValidationError";
1202
- this.fieldErrors = fieldErrors;
1203
- }
1204
- /**
1205
- * Create from Zod error
1206
- */
1207
- static fromZodError(zodError) {
1208
- const fieldErrors = {};
1209
- for (const error of zodError.errors) {
1210
- const path = error.path.join(".");
1211
- if (!fieldErrors[path]) {
1212
- fieldErrors[path] = [];
1213
- }
1214
- fieldErrors[path].push(error.message);
1215
- }
1216
- const message = Object.entries(fieldErrors).map(([field, errors]) => `${field}: ${errors.join(", ")}`).join("; ");
1217
- return new _ValidationError(`Validation failed: ${message}`, fieldErrors);
1218
- }
1219
- };
1220
- var AuthenticationError = class _AuthenticationError extends AppError {
1221
- constructor(message = "Authentication required", code = "AUTHENTICATION_REQUIRED" /* AUTHENTICATION_REQUIRED */) {
1222
- super(message, code, 401);
1223
- this.name = "AuthenticationError";
1224
- }
1225
- /**
1226
- * Create for invalid credentials
1227
- */
1228
- static invalidCredentials() {
1229
- return new _AuthenticationError("Invalid credentials", "INVALID_CREDENTIALS" /* INVALID_CREDENTIALS */);
1230
- }
1231
- /**
1232
- * Create for expired session
1233
- */
1234
- static sessionExpired() {
1235
- return new _AuthenticationError("Session has expired", "SESSION_EXPIRED" /* SESSION_EXPIRED */);
1236
- }
1237
- };
1238
- var AuthorizationError = class _AuthorizationError extends AppError {
1239
- constructor(message = "Access denied", code = "FORBIDDEN" /* FORBIDDEN */) {
1240
- super(message, code, 403);
1241
- this.name = "AuthorizationError";
1242
- }
1243
- /**
1244
- * Create for insufficient permissions
1245
- */
1246
- static insufficientPermissions(requiredPermission) {
1247
- const message = requiredPermission ? `Insufficient permissions. Required: ${requiredPermission}` : "Insufficient permissions";
1248
- return new _AuthorizationError(message, "INSUFFICIENT_PERMISSIONS" /* INSUFFICIENT_PERMISSIONS */);
1249
- }
1250
- };
1251
- var NotFoundError = class _NotFoundError extends AppError {
1252
- constructor(message = "Resource not found", resourceType, resourceId) {
1253
- super(
1254
- message,
1255
- "NOT_FOUND" /* NOT_FOUND */,
1256
- 404,
1257
- resourceType || resourceId ? { resourceType, resourceId } : void 0
1258
- );
1259
- this.name = "NotFoundError";
1260
- this.resourceType = resourceType;
1261
- this.resourceId = resourceId;
1262
- }
1263
- /**
1264
- * Create for a specific resource
1265
- */
1266
- static forResource(resourceType, resourceId) {
1267
- const message = resourceId ? `${resourceType} with ID '${resourceId}' not found` : `${resourceType} not found`;
1268
- return new _NotFoundError(message, resourceType, resourceId);
1269
- }
1270
- };
1271
- var ConflictError = class _ConflictError extends AppError {
1272
- constructor(message = "Resource conflict", conflictingField) {
1273
- super(
1274
- message,
1275
- "CONFLICT" /* CONFLICT */,
1276
- 409,
1277
- conflictingField ? { field: conflictingField } : void 0
1278
- );
1279
- this.name = "ConflictError";
1280
- this.conflictingField = conflictingField;
1281
- }
1282
- /**
1283
- * Create for duplicate resource
1284
- */
1285
- static duplicate(resourceType, field) {
1286
- const message = field ? `A ${resourceType} with this ${field} already exists` : `A ${resourceType} with these values already exists`;
1287
- return new _ConflictError(message, field);
1288
- }
1289
- };
1290
- var RateLimitError = class extends AppError {
1291
- constructor(message = "Too many requests", retryAfter) {
1292
- super(
1293
- message,
1294
- "RATE_LIMITED" /* RATE_LIMITED */,
1295
- 429,
1296
- retryAfter ? { retryAfter } : void 0
1297
- );
1298
- this.name = "RateLimitError";
1299
- this.retryAfter = retryAfter;
1300
- }
1301
- };
1302
- var DatabaseError = class _DatabaseError extends AppError {
1303
- constructor(message = "Database operation failed", details) {
1304
- const safeDetails = process.env.NODE_ENV === "development" ? details : void 0;
1305
- super(message, "DATABASE_ERROR" /* DATABASE_ERROR */, 500, safeDetails);
1306
- this.name = "DatabaseError";
1307
- }
1308
- /**
1309
- * Create from Prisma error
1310
- */
1311
- static fromPrismaError(error) {
1312
- const code = error.code;
1313
- switch (code) {
1314
- case "P2002":
1315
- throw ConflictError.duplicate("record", error.meta?.target?.[0]);
1316
- case "P2025":
1317
- throw new NotFoundError("Record not found");
1318
- case "P2003":
1319
- throw new ConflictError("Cannot perform operation due to related records");
1320
- default:
1321
- return new _DatabaseError("Database operation failed", { code });
1322
- }
1323
- }
1324
- };
1325
- var ExternalServiceError = class extends AppError {
1326
- constructor(serviceName, message = "External service error", details) {
1327
- super(
1328
- message,
1329
- "EXTERNAL_SERVICE_ERROR" /* EXTERNAL_SERVICE_ERROR */,
1330
- 502,
1331
- { service: serviceName, ...details }
1332
- );
1333
- this.name = "ExternalServiceError";
1334
- this.serviceName = serviceName;
1335
- }
1336
- };
1337
- function isPrismaError(error) {
1338
- return typeof error === "object" && error !== null && "code" in error && typeof error.code === "string";
1339
- }
1340
- function toAppError(error) {
1341
- if (error instanceof AppError) {
1342
- return error;
1343
- }
1344
- if (isPrismaError(error)) {
1345
- return DatabaseError.fromPrismaError(error);
1346
- }
1347
- if (error instanceof Error) {
1348
- return new AppError(
1349
- error.message,
1350
- "INTERNAL_ERROR" /* INTERNAL_ERROR */,
1351
- 500,
1352
- process.env.NODE_ENV === "development" ? { stack: error.stack } : void 0
1353
- );
1354
- }
1355
- return new AppError(
1356
- "An unexpected error occurred",
1357
- "INTERNAL_ERROR" /* INTERNAL_ERROR */,
1358
- 500
1359
- );
1360
- }
1361
- function sanitizeHtml(input) {
1362
- return DOMPurify.sanitize(input, {
1363
- ALLOWED_TAGS: ["b", "i", "em", "strong", "a", "p", "br"],
1364
- ALLOWED_ATTR: ["href"],
1365
- ALLOW_DATA_ATTR: false
1366
- });
1367
- }
1368
- function sanitizeSearchQuery(query) {
1369
- if (!query || typeof query !== "string") {
1370
- return "";
1371
- }
1372
- return query.trim().replace(/[.*+?^${}()|[\]\\]/g, "\\$&").substring(0, 100);
1373
- }
1374
- function validateIdentifier(input) {
1375
- return /^[a-zA-Z0-9_-]+$/.test(input);
1376
- }
1377
-
1378
- // src/lib/llm-sanitize.ts
1379
- var MAX_PROMPT_LENGTH = 2e3;
1380
- var MAX_CHAT_MESSAGE_LENGTH = 1e3;
1381
- var INJECTION_PATTERNS = [
1382
- // System/role injection attempts
1383
- /\bSYSTEM\s*:/gi,
1384
- /\bASSISTANT\s*:/gi,
1385
- /\bUSER\s*:/gi,
1386
- /\bHUMAN\s*:/gi,
1387
- /\bAI\s*:/gi,
1388
- // Instruction override attempts
1389
- /\bignore\s+(previous|above|all)\s+instructions?\b/gi,
1390
- /\bdisregard\s+(previous|above|all)\s+instructions?\b/gi,
1391
- /\bforget\s+(previous|above|all)\s+instructions?\b/gi,
1392
- /\bnew\s+instructions?\s*:/gi,
1393
- /\boverride\s*:/gi,
1394
- // Role-playing attempts
1395
- /\byou\s+are\s+now\b/gi,
1396
- /\bact\s+as\s+(if|a|an|the)\b/gi,
1397
- /\bpretend\s+(to\s+be|you\s+are)\b/gi,
1398
- // JSON/schema manipulation
1399
- /\b(output|respond|return)\s+only\s*:/gi,
1400
- /\bformat\s*:\s*json\b/gi
1401
- ];
1402
- var FORMATTING_MARKERS = [
1403
- "```",
1404
- // Code blocks
1405
- "---",
1406
- // Horizontal rules (when at line start)
1407
- "***",
1408
- // Alternative horizontal rules
1409
- "##",
1410
- // Headers (when at line start)
1411
- ">>"
1412
- // Potential quote injection
1413
- ];
1414
- var CONTROL_CHAR_REGEX = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g;
1415
- function sanitizeUserInput(input, maxLength = MAX_PROMPT_LENGTH) {
1416
- if (!input || typeof input !== "string") {
1417
- return "";
1418
- }
1419
- let sanitized = input;
1420
- sanitized = sanitized.replace(CONTROL_CHAR_REGEX, "");
1421
- sanitized = sanitized.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\n{3,}/g, "\n\n").replace(/[ \t]{3,}/g, " ").trim();
1422
- for (const pattern of INJECTION_PATTERNS) {
1423
- sanitized = sanitized.replace(pattern, (match) => {
1424
- return `[${match.replace(/:/g, "")}]`;
1425
- });
1426
- }
1427
- for (const marker of FORMATTING_MARKERS) {
1428
- const escapeRegex = new RegExp(`(^|\\n)(${escapeRegexChars(marker)})`, "g");
1429
- sanitized = sanitized.replace(escapeRegex, (_, prefix, match) => {
1430
- return `${prefix}[${match}]`;
1431
- });
1432
- }
1433
- if (sanitized.length > maxLength) {
1434
- sanitized = truncateAtWordBoundary(sanitized, maxLength);
1435
- }
1436
- return sanitized;
1437
- }
1438
- function sanitizeChatMessage(input) {
1439
- return sanitizeUserInput(input, MAX_CHAT_MESSAGE_LENGTH);
1440
- }
1441
- function truncateAtWordBoundary(text, maxLength) {
1442
- if (text.length <= maxLength) {
1443
- return text;
1444
- }
1445
- const truncated = text.slice(0, maxLength);
1446
- const lastSpace = truncated.lastIndexOf(" ");
1447
- if (lastSpace > maxLength * 0.8) {
1448
- return truncated.slice(0, lastSpace).trim();
1449
- }
1450
- return truncated.trim();
1451
- }
1452
- function escapeRegexChars(str) {
1453
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1454
- }
1455
-
1456
- // src/lib/cors.ts
1457
- var DEFAULT_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"];
1458
- var DEFAULT_HEADERS = ["Content-Type", "Authorization", "X-Requested-With", "Accept", "X-CSRF-Token"];
1459
- function isAllowed(origin, options) {
1460
- if (!origin) return false;
1461
- if (options.origins === "*") return true;
1462
- return options.origins.includes(origin);
1463
- }
1464
- function getCorsHeaders(origin, options) {
1465
- if (!isAllowed(origin, options)) {
1466
- return {};
1467
- }
1468
- const methods = options.methods ?? DEFAULT_METHODS;
1469
- const headers = options.headers ?? DEFAULT_HEADERS;
1470
- const credentials = options.credentials ?? options.origins !== "*";
1471
- const maxAge = options.maxAge ?? 86400;
1472
- const result = {
1473
- "Access-Control-Allow-Origin": options.origins === "*" ? "*" : origin,
1474
- "Access-Control-Allow-Methods": methods.join(", "),
1475
- "Access-Control-Allow-Headers": headers.join(", "),
1476
- "Access-Control-Max-Age": String(maxAge)
1477
- };
1478
- if (credentials && options.origins !== "*") {
1479
- result["Access-Control-Allow-Credentials"] = "true";
1480
- }
1481
- return result;
1482
- }
1483
- function applyCorsHeaders(responseHeaders, origin, options) {
1484
- const corsHeaders = getCorsHeaders(origin, options);
1485
- for (const [key, value] of Object.entries(corsHeaders)) {
1486
- responseHeaders.set(key, value);
1487
- }
1488
- }
1489
- function createCorsMiddleware(options) {
1490
- return function corsMiddleware(request) {
1491
- const origin = request.headers.get("origin");
1492
- if (request.method === "OPTIONS") {
1493
- const corsHeaders = getCorsHeaders(origin, options);
1494
- return new Response(null, { status: 204, headers: corsHeaders });
1495
- }
1496
- return null;
1497
- };
1498
- }
1499
-
1500
- // src/types/response.ts
1501
- var ErrorCodes = /* @__PURE__ */ ((ErrorCodes2) => {
1502
- ErrorCodes2["UNAUTHORIZED"] = "UNAUTHORIZED";
1503
- ErrorCodes2["FORBIDDEN"] = "FORBIDDEN";
1504
- ErrorCodes2["NOT_FOUND"] = "NOT_FOUND";
1505
- ErrorCodes2["VALIDATION_ERROR"] = "VALIDATION_ERROR";
1506
- ErrorCodes2["CONFLICT"] = "CONFLICT";
1507
- ErrorCodes2["INTERNAL_ERROR"] = "INTERNAL_ERROR";
1508
- ErrorCodes2["SERVICE_UNAVAILABLE"] = "SERVICE_UNAVAILABLE";
1509
- ErrorCodes2["RATE_LIMITED"] = "RATE_LIMITED";
1510
- return ErrorCodes2;
1511
- })(ErrorCodes || {});
1512
- var FieldErrorSchema = z.object({
1513
- field: z.string(),
1514
- messages: z.array(z.string()),
1515
- code: z.string().optional()
1516
- });
1517
- var StandardErrorResponseSchema = z.object({
1518
- error: z.string(),
1519
- code: z.string(),
1520
- statusCode: z.number().int().min(400).max(599),
1521
- fieldErrors: z.array(FieldErrorSchema).optional(),
1522
- details: z.record(z.unknown()).optional(),
1523
- requestId: z.string().optional(),
1524
- timestamp: z.string().datetime().optional()
1525
- });
1526
- var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
1527
- ErrorCode2["BAD_REQUEST"] = "bad_request";
1528
- ErrorCode2["UNAUTHORIZED"] = "unauthorized";
1529
- ErrorCode2["FORBIDDEN"] = "forbidden";
1530
- ErrorCode2["NOT_FOUND"] = "not_found";
1531
- ErrorCode2["METHOD_NOT_ALLOWED"] = "method_not_allowed";
1532
- ErrorCode2["VALIDATION_ERROR"] = "validation_error";
1533
- ErrorCode2["CONFLICT"] = "conflict";
1534
- ErrorCode2["RATE_LIMITED"] = "rate_limited";
1535
- ErrorCode2["INTERNAL_ERROR"] = "internal_error";
1536
- ErrorCode2["SERVICE_UNAVAILABLE"] = "service_unavailable";
1537
- ErrorCode2["GATEWAY_TIMEOUT"] = "gateway_timeout";
1538
- ErrorCode2["NETWORK_ERROR"] = "network_error";
1539
- ErrorCode2["TIMEOUT"] = "timeout";
1540
- ErrorCode2["UNKNOWN"] = "unknown";
1541
- return ErrorCode2;
1542
- })(ErrorCode || {});
1543
- function getErrorCodeFromStatus(status) {
1544
- const codeMap = {
1545
- 400: "bad_request" /* BAD_REQUEST */,
1546
- 401: "unauthorized" /* UNAUTHORIZED */,
1547
- 403: "forbidden" /* FORBIDDEN */,
1548
- 404: "not_found" /* NOT_FOUND */,
1549
- 405: "method_not_allowed" /* METHOD_NOT_ALLOWED */,
1550
- 409: "conflict" /* CONFLICT */,
1551
- 422: "validation_error" /* VALIDATION_ERROR */,
1552
- 429: "rate_limited" /* RATE_LIMITED */,
1553
- 500: "internal_error" /* INTERNAL_ERROR */,
1554
- 503: "service_unavailable" /* SERVICE_UNAVAILABLE */,
1555
- 504: "gateway_timeout" /* GATEWAY_TIMEOUT */
1556
- };
1557
- return codeMap[status] || "unknown" /* UNKNOWN */;
1558
- }
1559
- var ErrorMessages = {
1560
- ["bad_request" /* BAD_REQUEST */]: "The request was invalid. Please check your input.",
1561
- ["unauthorized" /* UNAUTHORIZED */]: "You need to log in to access this resource.",
1562
- ["forbidden" /* FORBIDDEN */]: "You don't have permission to access this resource.",
1563
- ["not_found" /* NOT_FOUND */]: "The requested resource was not found.",
1564
- ["method_not_allowed" /* METHOD_NOT_ALLOWED */]: "This operation is not allowed.",
1565
- ["validation_error" /* VALIDATION_ERROR */]: "Please fix the errors in your form.",
1566
- ["conflict" /* CONFLICT */]: "This operation conflicts with existing data.",
1567
- ["rate_limited" /* RATE_LIMITED */]: "Too many requests. Please slow down.",
1568
- ["internal_error" /* INTERNAL_ERROR */]: "An unexpected error occurred. Please try again.",
1569
- ["service_unavailable" /* SERVICE_UNAVAILABLE */]: "The service is temporarily unavailable.",
1570
- ["gateway_timeout" /* GATEWAY_TIMEOUT */]: "The request took too long. Please try again.",
1571
- ["network_error" /* NETWORK_ERROR */]: "Network error. Please check your connection.",
1572
- ["timeout" /* TIMEOUT */]: "The request timed out. Please try again.",
1573
- ["unknown" /* UNKNOWN */]: "An unknown error occurred."
1574
- };
1575
-
1576
- // src/lib/rate-limit.ts
1577
- var CLEANUP_INTERVAL_MS = 10 * 60 * 1e3;
1578
- function createRateLimiter(options) {
1579
- const { windowMs, maxRequests, keyPrefix = "" } = options;
1580
- const store = /* @__PURE__ */ new Map();
1581
- let lastCleanup = Date.now();
1582
- function cleanup() {
1583
- const now = Date.now();
1584
- if (now - lastCleanup < CLEANUP_INTERVAL_MS) return;
1585
- lastCleanup = now;
1586
- for (const [key, entry] of store.entries()) {
1587
- if (now > entry.resetAt) store.delete(key);
1588
- }
1589
- }
1590
- return function check(key) {
1591
- cleanup();
1592
- const storeKey = keyPrefix ? `${keyPrefix}:${key}` : key;
1593
- const now = Date.now();
1594
- const entry = store.get(storeKey);
1595
- if (!entry || now > entry.resetAt) {
1596
- const resetAt = now + windowMs;
1597
- store.set(storeKey, { count: 1, resetAt });
1598
- return { success: true, remaining: maxRequests - 1, resetAt };
1599
- }
1600
- if (entry.count >= maxRequests) {
1601
- const retryAfter = Math.ceil((entry.resetAt - now) / 1e3);
1602
- return { success: false, remaining: 0, resetAt: entry.resetAt, retryAfter };
1603
- }
1604
- entry.count++;
1605
- return { success: true, remaining: maxRequests - entry.count, resetAt: entry.resetAt };
1606
- };
1607
- }
1608
- function getClientIP(request) {
1609
- const forwarded = request.headers.get("x-forwarded-for");
1610
- if (forwarded) return forwarded.split(",")[0].trim();
1611
- const real = request.headers.get("x-real-ip");
1612
- if (real) return real;
1613
- return "unknown";
1614
- }
1615
-
1616
- // src/lib/cache-store.ts
1617
- var DEFAULT_CONFIG = {
1618
- maxSize: 1e3,
1619
- defaultTTL: 60 * 1e3
1620
- };
1621
- var CacheStore = class {
1622
- constructor(config = {}) {
1623
- this.cache = /* @__PURE__ */ new Map();
1624
- this.hits = 0;
1625
- this.misses = 0;
1626
- this.accessCounter = 0;
1627
- this.config = { ...DEFAULT_CONFIG, ...config };
1628
- }
1629
- get(key) {
1630
- const entry = this.cache.get(key);
1631
- if (!entry) {
1632
- this.misses++;
1633
- return void 0;
1634
- }
1635
- if (Date.now() > entry.expiresAt) {
1636
- this.cache.delete(key);
1637
- this.misses++;
1638
- return void 0;
1639
- }
1640
- entry.accessOrder = ++this.accessCounter;
1641
- this.hits++;
1642
- return entry.value;
1643
- }
1644
- set(key, value, ttl) {
1645
- if (this.cache.size >= this.config.maxSize) this.evictLRU();
1646
- this.cache.set(key, {
1647
- value,
1648
- expiresAt: Date.now() + (ttl ?? this.config.defaultTTL),
1649
- accessOrder: ++this.accessCounter
1650
- });
1651
- }
1652
- has(key) {
1653
- const entry = this.cache.get(key);
1654
- if (!entry) return false;
1655
- if (Date.now() > entry.expiresAt) {
1656
- this.cache.delete(key);
1657
- return false;
1658
- }
1659
- return true;
1660
- }
1661
- delete(key) {
1662
- return this.cache.delete(key);
1663
- }
1664
- /** Delete all keys matching a string prefix or RegExp pattern */
1665
- deletePattern(pattern) {
1666
- const regex = typeof pattern === "string" ? new RegExp(pattern) : pattern;
1667
- let deleted = 0;
1668
- for (const key of this.cache.keys()) {
1669
- if (regex.test(key)) {
1670
- this.cache.delete(key);
1671
- deleted++;
1672
- }
1673
- }
1674
- return deleted;
1675
- }
1676
- clear() {
1677
- this.cache.clear();
1678
- this.hits = 0;
1679
- this.misses = 0;
1680
- this.accessCounter = 0;
1681
- }
1682
- /** Remove expired entries and return count removed */
1683
- cleanup() {
1684
- const now = Date.now();
1685
- let removed = 0;
1686
- for (const [key, entry] of this.cache.entries()) {
1687
- if (now > entry.expiresAt) {
1688
- this.cache.delete(key);
1689
- removed++;
1690
- }
1691
- }
1692
- return removed;
1693
- }
1694
- getStats() {
1695
- const total = this.hits + this.misses;
1696
- return {
1697
- size: this.cache.size,
1698
- maxSize: this.config.maxSize,
1699
- hits: this.hits,
1700
- misses: this.misses,
1701
- hitRate: total > 0 ? this.hits / total : 0
1702
- };
1703
- }
1704
- evictLRU() {
1705
- let oldestKey = null;
1706
- let oldestOrder = Infinity;
1707
- for (const [key, entry] of this.cache.entries()) {
1708
- if (entry.accessOrder < oldestOrder) {
1709
- oldestOrder = entry.accessOrder;
1710
- oldestKey = key;
1711
- }
1712
- }
1713
- if (oldestKey) this.cache.delete(oldestKey);
1714
- }
1715
- };
1716
-
1717
- // src/lib/cache-manager.ts
1718
- var DEFAULT_CONFIG2 = {
1719
- entity: { maxSize: 500, defaultTTL: 5 * 60 * 1e3 },
1720
- query: { maxSize: 200, defaultTTL: 60 * 1e3 }
1721
- };
1722
- var CacheManager = class {
1723
- constructor(enabled = true, config = {}) {
1724
- this.entity = new CacheStore({ ...DEFAULT_CONFIG2.entity, ...config.entity });
1725
- this.query = new CacheStore({ ...DEFAULT_CONFIG2.query, ...config.query });
1726
- this.enabled = enabled;
1727
- }
1728
- /**
1729
- * Cache-aside: return the cached value if present, otherwise call fetchFn,
1730
- * store the result, and return it.
1731
- */
1732
- async getOrSet(key, ttlMs, fetchFn) {
1733
- if (this.enabled) {
1734
- const cached = this.query.get(key);
1735
- if (cached !== void 0) return cached;
1736
- }
1737
- const value = await fetchFn();
1738
- if (this.enabled) this.query.set(key, value, ttlMs);
1739
- return value;
1740
- }
1741
- /** Invalidate a specific key in the query cache */
1742
- invalidateKey(key) {
1743
- this.query.delete(key);
1744
- }
1745
- /** Invalidate all query cache keys matching a string prefix or RegExp */
1746
- invalidatePattern(pattern) {
1747
- this.query.deletePattern(pattern);
1748
- }
1749
- /** Invalidate all entity and query cache entries for the given prefix */
1750
- invalidateAll(prefix) {
1751
- this.entity.deletePattern(prefix);
1752
- this.query.deletePattern(prefix);
1753
- }
1754
- setEnabled(enabled) {
1755
- this.enabled = enabled;
1756
- }
1757
- isEnabled() {
1758
- return this.enabled;
1759
- }
1760
- /** Remove expired entries from both stores */
1761
- maintenance() {
1762
- return {
1763
- entityRemoved: this.entity.cleanup(),
1764
- queryRemoved: this.query.cleanup()
1765
- };
1766
- }
1767
- clear() {
1768
- this.entity.clear();
1769
- this.query.clear();
1770
- }
1771
- getStats() {
1772
- return { entity: this.entity.getStats(), query: this.query.getStats() };
1773
- }
1774
- };
1775
- var _cacheManager = null;
1776
- function getCacheManager(config) {
1777
- if (!_cacheManager) _cacheManager = new CacheManager(true, config);
1778
- return _cacheManager;
1779
- }
1780
- function resetCacheManager() {
1781
- _cacheManager?.clear();
1782
- _cacheManager = null;
1783
- }
1784
-
1785
- // src/constants/options.ts
1786
- var COMPANY_SIZE_OPTIONS = [
1787
- { value: "startup", label: "Startup (1-10)" },
1788
- { value: "small", label: "Small (11-50)" },
1789
- { value: "smb", label: "SMB (51-200)" },
1790
- { value: "mid_market", label: "Mid-Market (201-1000)" },
1791
- { value: "enterprise", label: "Enterprise (1000+)" }
1792
- ];
1793
- var LIFECYCLE_STAGE_OPTIONS = [
1794
- { value: "subscriber", label: "Subscriber" },
1795
- { value: "lead", label: "Lead" },
1796
- { value: "mql", label: "MQL" },
1797
- { value: "sql", label: "SQL" },
1798
- { value: "opportunity", label: "Opportunity" },
1799
- { value: "customer", label: "Customer" },
1800
- { value: "evangelist", label: "Evangelist" }
1801
- ];
1802
- var REVENUE_RANGE_OPTIONS = [
1803
- { value: "pre_revenue", label: "Pre-revenue" },
1804
- { value: "0_1m", label: "$0-$1M" },
1805
- { value: "1m_10m", label: "$1M-$10M" },
1806
- { value: "10m_50m", label: "$10M-$50M" },
1807
- { value: "50m_plus", label: "$50M+" }
1808
- ];
1809
- var ACTIVITY_TYPE_OPTIONS = [
1810
- { value: "call", label: "Call" },
1811
- { value: "email", label: "Email" },
1812
- { value: "meeting", label: "Meeting" },
1813
- { value: "demo", label: "Demo" },
1814
- { value: "note", label: "Note" },
1815
- { value: "task", label: "Task" }
1816
- ];
1817
- var ACTIVITY_OUTCOME_OPTIONS = [
1818
- { value: "scheduled_demo", label: "Scheduled Demo" },
1819
- { value: "scheduled_meeting", label: "Scheduled Meeting" },
1820
- { value: "callback_later", label: "Callback Later" },
1821
- { value: "left_voicemail", label: "Left Voicemail" },
1822
- { value: "no_answer", label: "No Answer" },
1823
- { value: "not_interested", label: "Not Interested" },
1824
- { value: "successful", label: "Successful" },
1825
- { value: "unsuccessful", label: "Unsuccessful" }
1826
- ];
1827
- var LOSS_REASON_OPTIONS = [
1828
- { value: "price", label: "Price / Budget" },
1829
- { value: "timing", label: "Bad Timing" },
1830
- { value: "competitor", label: "Chose Competitor" },
1831
- { value: "no_need", label: "No Need" },
1832
- { value: "no_response", label: "No Response" },
1833
- { value: "other", label: "Other" }
1834
- ];
1835
- var DEAL_STAGE_OPTIONS = [
1836
- { value: "qualification", label: "Qualification" },
1837
- { value: "discovery", label: "Discovery" },
1838
- { value: "demo", label: "Demo" },
1839
- { value: "proposal", label: "Proposal" },
1840
- { value: "negotiation", label: "Negotiation" },
1841
- { value: "closed_won", label: "Closed Won" },
1842
- { value: "closed_lost", label: "Closed Lost" }
1843
- ];
1844
- function useServerList(endpoint, options = {}) {
1845
- const {
1846
- pageSize: initialPageSize = 25,
1847
- initialPage = 1,
1848
- initialSearch = "",
1849
- initialSortField = "",
1850
- initialSortDir = "asc",
1851
- params: extraParams = {},
1852
- disabled = false,
1853
- fetcher = fetch
1854
- } = options;
1855
- const [page, setPage] = useState(initialPage);
1856
- const [pageSize, setPageSize] = useState(initialPageSize);
1857
- const [search, setSearchState] = useState(initialSearch);
1858
- const [sortField, setSortField] = useState(initialSortField);
1859
- const [sortDir, setSortDir] = useState(initialSortDir);
1860
- const [data, setData] = useState([]);
1861
- const [total, setTotal] = useState(0);
1862
- const [loading, setLoading] = useState(!disabled);
1863
- const [error, setError] = useState(null);
1864
- const refreshCountRef = useRef(0);
1865
- const fetchData = useCallback(async () => {
1866
- if (disabled) return;
1867
- setLoading(true);
1868
- setError(null);
1869
- const searchParams = new URLSearchParams();
1870
- searchParams.set("page", String(page));
1871
- searchParams.set("pageSize", String(pageSize));
1872
- if (sortField) {
1873
- searchParams.set("sortField", sortField);
1874
- searchParams.set("sortDirection", sortDir);
1875
- }
1876
- if (search) searchParams.set("search", search);
1877
- for (const [k, v] of Object.entries(extraParams)) {
1878
- searchParams.set(k, String(v));
1879
- }
1880
- const sep = endpoint.includes("?") ? "&" : "?";
1881
- const url = `${endpoint}${sep}${searchParams.toString()}`;
1882
- try {
1883
- const response = await fetcher(url);
1884
- if (!response.ok) {
1885
- throw new Error(`Request failed: ${response.status} ${response.statusText}`);
1886
- }
1887
- const json = await response.json();
1888
- if (Array.isArray(json)) {
1889
- setData(json);
1890
- setTotal(json.length);
1891
- } else if (json.results !== void 0) {
1892
- setData(json.results);
1893
- setTotal(json.count ?? json.results.length);
1894
- } else if (json.data !== void 0) {
1895
- setData(json.data);
1896
- setTotal(json.total ?? json.data.length);
1897
- } else {
1898
- setData([]);
1899
- setTotal(0);
1900
- }
1901
- } catch (err) {
1902
- setError(err instanceof Error ? err.message : "Failed to load data");
1903
- setData([]);
1904
- } finally {
1905
- setLoading(false);
1906
- }
1907
- }, [endpoint, page, pageSize, search, sortField, sortDir, disabled, fetcher, refreshCountRef.current]);
1908
- useEffect(() => {
1909
- fetchData();
1910
- }, [fetchData]);
1911
- const setSearch = useCallback((value) => {
1912
- setPage(1);
1913
- setSearchState(value);
1914
- }, []);
1915
- const setSort = useCallback(
1916
- (field, dir) => {
1917
- if (field === sortField && !dir) {
1918
- setSortDir((prev) => prev === "asc" ? "desc" : "asc");
1919
- } else {
1920
- setSortField(field);
1921
- setSortDir(dir ?? "asc");
1922
- }
1923
- setPage(1);
1924
- },
1925
- [sortField]
1926
- );
1927
- const refresh = useCallback(() => {
1928
- refreshCountRef.current += 1;
1929
- fetchData();
1930
- }, [fetchData]);
1931
- return {
1932
- data,
1933
- total,
1934
- loading,
1935
- error,
1936
- page,
1937
- pageSize,
1938
- search,
1939
- sortField,
1940
- sortDir,
1941
- setPage,
1942
- setPageSize,
1943
- setSearch,
1944
- setSort,
1945
- refresh
1946
- };
1947
- }
1948
- function useServerDetail(endpoint, id, options = {}) {
1949
- const { fetcher = fetch, disabled = false } = options;
1950
- const [data, setData] = useState(null);
1951
- const [loading, setLoading] = useState(!disabled && id !== null && id !== void 0);
1952
- const [error, setError] = useState(null);
1953
- const fetchData = useCallback(async () => {
1954
- if (disabled || id === null) return;
1955
- const url = id !== void 0 ? `${endpoint}${endpoint.endsWith("/") ? "" : "/"}${id}/` : endpoint;
1956
- setLoading(true);
1957
- setError(null);
1958
- try {
1959
- const response = await fetcher(url);
1960
- if (!response.ok) {
1961
- throw new Error(`Request failed: ${response.status} ${response.statusText}`);
1962
- }
1963
- setData(await response.json());
1964
- } catch (err) {
1965
- setError(err instanceof Error ? err.message : "Failed to load data");
1966
- } finally {
1967
- setLoading(false);
1968
- }
1969
- }, [endpoint, id, disabled, fetcher]);
1970
- useEffect(() => {
1971
- fetchData();
1972
- }, [fetchData]);
1973
- return { data, loading, error, refresh: fetchData };
1974
- }
1975
-
1976
- // src/lib/env.ts
1977
- function getRequiredEnv(key) {
1978
- const value = process.env[key];
1979
- if (!value) {
1980
- throw new Error(`Missing required environment variable: ${key}`);
1981
- }
1982
- return value;
1983
- }
1984
- function getOptionalEnv(key, defaultValue) {
1985
- return process.env[key] ?? defaultValue;
1986
- }
1987
- function validateEnvVars(required) {
1988
- const missing = required.filter((key) => !process.env[key]);
1989
- if (missing.length > 0) {
1990
- throw new Error(`Missing required environment variables: ${missing.join(", ")}`);
1991
- }
1992
- }
1993
-
1994
- // src/index.ts
1995
- function createStartSimpliApi(config = {}) {
1996
- const client = createApiClient(config);
1997
- return {
1998
- client,
1999
- contacts: new ContactsApi(client),
2000
- organizations: new OrganizationsApi(client),
2001
- entities: new EntitiesApi(client),
2002
- workflows: new WorkflowsApi(client),
2003
- messages: new MessagesApi(client),
2004
- funnels: new FunnelsApi(client)
2005
- };
2006
- }
2007
-
2008
- export { ACTIVITY_OUTCOME_OPTIONS, ACTIVITY_TYPE_OPTIONS, ApiClient, ApiException, AppError, AppErrorCode, AuthenticationError, AuthorizationError, COMPANY_SIZE_OPTIONS, CacheManager, CacheStore, ConflictError, ContactsApi, DEAL_STAGE_OPTIONS, DatabaseError, ENDPOINTS, EntitiesApi, EntityQueryBuilder, ErrorCode, ErrorCodes, ErrorMessages, ExternalServiceError, FetchWrapper, FieldErrorSchema, FunnelsApi, LIFECYCLE_STAGE_OPTIONS, LOSS_REASON_OPTIONS, MAX_CHAT_MESSAGE_LENGTH, MAX_PROMPT_LENGTH, MessagesApi, NotFoundError, OrganizationsApi, REVENUE_RANGE_OPTIONS, RateLimitError, StandardErrorResponseSchema, ValidationError, WorkflowsApi, applyCorsHeaders, buildFilterParams, buildOrderingParam, buildQueryString, buildUrl, createApiClient, createCorsMiddleware, createRateLimiter, createStartSimpliApi, getCacheManager, getClientIP, getCorsHeaders, getErrorCodeFromStatus, getOptionalEnv, getRequiredEnv, handleFetchError, isApiException, isAuthError, isDRFPaginatedResponse, isFunnelRunConflict, isFunnelValidationError, isNotFoundError, isPrismaError, isValidationError, mergeQueryParams, normalizeId, normalizePaginated, parseErrorResponse, resetCacheManager, resolveApiUrl, sanitizeChatMessage, sanitizeHtml, sanitizeSearchQuery, sanitizeUserInput, toAppError, useServerDetail, useServerList, validateApiResponse, validateEnvVars, validateIdentifier };
2009
- //# sourceMappingURL=index.mjs.map
2010
- //# sourceMappingURL=index.mjs.map