@jclind/ingredient-parser 1.3.1 → 1.3.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.
- package/README.md +250 -211
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,211 +1,250 @@
|
|
|
1
|
-
# @jclind/ingredient-parser
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/@jclind/ingredient-parser)
|
|
4
|
-
[](https://github.com/jclind/ingredient-parser/blob/main/LICENSE)
|
|
5
|
-
|
|
6
|
-
A TypeScript package for parsing ingredient strings and retrieving structured ingredient data from the Spoonacular API.
|
|
7
|
-
|
|
8
|
-
Built on top of [recipe-ingredient-parser-v3](https://www.npmjs.com/package/recipe-ingredient-parser-v3). If you only need ingredient parsing without ingredient metadata, nutrition, or API lookups, you may prefer using that package directly.
|
|
9
|
-
|
|
10
|
-
## Installation
|
|
11
|
-
|
|
12
|
-
```sh
|
|
13
|
-
npm install @jclind/ingredient-parser
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## Quick Start
|
|
17
|
-
|
|
18
|
-
```ts
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
| `
|
|
52
|
-
| `
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
|
58
|
-
|
|
|
59
|
-
| `
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
{
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
1
|
+
# @jclind/ingredient-parser
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@jclind/ingredient-parser)
|
|
4
|
+
[](https://github.com/jclind/ingredient-parser/blob/main/LICENSE)
|
|
5
|
+
|
|
6
|
+
A TypeScript package for parsing ingredient strings and retrieving structured ingredient data from the Spoonacular API.
|
|
7
|
+
|
|
8
|
+
Built on top of [recipe-ingredient-parser-v3](https://www.npmjs.com/package/recipe-ingredient-parser-v3). If you only need ingredient parsing without ingredient metadata, nutrition, or API lookups, you may prefer using that package directly.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
npm install @jclind/ingredient-parser
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import { ingredientParser } from '@jclind/ingredient-parser'
|
|
20
|
+
|
|
21
|
+
const result = await ingredientParser('1 cup rice, washed', 'YOUR_API_KEY', {
|
|
22
|
+
returnNutritionData: true,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
console.log(result)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## API
|
|
29
|
+
|
|
30
|
+
### `ingredientParser(ingredientString, apiKey, options?)`
|
|
31
|
+
|
|
32
|
+
Parses an ingredient string and returns both the parsed ingredient data and ingredient metadata retrieved from Spoonacular.
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { ingredientParser } from '@jclind/ingredient-parser'
|
|
36
|
+
|
|
37
|
+
ingredientParser(
|
|
38
|
+
ingredientString: string,
|
|
39
|
+
apiKey: string,
|
|
40
|
+
options?: {
|
|
41
|
+
returnNutritionData?: boolean
|
|
42
|
+
imageSize?: '100x100' | '250x250' | '500x500'
|
|
43
|
+
serverUrl?: string
|
|
44
|
+
}
|
|
45
|
+
): Promise<IngredientResponse>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
| Parameter | Type | Required | Description |
|
|
49
|
+
| ------------------ | -------- | -------- | ------------------------------------------------------- |
|
|
50
|
+
| `ingredientString` | `string` | Yes | Ingredient string formatted like `2 cups onions, diced` |
|
|
51
|
+
| `apiKey` | `string` | Yes | Your Spoonacular API key |
|
|
52
|
+
| `options` | `object` | No | Additional parsing options |
|
|
53
|
+
|
|
54
|
+
#### Options
|
|
55
|
+
|
|
56
|
+
| Option | Type | Default | Description |
|
|
57
|
+
| --------------------- | --------------------------------------- | ----------- | ------------------------------------------------------------- |
|
|
58
|
+
| `returnNutritionData` | `boolean` | `false` | Includes Spoonacular nutrition data in `ingredientData` |
|
|
59
|
+
| `imageSize` | `'100x100' \| '250x250' \| '500x500'` | `'100x100'` | Size of the ingredient image returned in `imagePath` |
|
|
60
|
+
| `serverUrl` | `string` | — | Override the default proxy server URL used to call Spoonacular |
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
### `parseIngredientString(ingredientString)`
|
|
65
|
+
|
|
66
|
+
Parses an ingredient string locally without any network calls. Use this when you only need quantity, unit, and ingredient name extraction.
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { parseIngredientString } from '@jclind/ingredient-parser'
|
|
70
|
+
|
|
71
|
+
parseIngredientString(ingredientString: string): ParsedIngredient
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
parseIngredientString('1 cup rice, washed')
|
|
76
|
+
// {
|
|
77
|
+
// quantity: 1,
|
|
78
|
+
// unit: 'cup',
|
|
79
|
+
// unitPlural: 'cups',
|
|
80
|
+
// symbol: 'c',
|
|
81
|
+
// ingredient: 'rice',
|
|
82
|
+
// originalIngredientString: '1 cup rice, washed',
|
|
83
|
+
// minQty: 1,
|
|
84
|
+
// maxQty: 1,
|
|
85
|
+
// comment: 'washed'
|
|
86
|
+
// }
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Response Structure
|
|
92
|
+
|
|
93
|
+
`ingredientParser` returns a discriminated union. On success, `ingredientData` is always present. On error, `error` is present and `ingredientData` is `null`.
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
// Success
|
|
97
|
+
{
|
|
98
|
+
parsedIngredient: ParsedIngredient
|
|
99
|
+
ingredientData: IngredientData
|
|
100
|
+
id?: string
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Error
|
|
104
|
+
{
|
|
105
|
+
error: { message: string }
|
|
106
|
+
parsedIngredient: ParsedIngredient
|
|
107
|
+
ingredientData: null
|
|
108
|
+
id?: string
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
### `parsedIngredient`
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
{
|
|
118
|
+
quantity: 1,
|
|
119
|
+
unit: 'cup',
|
|
120
|
+
unitPlural: 'cups',
|
|
121
|
+
symbol: 'c',
|
|
122
|
+
ingredient: 'rice',
|
|
123
|
+
originalIngredientString: '1 cup rice, washed',
|
|
124
|
+
minQty: 1,
|
|
125
|
+
maxQty: 1,
|
|
126
|
+
comment: 'washed'
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
### `ingredientData`
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
{
|
|
136
|
+
ingredientId: 20444,
|
|
137
|
+
originalName: 'rice',
|
|
138
|
+
name: 'rice',
|
|
139
|
+
amount: 1,
|
|
140
|
+
possibleUnits: ['g', 'oz', 'cup'],
|
|
141
|
+
consistency: 'solid',
|
|
142
|
+
shoppingListUnits: ['ounces', 'pounds'],
|
|
143
|
+
aisle: 'Pasta and Rice',
|
|
144
|
+
image: 'uncooked-white-rice.png',
|
|
145
|
+
imagePath: 'https://spoonacular.com/cdn/ingredients_100x100/uncooked-white-rice.png',
|
|
146
|
+
nutrition?: {
|
|
147
|
+
nutrients: [...],
|
|
148
|
+
properties: [...],
|
|
149
|
+
flavonoids: [...],
|
|
150
|
+
caloricBreakdown: {...},
|
|
151
|
+
weightPerServing: {...}
|
|
152
|
+
},
|
|
153
|
+
totalPriceUSACents: 75.71
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Error Handling
|
|
160
|
+
|
|
161
|
+
The function returns an error object (and `ingredientData: null`) when the ingredient cannot be identified or the API key is invalid. `parsedIngredient` is always populated.
|
|
162
|
+
|
|
163
|
+
### Unknown Ingredient
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
const result = await ingredientParser('Invalid Text', 'YOUR_API_KEY')
|
|
167
|
+
|
|
168
|
+
/*
|
|
169
|
+
{
|
|
170
|
+
error: { message: 'Ingredient not formatted correctly or Ingredient Unknown. Please pass ingredient comments/instructions after a comma' },
|
|
171
|
+
ingredientData: null,
|
|
172
|
+
parsedIngredient: {
|
|
173
|
+
quantity: null,
|
|
174
|
+
unit: null,
|
|
175
|
+
unitPlural: null,
|
|
176
|
+
symbol: null,
|
|
177
|
+
ingredient: 'Invalid Text',
|
|
178
|
+
originalIngredientString: 'Invalid Text',
|
|
179
|
+
minQty: null,
|
|
180
|
+
maxQty: null,
|
|
181
|
+
comment: null
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
*/
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Invalid API Key
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
const result = await ingredientParser('1 cup rice', 'INVALID_KEY')
|
|
191
|
+
|
|
192
|
+
/*
|
|
193
|
+
{
|
|
194
|
+
error: { message: 'API Key Not Valid' },
|
|
195
|
+
ingredientData: null,
|
|
196
|
+
parsedIngredient: {
|
|
197
|
+
quantity: 1,
|
|
198
|
+
unit: 'cup',
|
|
199
|
+
unitPlural: 'cups',
|
|
200
|
+
symbol: 'c',
|
|
201
|
+
ingredient: 'rice',
|
|
202
|
+
originalIngredientString: '1 cup rice',
|
|
203
|
+
minQty: 1,
|
|
204
|
+
maxQty: 1,
|
|
205
|
+
comment: null
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
*/
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## TypeScript
|
|
214
|
+
|
|
215
|
+
This package ships with full TypeScript definitions. No additional `@types` package required.
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
import {
|
|
219
|
+
ingredientParser,
|
|
220
|
+
parseIngredientString,
|
|
221
|
+
ParsedIngredient,
|
|
222
|
+
IngredientData,
|
|
223
|
+
IngredientResponse,
|
|
224
|
+
} from '@jclind/ingredient-parser'
|
|
225
|
+
|
|
226
|
+
const result: IngredientResponse = await ingredientParser(
|
|
227
|
+
'1 cup rice, washed',
|
|
228
|
+
'YOUR_API_KEY'
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
if ('error' in result) {
|
|
232
|
+
console.error(result.error.message)
|
|
233
|
+
} else {
|
|
234
|
+
const parsed: ParsedIngredient = result.parsedIngredient
|
|
235
|
+
const data: IngredientData = result.ingredientData
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Notes
|
|
242
|
+
|
|
243
|
+
- A valid Spoonacular API key is required for ingredient lookups via `ingredientParser`.
|
|
244
|
+
- `parseIngredientString` works offline with no API key.
|
|
245
|
+
- Nutrition data is optional and disabled by default to reduce API usage.
|
|
246
|
+
- `parsedIngredient` is always populated, even when the API call fails.
|
|
247
|
+
|
|
248
|
+
## Issues & Contributing
|
|
249
|
+
|
|
250
|
+
Found a bug or have a feature request? [Open an issue](https://github.com/jclind/ingredient-parser/issues) on GitHub. PRs are welcome.
|
package/package.json
CHANGED