@startsimpli/funnels 0.1.2

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.
Files changed (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +564 -0
  3. package/dist/client-3ESO2NHy.d.ts +310 -0
  4. package/dist/client-CZu03ACp.d.cts +310 -0
  5. package/dist/components/index.cjs +3243 -0
  6. package/dist/components/index.cjs.map +1 -0
  7. package/dist/components/index.css +198 -0
  8. package/dist/components/index.css.map +1 -0
  9. package/dist/components/index.d.cts +726 -0
  10. package/dist/components/index.d.ts +726 -0
  11. package/dist/components/index.js +3196 -0
  12. package/dist/components/index.js.map +1 -0
  13. package/dist/core/index.cjs +500 -0
  14. package/dist/core/index.cjs.map +1 -0
  15. package/dist/core/index.d.cts +359 -0
  16. package/dist/core/index.d.ts +359 -0
  17. package/dist/core/index.js +486 -0
  18. package/dist/core/index.js.map +1 -0
  19. package/dist/hooks/index.cjs +21 -0
  20. package/dist/hooks/index.cjs.map +1 -0
  21. package/dist/hooks/index.d.cts +11 -0
  22. package/dist/hooks/index.d.ts +11 -0
  23. package/dist/hooks/index.js +19 -0
  24. package/dist/hooks/index.js.map +1 -0
  25. package/dist/index-BGDEXbuz.d.cts +434 -0
  26. package/dist/index-BGDEXbuz.d.ts +434 -0
  27. package/dist/index.cjs +4499 -0
  28. package/dist/index.cjs.map +1 -0
  29. package/dist/index.css +198 -0
  30. package/dist/index.css.map +1 -0
  31. package/dist/index.d.cts +99 -0
  32. package/dist/index.d.ts +99 -0
  33. package/dist/index.js +4421 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/store/index.cjs +391 -0
  36. package/dist/store/index.cjs.map +1 -0
  37. package/dist/store/index.d.cts +225 -0
  38. package/dist/store/index.d.ts +225 -0
  39. package/dist/store/index.js +388 -0
  40. package/dist/store/index.js.map +1 -0
  41. package/package.json +122 -0
@@ -0,0 +1,434 @@
1
+ /**
2
+ * @startsimpli/funnels - BRUTALLY GENERIC Funnel Type System
3
+ *
4
+ * This type system works for ANY entity type:
5
+ * - Investors, firms, contacts, organizations
6
+ * - Recipes, ingredients, users
7
+ * - Leads, tasks, projects
8
+ * - GitHub repos, pull requests, issues
9
+ *
10
+ * Zero domain-specific types. All filtering is based on field paths and operators.
11
+ */
12
+ /**
13
+ * Filter operators - works with any data type
14
+ */
15
+ type Operator = 'eq' | 'ne' | 'gt' | 'lt' | 'gte' | 'lte' | 'contains' | 'not_contains' | 'startswith' | 'endswith' | 'matches' | 'in' | 'not_in' | 'has_any' | 'has_all' | 'isnull' | 'isnotnull' | 'has_tag' | 'not_has_tag' | 'is_true' | 'is_false';
16
+ /**
17
+ * Field data types - for operator validation
18
+ */
19
+ type FieldType = 'string' | 'number' | 'boolean' | 'date' | 'array' | 'object' | 'tag' | 'any';
20
+ /**
21
+ * A single filter rule
22
+ *
23
+ * Examples:
24
+ * - { field_path: 'firm.stage', operator: 'eq', value: 'Series A' }
25
+ * - { field_path: 'recipe.cuisine', operator: 'in', value: ['Italian', 'French'] }
26
+ * - { field_path: 'contact.email', operator: 'isnotnull', value: null }
27
+ * - { field_path: 'organization.tags', operator: 'has_tag', value: 'enterprise' }
28
+ */
29
+ interface FilterRule {
30
+ /**
31
+ * Dot-notation path to field
32
+ * Examples: 'name', 'firm.stage', 'profile.linkedin_url', 'tags', 'metrics.arr_usd'
33
+ */
34
+ field_path: string;
35
+ /** Comparison operator */
36
+ operator: Operator;
37
+ /**
38
+ * Value to compare against
39
+ * Type depends on operator:
40
+ * - eq/ne/gt/lt/gte/lte: any primitive
41
+ * - contains/startswith/endswith: string
42
+ * - in/not_in: array
43
+ * - isnull/isnotnull: null (value ignored)
44
+ * - has_tag/not_has_tag: string (tag name)
45
+ */
46
+ value: any;
47
+ /**
48
+ * Optional: negate the rule result
49
+ * Default: false
50
+ */
51
+ negate?: boolean;
52
+ }
53
+ /**
54
+ * Filter logic for combining rules
55
+ */
56
+ type FilterLogic = 'AND' | 'OR';
57
+ /**
58
+ * Action to take when stage rules match
59
+ */
60
+ type MatchAction = 'continue' | 'tag' | 'tag_continue' | 'output';
61
+ /**
62
+ * Action to take when stage rules don't match
63
+ */
64
+ type NoMatchAction = 'continue' | 'exclude' | 'tag_exclude';
65
+ /**
66
+ * A single stage in a funnel
67
+ *
68
+ * Generic over entity type TEntity
69
+ */
70
+ interface FunnelStage<TEntity = any> {
71
+ /** Unique stage identifier */
72
+ id: string;
73
+ /** Stage execution order (0-indexed) */
74
+ order: number;
75
+ /** Human-readable stage name */
76
+ name: string;
77
+ /** Optional description */
78
+ description?: string;
79
+ /**
80
+ * How to combine filter rules
81
+ * - AND: All rules must match
82
+ * - OR: At least one rule must match
83
+ */
84
+ filter_logic: FilterLogic;
85
+ /** Filter rules to evaluate */
86
+ rules: FilterRule[];
87
+ /** Action when rules match */
88
+ match_action: MatchAction;
89
+ /** Action when rules don't match */
90
+ no_match_action: NoMatchAction;
91
+ /** Tags to add when rules match */
92
+ match_tags?: string[];
93
+ /** Tags to add when rules don't match */
94
+ no_match_tags?: string[];
95
+ /**
96
+ * Context to add to entity when rules match
97
+ * Can be used to track why entity matched
98
+ * Examples:
99
+ * - { stage: 'qualified_leads', reason: 'high_fit_score' }
100
+ * - { tier: 'premium', discount: 0.2 }
101
+ */
102
+ match_context?: Record<string, any>;
103
+ /**
104
+ * Optional: Custom evaluation function
105
+ * For complex logic that can't be expressed with rules
106
+ */
107
+ custom_evaluator?: (entity: TEntity) => boolean;
108
+ }
109
+ /**
110
+ * Funnel status
111
+ */
112
+ type FunnelStatus = 'draft' | 'active' | 'paused' | 'archived';
113
+ /**
114
+ * Input entity types
115
+ */
116
+ type InputType = 'contacts' | 'organizations' | 'both' | 'any';
117
+ /**
118
+ * A complete funnel definition
119
+ *
120
+ * Generic over entity type TEntity
121
+ */
122
+ interface Funnel<TEntity = any> {
123
+ /** Unique funnel identifier */
124
+ id: string;
125
+ /** Human-readable funnel name */
126
+ name: string;
127
+ /** Optional description */
128
+ description?: string;
129
+ /** Funnel status */
130
+ status: FunnelStatus;
131
+ /**
132
+ * Type of entities this funnel processes
133
+ * Used for field registry lookup
134
+ */
135
+ input_type: InputType;
136
+ /** Ordered stages */
137
+ stages: FunnelStage<TEntity>[];
138
+ /** Created timestamp */
139
+ created_at: Date | string;
140
+ /** Last updated timestamp */
141
+ updated_at: Date | string;
142
+ /** Owner user ID */
143
+ owner_id?: string;
144
+ /** Team/company ID for multi-tenancy */
145
+ team_id?: string;
146
+ /**
147
+ * Optional: Tags to automatically add to all entities
148
+ * that complete the funnel
149
+ */
150
+ completion_tags?: string[];
151
+ /**
152
+ * Optional: Metadata for custom integrations
153
+ */
154
+ metadata?: Record<string, any>;
155
+ }
156
+ /**
157
+ * Funnel run status
158
+ */
159
+ type FunnelRunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
160
+ /**
161
+ * How the funnel run was triggered
162
+ */
163
+ type TriggerType = 'manual' | 'scheduled' | 'webhook' | 'api';
164
+ /**
165
+ * Statistics for a single stage execution
166
+ */
167
+ interface StageStats {
168
+ /** Stage ID */
169
+ stage_id: string;
170
+ /** Stage name */
171
+ stage_name: string;
172
+ /** Entities that entered this stage */
173
+ input_count: number;
174
+ /** Entities that matched rules */
175
+ matched_count: number;
176
+ /** Entities that didn't match rules */
177
+ not_matched_count: number;
178
+ /** Entities excluded at this stage */
179
+ excluded_count: number;
180
+ /** Entities tagged at this stage */
181
+ tagged_count: number;
182
+ /** Entities that continued to next stage */
183
+ continued_count: number;
184
+ /** Execution time in milliseconds */
185
+ duration_ms?: number;
186
+ /** Error count */
187
+ error_count?: number;
188
+ }
189
+ /**
190
+ * A funnel execution run
191
+ */
192
+ interface FunnelRun {
193
+ /** Unique run identifier */
194
+ id: string;
195
+ /** Funnel ID */
196
+ funnel_id: string;
197
+ /** Funnel snapshot (copy of funnel at run time) */
198
+ funnel?: Funnel;
199
+ /** Run status */
200
+ status: FunnelRunStatus;
201
+ /** How run was triggered */
202
+ trigger_type: TriggerType;
203
+ /** User who triggered (if manual) */
204
+ triggered_by?: string;
205
+ /** Started timestamp */
206
+ started_at: Date | string;
207
+ /** Completed timestamp */
208
+ completed_at?: Date | string;
209
+ /** Duration in milliseconds */
210
+ duration_ms?: number;
211
+ /** Total entities input */
212
+ total_input: number;
213
+ /** Total entities matched (in output) */
214
+ total_matched: number;
215
+ /** Total entities excluded */
216
+ total_excluded: number;
217
+ /** Total entities tagged */
218
+ total_tagged: number;
219
+ /** Per-stage statistics */
220
+ stage_stats: Record<string, StageStats>;
221
+ /** Error message (if failed) */
222
+ error?: string;
223
+ /** Stack trace (if failed) */
224
+ stack_trace?: string;
225
+ /** Metadata */
226
+ metadata?: Record<string, any>;
227
+ }
228
+ /**
229
+ * Result for a single entity processed through funnel
230
+ */
231
+ interface FunnelResult<TEntity = any> {
232
+ /** The entity that was processed */
233
+ entity: TEntity;
234
+ /** Whether entity matched and is in output */
235
+ matched: boolean;
236
+ /** Stage where entity was excluded (if excluded) */
237
+ excluded_at_stage?: string;
238
+ /** Tags accumulated during processing */
239
+ accumulated_tags: string[];
240
+ /** Context accumulated during processing */
241
+ context: Record<string, any>;
242
+ /** Stage-by-stage results */
243
+ stage_results?: StageResult[];
244
+ }
245
+ /**
246
+ * Result for a single stage evaluation
247
+ */
248
+ interface StageResult {
249
+ /** Stage ID */
250
+ stage_id: string;
251
+ /** Stage name */
252
+ stage_name: string;
253
+ /** Whether rules matched */
254
+ matched: boolean;
255
+ /** Rule evaluation results */
256
+ rule_results?: RuleResult[];
257
+ /** Action taken */
258
+ action: MatchAction | NoMatchAction;
259
+ /** Tags added */
260
+ tags_added?: string[];
261
+ /** Context added */
262
+ context_added?: Record<string, any>;
263
+ /** Whether entity was excluded */
264
+ excluded: boolean;
265
+ /** Whether entity continued to next stage */
266
+ continued: boolean;
267
+ }
268
+ /**
269
+ * Result for a single rule evaluation
270
+ */
271
+ interface RuleResult {
272
+ /** Rule field path */
273
+ field_path: string;
274
+ /** Rule operator */
275
+ operator: Operator;
276
+ /** Value compared against */
277
+ value: any;
278
+ /** Actual value from entity */
279
+ actual_value: any;
280
+ /** Whether rule matched */
281
+ matched: boolean;
282
+ /** Error (if evaluation failed) */
283
+ error?: string;
284
+ }
285
+ /**
286
+ * Valid operators for a field type
287
+ */
288
+ type ValidOperators = Operator[];
289
+ /**
290
+ * Field constraints
291
+ */
292
+ interface FieldConstraints {
293
+ /** Minimum value (numbers, dates) */
294
+ min_value?: number | string;
295
+ /** Maximum value (numbers, dates) */
296
+ max_value?: number | string;
297
+ /** Allowed values (enums) */
298
+ choices?: any[];
299
+ /** Regex pattern */
300
+ pattern?: string;
301
+ /** Required field */
302
+ required?: boolean;
303
+ }
304
+ /**
305
+ * Field definition in registry
306
+ *
307
+ * Describes what fields are available for filtering
308
+ * on a given entity type
309
+ */
310
+ interface FieldDefinition {
311
+ /** Unique field identifier (dot-notation path) */
312
+ name: string;
313
+ /** Human-readable label */
314
+ label: string;
315
+ /** Field data type */
316
+ type: FieldType;
317
+ /** Valid operators for this field */
318
+ operators: ValidOperators;
319
+ /** Field category (for UI grouping) */
320
+ category?: string;
321
+ /** Optional description */
322
+ description?: string;
323
+ /** Field constraints */
324
+ constraints?: FieldConstraints;
325
+ /** Whether field is sortable */
326
+ sortable?: boolean;
327
+ /** Whether field is searchable */
328
+ searchable?: boolean;
329
+ /** Example values (for UI help) */
330
+ examples?: any[];
331
+ /** Related fields (for UI suggestions) */
332
+ related_fields?: string[];
333
+ }
334
+ /**
335
+ * Field registry for an entity type
336
+ *
337
+ * Maps field paths to their definitions
338
+ */
339
+ interface FieldRegistry {
340
+ /** Entity type this registry is for */
341
+ entity_type: string;
342
+ /** Available fields */
343
+ fields: FieldDefinition[];
344
+ /** Field lookup by name */
345
+ field_map?: Map<string, FieldDefinition>;
346
+ /** Categories (for UI grouping) */
347
+ categories?: string[];
348
+ }
349
+ /**
350
+ * Filter configuration (rules + logic)
351
+ */
352
+ interface FilterConfig {
353
+ logic: FilterLogic;
354
+ rules: FilterRule[];
355
+ }
356
+ /**
357
+ * Partial type helper
358
+ */
359
+ type DeepPartial<T> = {
360
+ [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
361
+ };
362
+ /**
363
+ * Extract field paths from object type
364
+ * Helper for type-safe field path completion
365
+ */
366
+ type FieldPath<T, Prefix extends string = ''> = {
367
+ [K in keyof T]: T[K] extends object ? K extends string ? `${Prefix}${K}` | FieldPath<T[K], `${Prefix}${K}.`> : never : K extends string ? `${Prefix}${K}` : never;
368
+ }[keyof T];
369
+ /**
370
+ * Funnel creation input (omits auto-generated fields)
371
+ */
372
+ type CreateFunnelInput<TEntity = any> = Omit<Funnel<TEntity>, 'id' | 'created_at' | 'updated_at'>;
373
+ /**
374
+ * Funnel update input (all fields optional except id)
375
+ */
376
+ type UpdateFunnelInput<TEntity = any> = DeepPartial<Funnel<TEntity>> & {
377
+ id: string;
378
+ };
379
+ /**
380
+ * Stage creation input
381
+ */
382
+ type CreateStageInput<TEntity = any> = Omit<FunnelStage<TEntity>, 'id'>;
383
+ /**
384
+ * Stage update input
385
+ */
386
+ type UpdateStageInput<TEntity = any> = DeepPartial<FunnelStage<TEntity>> & {
387
+ id: string;
388
+ };
389
+ /**
390
+ * Type guard: is value a valid Funnel?
391
+ */
392
+ declare function isFunnel<TEntity = any>(value: unknown): value is Funnel<TEntity>;
393
+ /**
394
+ * Type guard: is value a valid FunnelStage?
395
+ */
396
+ declare function isStage<TEntity = any>(value: unknown): value is FunnelStage<TEntity>;
397
+ /**
398
+ * Type guard: is value a valid FilterRule?
399
+ */
400
+ declare function isFilterRule(value: unknown): value is FilterRule;
401
+ /**
402
+ * Type guard: is value a valid FunnelRun?
403
+ */
404
+ declare function isFunnelRun(value: unknown): value is FunnelRun;
405
+ /**
406
+ * Type guard: is value a valid FunnelResult?
407
+ */
408
+ declare function isFunnelResult<TEntity = any>(value: unknown): value is FunnelResult<TEntity>;
409
+ /**
410
+ * Type guard: is value a valid FieldDefinition?
411
+ */
412
+ declare function isFieldDefinition(value: unknown): value is FieldDefinition;
413
+ /**
414
+ * Get valid operators for a field type
415
+ */
416
+ declare function getValidOperators(fieldType: FieldType): ValidOperators;
417
+ /**
418
+ * Validate operator is allowed for field type
419
+ */
420
+ declare function isValidOperator(operator: Operator, fieldType: FieldType): boolean;
421
+ /**
422
+ * Validate filter rule
423
+ */
424
+ declare function validateFilterRule(rule: FilterRule): string[];
425
+ /**
426
+ * Validate funnel stage
427
+ */
428
+ declare function validateStage<TEntity = any>(stage: FunnelStage<TEntity>): string[];
429
+ /**
430
+ * Validate funnel
431
+ */
432
+ declare function validateFunnel<TEntity = any>(funnel: Funnel<TEntity>): string[];
433
+
434
+ export { validateStage as A, type CreateFunnelInput as C, type DeepPartial as D, type FieldConstraints as F, type InputType as I, type MatchAction as M, type NoMatchAction as N, type Operator as O, type RuleResult as R, type StageResult as S, type TriggerType as T, type UpdateFunnelInput as U, type ValidOperators as V, type CreateStageInput as a, type FieldDefinition as b, type FieldPath as c, type FieldRegistry as d, type FieldType as e, type FilterConfig as f, type FilterLogic as g, type FilterRule as h, type Funnel as i, type FunnelResult as j, type FunnelRun as k, type FunnelRunStatus as l, type FunnelStage as m, type FunnelStatus as n, type StageStats as o, type UpdateStageInput as p, getValidOperators as q, isFieldDefinition as r, isFilterRule as s, isFunnel as t, isFunnelResult as u, isFunnelRun as v, isStage as w, isValidOperator as x, validateFilterRule as y, validateFunnel as z };