@codeforamerica/safety-net-openapi-california 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/applications/client/client.gen.d.ts +2 -0
- package/dist/applications/client/client.gen.js +128 -0
- package/dist/applications/client/index.d.ts +8 -0
- package/dist/applications/client/index.js +6 -0
- package/dist/applications/client/types.gen.d.ts +88 -0
- package/dist/applications/client/types.gen.js +2 -0
- package/dist/applications/client/utils.gen.d.ts +14 -0
- package/dist/applications/client/utils.gen.js +171 -0
- package/dist/applications/client.gen.d.ts +12 -0
- package/dist/applications/client.gen.js +3 -0
- package/dist/applications/core/auth.gen.d.ts +18 -0
- package/dist/applications/core/auth.gen.js +14 -0
- package/dist/applications/core/bodySerializer.gen.d.ts +25 -0
- package/dist/applications/core/bodySerializer.gen.js +57 -0
- package/dist/applications/core/params.gen.d.ts +43 -0
- package/dist/applications/core/params.gen.js +100 -0
- package/dist/applications/core/pathSerializer.gen.d.ts +33 -0
- package/dist/applications/core/pathSerializer.gen.js +114 -0
- package/dist/applications/core/queryKeySerializer.gen.d.ts +18 -0
- package/dist/applications/core/queryKeySerializer.gen.js +99 -0
- package/dist/applications/core/serverSentEvents.gen.d.ts +71 -0
- package/dist/applications/core/serverSentEvents.gen.js +137 -0
- package/dist/applications/core/types.gen.d.ts +78 -0
- package/dist/applications/core/types.gen.js +2 -0
- package/dist/applications/core/utils.gen.d.ts +19 -0
- package/dist/applications/core/utils.gen.js +87 -0
- package/dist/applications/index.d.ts +2 -0
- package/dist/applications/index.js +2 -0
- package/dist/applications/sdk.gen.d.ts +45 -0
- package/dist/applications/sdk.gen.js +70 -0
- package/dist/applications/types.gen.d.ts +34007 -0
- package/dist/applications/types.gen.js +2 -0
- package/dist/applications/zod.gen.d.ts +17374 -0
- package/dist/applications/zod.gen.js +16857 -0
- package/dist/households/client/client.gen.d.ts +2 -0
- package/dist/households/client/client.gen.js +128 -0
- package/dist/households/client/index.d.ts +8 -0
- package/dist/households/client/index.js +6 -0
- package/dist/households/client/types.gen.d.ts +88 -0
- package/dist/households/client/types.gen.js +2 -0
- package/dist/households/client/utils.gen.d.ts +14 -0
- package/dist/households/client/utils.gen.js +171 -0
- package/dist/households/client.gen.d.ts +12 -0
- package/dist/households/client.gen.js +3 -0
- package/dist/households/core/auth.gen.d.ts +18 -0
- package/dist/households/core/auth.gen.js +14 -0
- package/dist/households/core/bodySerializer.gen.d.ts +25 -0
- package/dist/households/core/bodySerializer.gen.js +57 -0
- package/dist/households/core/params.gen.d.ts +43 -0
- package/dist/households/core/params.gen.js +100 -0
- package/dist/households/core/pathSerializer.gen.d.ts +33 -0
- package/dist/households/core/pathSerializer.gen.js +114 -0
- package/dist/households/core/queryKeySerializer.gen.d.ts +18 -0
- package/dist/households/core/queryKeySerializer.gen.js +99 -0
- package/dist/households/core/serverSentEvents.gen.d.ts +71 -0
- package/dist/households/core/serverSentEvents.gen.js +137 -0
- package/dist/households/core/types.gen.d.ts +78 -0
- package/dist/households/core/types.gen.js +2 -0
- package/dist/households/core/utils.gen.d.ts +19 -0
- package/dist/households/core/utils.gen.js +87 -0
- package/dist/households/index.d.ts +2 -0
- package/dist/households/index.js +2 -0
- package/dist/households/sdk.gen.d.ts +45 -0
- package/dist/households/sdk.gen.js +70 -0
- package/dist/households/types.gen.d.ts +1693 -0
- package/dist/households/types.gen.js +2 -0
- package/dist/households/zod.gen.d.ts +624 -0
- package/dist/households/zod.gen.js +625 -0
- package/dist/incomes/client/client.gen.d.ts +2 -0
- package/dist/incomes/client/client.gen.js +128 -0
- package/dist/incomes/client/index.d.ts +8 -0
- package/dist/incomes/client/index.js +6 -0
- package/dist/incomes/client/types.gen.d.ts +88 -0
- package/dist/incomes/client/types.gen.js +2 -0
- package/dist/incomes/client/utils.gen.d.ts +14 -0
- package/dist/incomes/client/utils.gen.js +171 -0
- package/dist/incomes/client.gen.d.ts +12 -0
- package/dist/incomes/client.gen.js +3 -0
- package/dist/incomes/core/auth.gen.d.ts +18 -0
- package/dist/incomes/core/auth.gen.js +14 -0
- package/dist/incomes/core/bodySerializer.gen.d.ts +25 -0
- package/dist/incomes/core/bodySerializer.gen.js +57 -0
- package/dist/incomes/core/params.gen.d.ts +43 -0
- package/dist/incomes/core/params.gen.js +100 -0
- package/dist/incomes/core/pathSerializer.gen.d.ts +33 -0
- package/dist/incomes/core/pathSerializer.gen.js +114 -0
- package/dist/incomes/core/queryKeySerializer.gen.d.ts +18 -0
- package/dist/incomes/core/queryKeySerializer.gen.js +99 -0
- package/dist/incomes/core/serverSentEvents.gen.d.ts +71 -0
- package/dist/incomes/core/serverSentEvents.gen.js +137 -0
- package/dist/incomes/core/types.gen.d.ts +78 -0
- package/dist/incomes/core/types.gen.js +2 -0
- package/dist/incomes/core/utils.gen.d.ts +19 -0
- package/dist/incomes/core/utils.gen.js +87 -0
- package/dist/incomes/index.d.ts +2 -0
- package/dist/incomes/index.js +2 -0
- package/dist/incomes/sdk.gen.d.ts +47 -0
- package/dist/incomes/sdk.gen.js +72 -0
- package/dist/incomes/types.gen.d.ts +1425 -0
- package/dist/incomes/types.gen.js +2 -0
- package/dist/incomes/zod.gen.d.ts +961 -0
- package/dist/incomes/zod.gen.js +920 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/persons/client/client.gen.d.ts +2 -0
- package/dist/persons/client/client.gen.js +128 -0
- package/dist/persons/client/index.d.ts +8 -0
- package/dist/persons/client/index.js +6 -0
- package/dist/persons/client/types.gen.d.ts +88 -0
- package/dist/persons/client/types.gen.js +2 -0
- package/dist/persons/client/utils.gen.d.ts +14 -0
- package/dist/persons/client/utils.gen.js +171 -0
- package/dist/persons/client.gen.d.ts +12 -0
- package/dist/persons/client.gen.js +3 -0
- package/dist/persons/core/auth.gen.d.ts +18 -0
- package/dist/persons/core/auth.gen.js +14 -0
- package/dist/persons/core/bodySerializer.gen.d.ts +25 -0
- package/dist/persons/core/bodySerializer.gen.js +57 -0
- package/dist/persons/core/params.gen.d.ts +43 -0
- package/dist/persons/core/params.gen.js +100 -0
- package/dist/persons/core/pathSerializer.gen.d.ts +33 -0
- package/dist/persons/core/pathSerializer.gen.js +114 -0
- package/dist/persons/core/queryKeySerializer.gen.d.ts +18 -0
- package/dist/persons/core/queryKeySerializer.gen.js +99 -0
- package/dist/persons/core/serverSentEvents.gen.d.ts +71 -0
- package/dist/persons/core/serverSentEvents.gen.js +137 -0
- package/dist/persons/core/types.gen.d.ts +78 -0
- package/dist/persons/core/types.gen.js +2 -0
- package/dist/persons/core/utils.gen.d.ts +19 -0
- package/dist/persons/core/utils.gen.js +87 -0
- package/dist/persons/index.d.ts +2 -0
- package/dist/persons/index.js +2 -0
- package/dist/persons/sdk.gen.d.ts +45 -0
- package/dist/persons/sdk.gen.js +70 -0
- package/dist/persons/types.gen.d.ts +7595 -0
- package/dist/persons/types.gen.js +2 -0
- package/dist/persons/zod.gen.d.ts +3578 -0
- package/dist/persons/zod.gen.js +3579 -0
- package/dist/search-helpers.d.ts +242 -0
- package/dist/search-helpers.js +244 -0
- package/package.json +95 -0
- package/src/applications/client/client.gen.ts +166 -0
- package/src/applications/client/index.ts +23 -0
- package/src/applications/client/types.gen.ts +197 -0
- package/src/applications/client/utils.gen.ts +213 -0
- package/src/applications/client.gen.ts +16 -0
- package/src/applications/core/auth.gen.ts +42 -0
- package/src/applications/core/bodySerializer.gen.ts +100 -0
- package/src/applications/core/params.gen.ts +176 -0
- package/src/applications/core/pathSerializer.gen.ts +181 -0
- package/src/applications/core/queryKeySerializer.gen.ts +136 -0
- package/src/applications/core/serverSentEvents.gen.ts +266 -0
- package/src/applications/core/types.gen.ts +118 -0
- package/src/applications/core/utils.gen.ts +143 -0
- package/src/applications/index.ts +4 -0
- package/src/applications/sdk.gen.ts +92 -0
- package/src/applications/types.gen.ts +34043 -0
- package/src/applications/zod.gen.ts +16877 -0
- package/src/households/client/client.gen.ts +166 -0
- package/src/households/client/index.ts +23 -0
- package/src/households/client/types.gen.ts +197 -0
- package/src/households/client/utils.gen.ts +213 -0
- package/src/households/client.gen.ts +16 -0
- package/src/households/core/auth.gen.ts +42 -0
- package/src/households/core/bodySerializer.gen.ts +100 -0
- package/src/households/core/params.gen.ts +176 -0
- package/src/households/core/pathSerializer.gen.ts +181 -0
- package/src/households/core/queryKeySerializer.gen.ts +136 -0
- package/src/households/core/serverSentEvents.gen.ts +266 -0
- package/src/households/core/types.gen.ts +118 -0
- package/src/households/core/utils.gen.ts +143 -0
- package/src/households/index.ts +4 -0
- package/src/households/sdk.gen.ts +92 -0
- package/src/households/types.gen.ts +1729 -0
- package/src/households/zod.gen.ts +645 -0
- package/src/incomes/client/client.gen.ts +166 -0
- package/src/incomes/client/index.ts +23 -0
- package/src/incomes/client/types.gen.ts +197 -0
- package/src/incomes/client/utils.gen.ts +213 -0
- package/src/incomes/client.gen.ts +16 -0
- package/src/incomes/core/auth.gen.ts +42 -0
- package/src/incomes/core/bodySerializer.gen.ts +100 -0
- package/src/incomes/core/params.gen.ts +176 -0
- package/src/incomes/core/pathSerializer.gen.ts +181 -0
- package/src/incomes/core/queryKeySerializer.gen.ts +136 -0
- package/src/incomes/core/serverSentEvents.gen.ts +266 -0
- package/src/incomes/core/types.gen.ts +118 -0
- package/src/incomes/core/utils.gen.ts +143 -0
- package/src/incomes/index.ts +4 -0
- package/src/incomes/sdk.gen.ts +94 -0
- package/src/incomes/types.gen.ts +1460 -0
- package/src/incomes/zod.gen.ts +939 -0
- package/src/index.ts +5 -0
- package/src/persons/client/client.gen.ts +166 -0
- package/src/persons/client/index.ts +23 -0
- package/src/persons/client/types.gen.ts +197 -0
- package/src/persons/client/utils.gen.ts +213 -0
- package/src/persons/client.gen.ts +16 -0
- package/src/persons/core/auth.gen.ts +42 -0
- package/src/persons/core/bodySerializer.gen.ts +100 -0
- package/src/persons/core/params.gen.ts +176 -0
- package/src/persons/core/pathSerializer.gen.ts +181 -0
- package/src/persons/core/queryKeySerializer.gen.ts +136 -0
- package/src/persons/core/serverSentEvents.gen.ts +266 -0
- package/src/persons/core/types.gen.ts +118 -0
- package/src/persons/core/utils.gen.ts +143 -0
- package/src/persons/index.ts +4 -0
- package/src/persons/sdk.gen.ts +92 -0
- package/src/persons/types.gen.ts +7631 -0
- package/src/persons/zod.gen.ts +3599 -0
- package/src/search-helpers.ts +264 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search Query Helpers for Safety Net API Clients
|
|
3
|
+
*
|
|
4
|
+
* This module provides utilities for building search queries using the
|
|
5
|
+
* field:value syntax supported by all list endpoints.
|
|
6
|
+
*
|
|
7
|
+
* @module search-helpers
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* import { q, search } from '@codeforamerica/safety-net-colorado';
|
|
11
|
+
*
|
|
12
|
+
* const query = q(
|
|
13
|
+
* search.eq("status", "approved"),
|
|
14
|
+
* search.gte("income", 1000),
|
|
15
|
+
* search.in("programs", ["snap", "cash_programs"])
|
|
16
|
+
* );
|
|
17
|
+
* // => "status:approved income:>=1000 programs:snap,cash_programs"
|
|
18
|
+
*
|
|
19
|
+
* const results = await personsClient.listPersons({
|
|
20
|
+
* queries: { q: query, limit: 25 }
|
|
21
|
+
* });
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Combines multiple search conditions into a single query string.
|
|
25
|
+
*
|
|
26
|
+
* Multiple conditions are ANDed together (all must match).
|
|
27
|
+
* Use comma-separated values within a single condition for OR logic.
|
|
28
|
+
*
|
|
29
|
+
* ## Syntax Reference
|
|
30
|
+
*
|
|
31
|
+
* | Pattern | Description | Example |
|
|
32
|
+
* |---------|-------------|---------|
|
|
33
|
+
* | `term` | Full-text exact match | `john` |
|
|
34
|
+
* | `*term*` | Full-text contains | `*john*` |
|
|
35
|
+
* | `term*` | Full-text starts with | `john*` |
|
|
36
|
+
* | `*term` | Full-text ends with | `*smith` |
|
|
37
|
+
* | `field:value` | Exact match | `status:approved` |
|
|
38
|
+
* | `field:*value*` | Contains (case-insensitive) | `name:*john*` |
|
|
39
|
+
* | `field:value*` | Starts with | `name:john*` |
|
|
40
|
+
* | `field:*value` | Ends with | `email:*@example.com` |
|
|
41
|
+
* | `field:"value"` | Quoted value (for spaces) | `name:"john doe"` |
|
|
42
|
+
* | `field.nested:value` | Nested field (dot notation) | `address.state:CA` |
|
|
43
|
+
* | `field:>value` | Greater than | `income:>1000` |
|
|
44
|
+
* | `field:>=value` | Greater than or equal | `income:>=1000` |
|
|
45
|
+
* | `field:<value` | Less than | `income:<5000` |
|
|
46
|
+
* | `field:<=value` | Less than or equal | `income:<=5000` |
|
|
47
|
+
* | `field:val1,val2` | Match any value (OR) | `status:approved,pending` |
|
|
48
|
+
* | `-field:value` | Exclude / negate | `-status:denied` |
|
|
49
|
+
* | `field:*` | Field exists (not null) | `email:*` |
|
|
50
|
+
* | `-field:*` | Field does not exist | `-deletedAt:*` |
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* // Full-text search
|
|
54
|
+
* q("john")
|
|
55
|
+
* // => "john"
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* // Exact match on a field
|
|
59
|
+
* q("status:approved")
|
|
60
|
+
* // => "status:approved"
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* // Multiple conditions (AND)
|
|
64
|
+
* q("status:approved", "income:>=1000")
|
|
65
|
+
* // => "status:approved income:>=1000"
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* // Using the search builder
|
|
69
|
+
* q(search.eq("status", "approved"), search.gte("income", 1000))
|
|
70
|
+
* // => "status:approved income:>=1000"
|
|
71
|
+
*
|
|
72
|
+
* @param conditions - One or more search conditions to combine
|
|
73
|
+
* @returns A search query string to pass to the `q` parameter
|
|
74
|
+
*/
|
|
75
|
+
export declare function q(...conditions: string[]): string;
|
|
76
|
+
/**
|
|
77
|
+
* Search query builder with type-safe methods for each operator.
|
|
78
|
+
*
|
|
79
|
+
* Use these methods to construct search conditions without memorizing
|
|
80
|
+
* the query syntax. All methods return strings that can be passed to `q()`.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* import { q, search } from '@codeforamerica/safety-net-colorado';
|
|
84
|
+
*
|
|
85
|
+
* // Build a complex query
|
|
86
|
+
* const query = q(
|
|
87
|
+
* search.eq("status", "approved"),
|
|
88
|
+
* search.gte("income", 1000),
|
|
89
|
+
* search.in("programs", ["snap", "medical_assistance"]),
|
|
90
|
+
* search.not("state", "TX")
|
|
91
|
+
* );
|
|
92
|
+
*
|
|
93
|
+
* // Use with Zodios client
|
|
94
|
+
* const results = await personsClient.listPersons({
|
|
95
|
+
* queries: { q: query, limit: 25 }
|
|
96
|
+
* });
|
|
97
|
+
*/
|
|
98
|
+
export declare const search: {
|
|
99
|
+
/**
|
|
100
|
+
* Exact match: `field:value`
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* search.eq("status", "approved")
|
|
104
|
+
* // => "status:approved"
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* // Nested field
|
|
108
|
+
* search.eq("address.state", "CA")
|
|
109
|
+
* // => "address.state:CA"
|
|
110
|
+
*/
|
|
111
|
+
eq: (field: string, value: string | number | boolean) => string;
|
|
112
|
+
/**
|
|
113
|
+
* Greater than: `field:>value`
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* search.gt("income", 1000)
|
|
117
|
+
* // => "income:>1000"
|
|
118
|
+
*/
|
|
119
|
+
gt: (field: string, value: string | number) => string;
|
|
120
|
+
/**
|
|
121
|
+
* Greater than or equal: `field:>=value`
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* search.gte("income", 1000)
|
|
125
|
+
* // => "income:>=1000"
|
|
126
|
+
*/
|
|
127
|
+
gte: (field: string, value: string | number) => string;
|
|
128
|
+
/**
|
|
129
|
+
* Less than: `field:<value`
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* search.lt("age", 65)
|
|
133
|
+
* // => "age:<65"
|
|
134
|
+
*/
|
|
135
|
+
lt: (field: string, value: string | number) => string;
|
|
136
|
+
/**
|
|
137
|
+
* Less than or equal: `field:<=value`
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* search.lte("income", 5000)
|
|
141
|
+
* // => "income:<=5000"
|
|
142
|
+
*/
|
|
143
|
+
lte: (field: string, value: string | number) => string;
|
|
144
|
+
/**
|
|
145
|
+
* Match any of the values (OR): `field:val1,val2,val3`
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* search.in("status", ["approved", "pending", "under_review"])
|
|
149
|
+
* // => "status:approved,pending,under_review"
|
|
150
|
+
*/
|
|
151
|
+
in: (field: string, values: (string | number)[]) => string;
|
|
152
|
+
/**
|
|
153
|
+
* Exclude / negate: `-field:value`
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* search.not("status", "denied")
|
|
157
|
+
* // => "-status:denied"
|
|
158
|
+
*/
|
|
159
|
+
not: (field: string, value: string | number) => string;
|
|
160
|
+
/**
|
|
161
|
+
* Field exists (is not null): `field:*`
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* search.exists("email")
|
|
165
|
+
* // => "email:*"
|
|
166
|
+
*/
|
|
167
|
+
exists: (field: string) => string;
|
|
168
|
+
/**
|
|
169
|
+
* Field does not exist (is null): `-field:*`
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* search.notExists("deletedAt")
|
|
173
|
+
* // => "-deletedAt:*"
|
|
174
|
+
*/
|
|
175
|
+
notExists: (field: string) => string;
|
|
176
|
+
/**
|
|
177
|
+
* Contains (case-insensitive): `field:*value*`
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* search.contains("name", "john")
|
|
181
|
+
* // => "name:*john*"
|
|
182
|
+
*/
|
|
183
|
+
contains: (field: string, value: string) => string;
|
|
184
|
+
/**
|
|
185
|
+
* Starts with (case-insensitive): `field:value*`
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* search.startsWith("name", "john")
|
|
189
|
+
* // => "name:john*"
|
|
190
|
+
*/
|
|
191
|
+
startsWith: (field: string, value: string) => string;
|
|
192
|
+
/**
|
|
193
|
+
* Ends with (case-insensitive): `field:*value`
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* search.endsWith("email", "@example.com")
|
|
197
|
+
* // => "email:*@example.com"
|
|
198
|
+
*/
|
|
199
|
+
endsWith: (field: string, value: string) => string;
|
|
200
|
+
/**
|
|
201
|
+
* Quoted value (for values containing spaces): `field:"value with spaces"`
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* search.quoted("name", "john doe")
|
|
205
|
+
* // => 'name:"john doe"'
|
|
206
|
+
*/
|
|
207
|
+
quoted: (field: string, value: string) => string;
|
|
208
|
+
/**
|
|
209
|
+
* Full-text exact match (no field specified)
|
|
210
|
+
*
|
|
211
|
+
* Searches across all searchable fields for an exact match of the term.
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* search.text("john")
|
|
215
|
+
* // => "john"
|
|
216
|
+
*/
|
|
217
|
+
text: (term: string) => string;
|
|
218
|
+
/**
|
|
219
|
+
* Full-text contains search (no field specified)
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* search.textContains("john")
|
|
223
|
+
* // => "*john*"
|
|
224
|
+
*/
|
|
225
|
+
textContains: (term: string) => string;
|
|
226
|
+
/**
|
|
227
|
+
* Full-text starts with search (no field specified)
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* search.textStartsWith("john")
|
|
231
|
+
* // => "john*"
|
|
232
|
+
*/
|
|
233
|
+
textStartsWith: (term: string) => string;
|
|
234
|
+
/**
|
|
235
|
+
* Full-text ends with search (no field specified)
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* search.textEndsWith("smith")
|
|
239
|
+
* // => "*smith"
|
|
240
|
+
*/
|
|
241
|
+
textEndsWith: (term: string) => string;
|
|
242
|
+
};
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search Query Helpers for Safety Net API Clients
|
|
3
|
+
*
|
|
4
|
+
* This module provides utilities for building search queries using the
|
|
5
|
+
* field:value syntax supported by all list endpoints.
|
|
6
|
+
*
|
|
7
|
+
* @module search-helpers
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* import { q, search } from '@codeforamerica/safety-net-colorado';
|
|
11
|
+
*
|
|
12
|
+
* const query = q(
|
|
13
|
+
* search.eq("status", "approved"),
|
|
14
|
+
* search.gte("income", 1000),
|
|
15
|
+
* search.in("programs", ["snap", "cash_programs"])
|
|
16
|
+
* );
|
|
17
|
+
* // => "status:approved income:>=1000 programs:snap,cash_programs"
|
|
18
|
+
*
|
|
19
|
+
* const results = await personsClient.listPersons({
|
|
20
|
+
* queries: { q: query, limit: 25 }
|
|
21
|
+
* });
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Combines multiple search conditions into a single query string.
|
|
25
|
+
*
|
|
26
|
+
* Multiple conditions are ANDed together (all must match).
|
|
27
|
+
* Use comma-separated values within a single condition for OR logic.
|
|
28
|
+
*
|
|
29
|
+
* ## Syntax Reference
|
|
30
|
+
*
|
|
31
|
+
* | Pattern | Description | Example |
|
|
32
|
+
* |---------|-------------|---------|
|
|
33
|
+
* | `term` | Full-text exact match | `john` |
|
|
34
|
+
* | `*term*` | Full-text contains | `*john*` |
|
|
35
|
+
* | `term*` | Full-text starts with | `john*` |
|
|
36
|
+
* | `*term` | Full-text ends with | `*smith` |
|
|
37
|
+
* | `field:value` | Exact match | `status:approved` |
|
|
38
|
+
* | `field:*value*` | Contains (case-insensitive) | `name:*john*` |
|
|
39
|
+
* | `field:value*` | Starts with | `name:john*` |
|
|
40
|
+
* | `field:*value` | Ends with | `email:*@example.com` |
|
|
41
|
+
* | `field:"value"` | Quoted value (for spaces) | `name:"john doe"` |
|
|
42
|
+
* | `field.nested:value` | Nested field (dot notation) | `address.state:CA` |
|
|
43
|
+
* | `field:>value` | Greater than | `income:>1000` |
|
|
44
|
+
* | `field:>=value` | Greater than or equal | `income:>=1000` |
|
|
45
|
+
* | `field:<value` | Less than | `income:<5000` |
|
|
46
|
+
* | `field:<=value` | Less than or equal | `income:<=5000` |
|
|
47
|
+
* | `field:val1,val2` | Match any value (OR) | `status:approved,pending` |
|
|
48
|
+
* | `-field:value` | Exclude / negate | `-status:denied` |
|
|
49
|
+
* | `field:*` | Field exists (not null) | `email:*` |
|
|
50
|
+
* | `-field:*` | Field does not exist | `-deletedAt:*` |
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* // Full-text search
|
|
54
|
+
* q("john")
|
|
55
|
+
* // => "john"
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* // Exact match on a field
|
|
59
|
+
* q("status:approved")
|
|
60
|
+
* // => "status:approved"
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* // Multiple conditions (AND)
|
|
64
|
+
* q("status:approved", "income:>=1000")
|
|
65
|
+
* // => "status:approved income:>=1000"
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* // Using the search builder
|
|
69
|
+
* q(search.eq("status", "approved"), search.gte("income", 1000))
|
|
70
|
+
* // => "status:approved income:>=1000"
|
|
71
|
+
*
|
|
72
|
+
* @param conditions - One or more search conditions to combine
|
|
73
|
+
* @returns A search query string to pass to the `q` parameter
|
|
74
|
+
*/
|
|
75
|
+
export function q(...conditions) {
|
|
76
|
+
return conditions.filter(Boolean).join(" ");
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Search query builder with type-safe methods for each operator.
|
|
80
|
+
*
|
|
81
|
+
* Use these methods to construct search conditions without memorizing
|
|
82
|
+
* the query syntax. All methods return strings that can be passed to `q()`.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* import { q, search } from '@codeforamerica/safety-net-colorado';
|
|
86
|
+
*
|
|
87
|
+
* // Build a complex query
|
|
88
|
+
* const query = q(
|
|
89
|
+
* search.eq("status", "approved"),
|
|
90
|
+
* search.gte("income", 1000),
|
|
91
|
+
* search.in("programs", ["snap", "medical_assistance"]),
|
|
92
|
+
* search.not("state", "TX")
|
|
93
|
+
* );
|
|
94
|
+
*
|
|
95
|
+
* // Use with Zodios client
|
|
96
|
+
* const results = await personsClient.listPersons({
|
|
97
|
+
* queries: { q: query, limit: 25 }
|
|
98
|
+
* });
|
|
99
|
+
*/
|
|
100
|
+
export const search = {
|
|
101
|
+
/**
|
|
102
|
+
* Exact match: `field:value`
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* search.eq("status", "approved")
|
|
106
|
+
* // => "status:approved"
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* // Nested field
|
|
110
|
+
* search.eq("address.state", "CA")
|
|
111
|
+
* // => "address.state:CA"
|
|
112
|
+
*/
|
|
113
|
+
eq: (field, value) => `${field}:${value}`,
|
|
114
|
+
/**
|
|
115
|
+
* Greater than: `field:>value`
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* search.gt("income", 1000)
|
|
119
|
+
* // => "income:>1000"
|
|
120
|
+
*/
|
|
121
|
+
gt: (field, value) => `${field}:>${value}`,
|
|
122
|
+
/**
|
|
123
|
+
* Greater than or equal: `field:>=value`
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* search.gte("income", 1000)
|
|
127
|
+
* // => "income:>=1000"
|
|
128
|
+
*/
|
|
129
|
+
gte: (field, value) => `${field}:>=${value}`,
|
|
130
|
+
/**
|
|
131
|
+
* Less than: `field:<value`
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* search.lt("age", 65)
|
|
135
|
+
* // => "age:<65"
|
|
136
|
+
*/
|
|
137
|
+
lt: (field, value) => `${field}:<${value}`,
|
|
138
|
+
/**
|
|
139
|
+
* Less than or equal: `field:<=value`
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* search.lte("income", 5000)
|
|
143
|
+
* // => "income:<=5000"
|
|
144
|
+
*/
|
|
145
|
+
lte: (field, value) => `${field}:<=${value}`,
|
|
146
|
+
/**
|
|
147
|
+
* Match any of the values (OR): `field:val1,val2,val3`
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* search.in("status", ["approved", "pending", "under_review"])
|
|
151
|
+
* // => "status:approved,pending,under_review"
|
|
152
|
+
*/
|
|
153
|
+
in: (field, values) => `${field}:${values.join(",")}`,
|
|
154
|
+
/**
|
|
155
|
+
* Exclude / negate: `-field:value`
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* search.not("status", "denied")
|
|
159
|
+
* // => "-status:denied"
|
|
160
|
+
*/
|
|
161
|
+
not: (field, value) => `-${field}:${value}`,
|
|
162
|
+
/**
|
|
163
|
+
* Field exists (is not null): `field:*`
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* search.exists("email")
|
|
167
|
+
* // => "email:*"
|
|
168
|
+
*/
|
|
169
|
+
exists: (field) => `${field}:*`,
|
|
170
|
+
/**
|
|
171
|
+
* Field does not exist (is null): `-field:*`
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* search.notExists("deletedAt")
|
|
175
|
+
* // => "-deletedAt:*"
|
|
176
|
+
*/
|
|
177
|
+
notExists: (field) => `-${field}:*`,
|
|
178
|
+
/**
|
|
179
|
+
* Contains (case-insensitive): `field:*value*`
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* search.contains("name", "john")
|
|
183
|
+
* // => "name:*john*"
|
|
184
|
+
*/
|
|
185
|
+
contains: (field, value) => `${field}:*${value}*`,
|
|
186
|
+
/**
|
|
187
|
+
* Starts with (case-insensitive): `field:value*`
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* search.startsWith("name", "john")
|
|
191
|
+
* // => "name:john*"
|
|
192
|
+
*/
|
|
193
|
+
startsWith: (field, value) => `${field}:${value}*`,
|
|
194
|
+
/**
|
|
195
|
+
* Ends with (case-insensitive): `field:*value`
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* search.endsWith("email", "@example.com")
|
|
199
|
+
* // => "email:*@example.com"
|
|
200
|
+
*/
|
|
201
|
+
endsWith: (field, value) => `${field}:*${value}`,
|
|
202
|
+
/**
|
|
203
|
+
* Quoted value (for values containing spaces): `field:"value with spaces"`
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* search.quoted("name", "john doe")
|
|
207
|
+
* // => 'name:"john doe"'
|
|
208
|
+
*/
|
|
209
|
+
quoted: (field, value) => `${field}:"${value}"`,
|
|
210
|
+
/**
|
|
211
|
+
* Full-text exact match (no field specified)
|
|
212
|
+
*
|
|
213
|
+
* Searches across all searchable fields for an exact match of the term.
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* search.text("john")
|
|
217
|
+
* // => "john"
|
|
218
|
+
*/
|
|
219
|
+
text: (term) => term,
|
|
220
|
+
/**
|
|
221
|
+
* Full-text contains search (no field specified)
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* search.textContains("john")
|
|
225
|
+
* // => "*john*"
|
|
226
|
+
*/
|
|
227
|
+
textContains: (term) => `*${term}*`,
|
|
228
|
+
/**
|
|
229
|
+
* Full-text starts with search (no field specified)
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* search.textStartsWith("john")
|
|
233
|
+
* // => "john*"
|
|
234
|
+
*/
|
|
235
|
+
textStartsWith: (term) => `${term}*`,
|
|
236
|
+
/**
|
|
237
|
+
* Full-text ends with search (no field specified)
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* search.textEndsWith("smith")
|
|
241
|
+
* // => "*smith"
|
|
242
|
+
*/
|
|
243
|
+
textEndsWith: (term) => `*${term}`,
|
|
244
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@codeforamerica/safety-net-openapi-california",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Safety Net API client for California with Zod validation",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"src"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./search": {
|
|
18
|
+
"import": "./dist/search-helpers.js",
|
|
19
|
+
"types": "./dist/search-helpers.d.ts"
|
|
20
|
+
},
|
|
21
|
+
"./persons": {
|
|
22
|
+
"import": "./dist/persons/index.js",
|
|
23
|
+
"types": "./dist/persons/index.d.ts"
|
|
24
|
+
},
|
|
25
|
+
"./persons/client": {
|
|
26
|
+
"import": "./dist/persons/client/index.js",
|
|
27
|
+
"types": "./dist/persons/client/index.d.ts"
|
|
28
|
+
},
|
|
29
|
+
"./persons/*": {
|
|
30
|
+
"import": "./dist/persons/*.js",
|
|
31
|
+
"types": "./dist/persons/*.d.ts"
|
|
32
|
+
},
|
|
33
|
+
"./applications": {
|
|
34
|
+
"import": "./dist/applications/index.js",
|
|
35
|
+
"types": "./dist/applications/index.d.ts"
|
|
36
|
+
},
|
|
37
|
+
"./applications/client": {
|
|
38
|
+
"import": "./dist/applications/client/index.js",
|
|
39
|
+
"types": "./dist/applications/client/index.d.ts"
|
|
40
|
+
},
|
|
41
|
+
"./applications/*": {
|
|
42
|
+
"import": "./dist/applications/*.js",
|
|
43
|
+
"types": "./dist/applications/*.d.ts"
|
|
44
|
+
},
|
|
45
|
+
"./households": {
|
|
46
|
+
"import": "./dist/households/index.js",
|
|
47
|
+
"types": "./dist/households/index.d.ts"
|
|
48
|
+
},
|
|
49
|
+
"./households/client": {
|
|
50
|
+
"import": "./dist/households/client/index.js",
|
|
51
|
+
"types": "./dist/households/client/index.d.ts"
|
|
52
|
+
},
|
|
53
|
+
"./households/*": {
|
|
54
|
+
"import": "./dist/households/*.js",
|
|
55
|
+
"types": "./dist/households/*.d.ts"
|
|
56
|
+
},
|
|
57
|
+
"./incomes": {
|
|
58
|
+
"import": "./dist/incomes/index.js",
|
|
59
|
+
"types": "./dist/incomes/index.d.ts"
|
|
60
|
+
},
|
|
61
|
+
"./incomes/client": {
|
|
62
|
+
"import": "./dist/incomes/client/index.js",
|
|
63
|
+
"types": "./dist/incomes/client/index.d.ts"
|
|
64
|
+
},
|
|
65
|
+
"./incomes/*": {
|
|
66
|
+
"import": "./dist/incomes/*.js",
|
|
67
|
+
"types": "./dist/incomes/*.d.ts"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"peerDependencies": {
|
|
71
|
+
"axios": "^1.6.0",
|
|
72
|
+
"zod": "^4.0.0"
|
|
73
|
+
},
|
|
74
|
+
"keywords": [
|
|
75
|
+
"safety-net",
|
|
76
|
+
"california",
|
|
77
|
+
"zod",
|
|
78
|
+
"openapi",
|
|
79
|
+
"api-client"
|
|
80
|
+
],
|
|
81
|
+
"repository": {
|
|
82
|
+
"type": "git",
|
|
83
|
+
"url": "git+https://github.com/codeforamerica/safety-net-openapi.git"
|
|
84
|
+
},
|
|
85
|
+
"license": "PolyForm-Noncommercial-1.0.0",
|
|
86
|
+
"publishConfig": {
|
|
87
|
+
"registry": "https://registry.npmjs.org",
|
|
88
|
+
"access": "public",
|
|
89
|
+
"provenance": true
|
|
90
|
+
},
|
|
91
|
+
"devDependencies": {
|
|
92
|
+
"axios": "^1.13.2",
|
|
93
|
+
"zod": "^4.3.5"
|
|
94
|
+
}
|
|
95
|
+
}
|