soustack 0.3.0 → 0.4.1
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 +44 -27
- package/dist/cli/index.js +5225 -992
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.mts +163 -91
- package/dist/index.d.ts +163 -91
- package/dist/index.js +5077 -1007
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5076 -1007
- package/dist/index.mjs.map +1 -1
- package/dist/{scrape.d.mts → scrape/index.d.mts} +88 -74
- package/dist/{scrape.d.ts → scrape/index.d.ts} +88 -74
- package/dist/{scrape.js → scrape/index.js} +255 -124
- package/dist/scrape/index.js.map +1 -0
- package/dist/{scrape.mjs → scrape/index.mjs} +255 -124
- package/dist/scrape/index.mjs.map +1 -0
- package/package.json +21 -9
- package/spec/.sync-meta.json +149 -0
- package/spec/SOUSTACK_SPEC_VERSION +1 -0
- package/spec/defs/common.schema.json +46 -0
- package/spec/defs/duration.schema.json +33 -0
- package/spec/defs/entities.schema.json +111 -0
- package/spec/defs/ingredientQuantified.schema.json +9 -0
- package/spec/defs/quantity.schema.json +16 -0
- package/spec/defs/scalingRule.schema.json +127 -0
- package/spec/defs/temperature.schema.json +63 -0
- package/spec/fixtures/content/illustrated-step.valid.json +24 -0
- package/spec/fixtures/invalid/equipment-unknown-reference.invalid.json +38 -0
- package/spec/fixtures/invalid/mise-en-place-unknown-equipment.invalid.json +37 -0
- package/spec/fixtures/invalid/mise-en-place-unknown-input.invalid.json +41 -0
- package/spec/fixtures/invalid/storage-leftovers-missing-method.invalid.json +31 -0
- package/spec/fixtures/invalid/storage-leftovers-wrong-type.invalid.json +23 -0
- package/spec/fixtures/level/base-full.valid.json +162 -0
- package/spec/fixtures/level/base-missing-yield.invalid.json +12 -0
- package/spec/fixtures/level/lite-min.valid.json +14 -0
- package/spec/fixtures/profile/profile-base.valid.json +20 -0
- package/spec/fixtures/profile/profile-equipped.valid.json +28 -0
- package/spec/fixtures/profile/profile-illustrated.valid.json +28 -0
- package/spec/fixtures/profile/profile-lite.valid.json +13 -0
- package/spec/fixtures/profile/profile-prepped.valid.json +31 -0
- package/spec/fixtures/profile/profile-scalable-missing-scaling.invalid.json +29 -0
- package/spec/fixtures/profile/profile-scalable.valid.json +49 -0
- package/spec/fixtures/profile/profile-timed-missing-structured.invalid.json +30 -0
- package/spec/fixtures/scaling/bakers-percent-missing-ref.invalid.json +41 -0
- package/spec/fixtures/scaling/bakers-percent.valid.json +51 -0
- package/spec/fixtures/scaling/discrete-range.invalid.json +36 -0
- package/spec/fixtures/scaling/missing-quantified.invalid.json +40 -0
- package/spec/fixtures/scaling/reject-bakersPercentage.invalid.json +50 -0
- package/spec/fixtures/stacks/compute-missing-timed.invalid.json +32 -0
- package/spec/fixtures/stacks/dietary-no-signal.invalid.json +16 -0
- package/spec/fixtures/stacks/illustrated-empty.invalid.json +13 -0
- package/spec/fixtures/stacks/quantified-string.invalid.json +22 -0
- package/spec/fixtures/stacks/referenced-missing-input.invalid.json +32 -0
- package/spec/fixtures/stacks/storage-min.valid.json +20 -0
- package/spec/fixtures/stacks/storage-no-duration.invalid.json +16 -0
- package/spec/fixtures/stacks/timed-implies-structured.valid.json +50 -0
- package/spec/fixtures/stacks/timed-range.invalid.json +33 -0
- package/spec/fixtures/valid/equipment-scaling-rules.valid.json +76 -0
- package/spec/fixtures/valid/equipment-strings.valid.json +31 -0
- package/spec/fixtures/valid/equipment-structured-uses.valid.json +47 -0
- package/spec/fixtures/valid/mise-en-place-basic.valid.json +31 -0
- package/spec/fixtures/valid/mise-en-place-referenced-equipment.valid.json +51 -0
- package/spec/fixtures/valid/prep-ingredient-strings.valid.json +48 -0
- package/spec/fixtures/valid/prep-ingredient-structured.valid.json +45 -0
- package/spec/fixtures/valid/profile-equipped.valid.json +29 -0
- package/spec/fixtures/valid/profile-prepped.valid.json +32 -0
- package/spec/fixtures/valid/quantified-nested-ingredient-sections.valid.json +61 -0
- package/spec/fixtures/valid/referenced-scaling.valid.json +67 -0
- package/spec/fixtures/valid/storage-leftovers-simple.valid.json +27 -0
- package/spec/fixtures/valid/storage-leftovers-structured.valid.json +43 -0
- package/spec/fixtures/valid/structured-nested-step-sections.valid.json +84 -0
- package/spec/schemas/stacks-registry.schema.json +108 -0
- package/spec/soustack.schema.json +2379 -0
- package/spec/stacks/compute.schema.json +7 -0
- package/spec/stacks/compute@1.md +22 -0
- package/spec/stacks/dietary.schema.json +45 -0
- package/spec/stacks/dietary@1.md +24 -0
- package/spec/stacks/equipment.schema.json +98 -0
- package/spec/stacks/equipment@1.md +244 -0
- package/spec/stacks/illustrated.schema.json +54 -0
- package/spec/stacks/illustrated@1.md +24 -0
- package/spec/stacks/prep.schema.json +76 -0
- package/spec/stacks/prep@1.md +276 -0
- package/spec/stacks/quantified.schema.json +74 -0
- package/spec/stacks/quantified@1.md +24 -0
- package/spec/stacks/referenced.schema.json +96 -0
- package/spec/stacks/referenced@1.md +23 -0
- package/spec/stacks/registry.json +112 -0
- package/spec/stacks/scaling.schema.json +99 -0
- package/spec/stacks/scaling@1.md +238 -0
- package/spec/stacks/storage.schema.json +132 -0
- package/spec/stacks/storage@1.md +256 -0
- package/spec/stacks/structured.schema.json +48 -0
- package/spec/stacks/structured@1.md +24 -0
- package/spec/stacks/substitutions.schema.json +43 -0
- package/spec/stacks/substitutions@1.md +24 -0
- package/spec/stacks/techniques.schema.json +28 -0
- package/spec/stacks/techniques@1.md +23 -0
- package/spec/stacks/timed.schema.json +60 -0
- package/spec/stacks/timed@1.md +23 -0
- package/src/defs/common.schema.json +46 -0
- package/src/defs/duration.schema.json +33 -0
- package/src/defs/entities.schema.json +111 -0
- package/src/defs/ingredientQuantified.schema.json +9 -0
- package/src/defs/quantity.schema.json +16 -0
- package/src/defs/scalingRule.schema.json +127 -0
- package/src/defs/temperature.schema.json +63 -0
- package/src/profiles/base.schema.json +2 -2
- package/src/profiles/equipped.schema.json +10 -0
- package/src/profiles/illustrated.schema.json +4 -4
- package/src/profiles/lite.schema.json +10 -0
- package/src/profiles/prepped.schema.json +10 -0
- package/src/profiles/scalable.schema.json +6 -6
- package/src/profiles/timed.schema.json +10 -0
- package/src/schema.json +2271 -248
- package/src/schemas/stacks-registry.schema.json +108 -0
- package/src/soustack.schema.json +2271 -248
- package/src/stacks/compute.schema.json +7 -0
- package/src/stacks/compute@1.md +22 -0
- package/src/stacks/dietary.schema.json +45 -0
- package/src/stacks/dietary@1.md +24 -0
- package/src/stacks/equipment.schema.json +98 -0
- package/src/stacks/equipment@1.md +244 -0
- package/src/stacks/illustrated.schema.json +54 -0
- package/src/stacks/illustrated@1.md +24 -0
- package/src/stacks/prep.schema.json +76 -0
- package/src/stacks/prep@1.md +276 -0
- package/src/stacks/quantified.schema.json +74 -0
- package/src/stacks/quantified@1.md +24 -0
- package/src/stacks/referenced.schema.json +96 -0
- package/src/stacks/referenced@1.md +23 -0
- package/src/stacks/registry.json +112 -0
- package/src/stacks/scaling.schema.json +99 -0
- package/src/stacks/scaling@1.md +238 -0
- package/src/stacks/storage.schema.json +132 -0
- package/src/stacks/storage@1.md +256 -0
- package/src/stacks/structured.schema.json +48 -0
- package/src/stacks/structured@1.md +24 -0
- package/src/stacks/substitutions.schema.json +43 -0
- package/src/stacks/substitutions@1.md +24 -0
- package/src/stacks/techniques.schema.json +28 -0
- package/src/stacks/techniques@1.md +23 -0
- package/src/stacks/timed.schema.json +60 -0
- package/src/stacks/timed@1.md +23 -0
- package/dist/scrape.js.map +0 -1
- package/dist/scrape.mjs.map +0 -1
- package/src/profiles/cookable.schema.json +0 -18
- package/src/profiles/quantified.schema.json +0 -43
- package/src/profiles/schedulable.schema.json +0 -43
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Soustack Recipe Schema v0.
|
|
2
|
+
* Soustack Recipe Schema v0.0.2
|
|
3
3
|
* A portable, scalable, interoperable recipe format.
|
|
4
4
|
*/
|
|
5
5
|
interface SoustackRecipe {
|
|
@@ -7,18 +7,10 @@ interface SoustackRecipe {
|
|
|
7
7
|
'@type'?: 'Recipe';
|
|
8
8
|
/** Optional $schema pointer for profile-aware validation */
|
|
9
9
|
$schema?: string;
|
|
10
|
-
/** Optional declared validation profile */
|
|
11
|
-
profile?:
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
/** Attribution module payload */
|
|
15
|
-
attribution?: AttributionModule;
|
|
16
|
-
/** Taxonomy module payload */
|
|
17
|
-
taxonomy?: TaxonomyModule;
|
|
18
|
-
/** Media module payload */
|
|
19
|
-
media?: MediaModule;
|
|
20
|
-
/** Times module payload */
|
|
21
|
-
times?: TimesModule;
|
|
10
|
+
/** Optional declared validation profile (vNext only) */
|
|
11
|
+
profile?: "base" | "equipped" | "illustrated" | "lite" | "prepped" | "scalable" | "timed";
|
|
12
|
+
/** Stack declarations as a map: Record<stackName, versionNumber> */
|
|
13
|
+
stacks?: Record<string, number>;
|
|
22
14
|
/** Unique identifier (slug or UUID) */
|
|
23
15
|
id?: string;
|
|
24
16
|
/** Optional display title */
|
|
@@ -35,6 +27,10 @@ interface SoustackRecipe {
|
|
|
35
27
|
/** Additional tags for filtering */
|
|
36
28
|
tags?: string[];
|
|
37
29
|
/** URL(s) to recipe image(s) */
|
|
30
|
+
images?: string[];
|
|
31
|
+
/** URL(s) to recipe video(s) */
|
|
32
|
+
videos?: string[];
|
|
33
|
+
/** Legacy image field preserved for compatibility */
|
|
38
34
|
image?: string | string[];
|
|
39
35
|
/** ISO 8601 date string */
|
|
40
36
|
dateAdded?: string;
|
|
@@ -72,19 +68,18 @@ interface ParsedYield {
|
|
|
72
68
|
description?: string;
|
|
73
69
|
}
|
|
74
70
|
/**
|
|
75
|
-
* Time
|
|
76
|
-
*
|
|
71
|
+
* Time uses DurationMinutes format (vNext).
|
|
72
|
+
* Required total field with minutes.
|
|
77
73
|
*/
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
cookTime?: string;
|
|
74
|
+
interface Time {
|
|
75
|
+
total: DurationMinutes;
|
|
76
|
+
metadata?: Record<string, unknown>;
|
|
77
|
+
[k: `x-${string}`]: unknown;
|
|
78
|
+
}
|
|
79
|
+
interface DurationMinutes {
|
|
80
|
+
minutes: number;
|
|
81
|
+
metadata?: Record<string, unknown>;
|
|
82
|
+
[k: `x-${string}`]: unknown;
|
|
88
83
|
}
|
|
89
84
|
interface Equipment {
|
|
90
85
|
id?: string;
|
|
@@ -94,99 +89,144 @@ interface Equipment {
|
|
|
94
89
|
capacity?: Quantity$1;
|
|
95
90
|
scalingLimit?: number;
|
|
96
91
|
alternatives?: string[];
|
|
92
|
+
count?: number;
|
|
93
|
+
countScaling?: EquipmentCountScaling;
|
|
94
|
+
upgrades?: EquipmentUpgradeRule[];
|
|
97
95
|
}
|
|
98
96
|
interface Quantity$1 {
|
|
99
97
|
amount: number;
|
|
100
98
|
/** Unit string (e.g. "g", "cup") or null for count-based items (e.g. "2 eggs") */
|
|
101
99
|
unit: string | null;
|
|
102
100
|
}
|
|
101
|
+
type EquipmentCountScaling = 'fixed' | 'linear' | EquipmentThresholdScaling;
|
|
102
|
+
interface EquipmentThresholdScaling {
|
|
103
|
+
mode: 'threshold';
|
|
104
|
+
steps: EquipmentThresholdStep[];
|
|
105
|
+
}
|
|
106
|
+
interface EquipmentThresholdStep {
|
|
107
|
+
maxFactor: number;
|
|
108
|
+
count: number;
|
|
109
|
+
}
|
|
110
|
+
interface EquipmentUpgradeRule {
|
|
111
|
+
minFactor: number;
|
|
112
|
+
use: string;
|
|
113
|
+
}
|
|
114
|
+
interface EquipmentUpgradeRecommendation {
|
|
115
|
+
fromId: string;
|
|
116
|
+
use: string;
|
|
117
|
+
minFactor: number;
|
|
118
|
+
}
|
|
119
|
+
interface ScalingMetadata {
|
|
120
|
+
multiplier: number;
|
|
121
|
+
equipment?: {
|
|
122
|
+
upgrades: EquipmentUpgradeRecommendation[];
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
type ScaledRecipe = Recipe & {
|
|
126
|
+
scaling?: ScalingMetadata;
|
|
127
|
+
};
|
|
103
128
|
type IngredientItem = string | Ingredient$1 | IngredientSubsection;
|
|
104
129
|
interface IngredientSubsection {
|
|
105
|
-
|
|
106
|
-
|
|
130
|
+
section: string;
|
|
131
|
+
ingredients: IngredientItem[];
|
|
107
132
|
}
|
|
108
133
|
interface Ingredient$1 {
|
|
109
134
|
id?: string;
|
|
110
|
-
/**
|
|
111
|
-
|
|
135
|
+
/** Ingredient name (required in vNext) */
|
|
136
|
+
name: string;
|
|
112
137
|
quantity?: Quantity$1;
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
/** Required prep state (e.g. "diced") */
|
|
116
|
-
prep?: string;
|
|
117
|
-
prepAction?: string;
|
|
118
|
-
prepTime?: number;
|
|
138
|
+
/** Required prep state (e.g. "diced") or array of prep items */
|
|
139
|
+
prep?: string | string[];
|
|
119
140
|
/** ID of equipment where this ingredient goes */
|
|
120
141
|
destination?: string;
|
|
121
142
|
scaling?: Scaling;
|
|
122
|
-
critical?: boolean;
|
|
123
143
|
optional?: boolean;
|
|
124
144
|
notes?: string;
|
|
145
|
+
temperature?: Temperature;
|
|
146
|
+
metadata?: Record<string, unknown>;
|
|
147
|
+
[k: `x-${string}`]: unknown;
|
|
125
148
|
}
|
|
126
149
|
interface ParsedIngredient {
|
|
127
|
-
|
|
150
|
+
name: string;
|
|
128
151
|
quantity?: {
|
|
129
152
|
amount: number | null;
|
|
130
153
|
unit: string | null;
|
|
131
154
|
};
|
|
132
|
-
name?: string;
|
|
133
155
|
prep?: string;
|
|
134
156
|
optional?: boolean;
|
|
135
157
|
notes?: string;
|
|
136
158
|
scaling?: Scaling;
|
|
137
159
|
}
|
|
138
160
|
/**
|
|
139
|
-
* Intelligent Scaling Logic
|
|
161
|
+
* Intelligent Scaling Logic (vNext format)
|
|
140
162
|
* Defines how an ingredient behaves when the recipe yield changes.
|
|
141
163
|
*/
|
|
142
|
-
type Scaling = ScalingLinear | ScalingDiscrete | ScalingProportional | ScalingFixed | ScalingBakersPercentage;
|
|
164
|
+
type Scaling = ScalingLinear | ScalingDiscrete | ScalingProportional | ScalingFixed | ScalingToTaste | ScalingBakersPercentage;
|
|
143
165
|
interface ScalingBase {
|
|
144
166
|
min?: number;
|
|
145
167
|
max?: number;
|
|
146
168
|
}
|
|
147
169
|
interface ScalingLinear extends ScalingBase {
|
|
148
|
-
|
|
170
|
+
mode: "linear";
|
|
149
171
|
}
|
|
150
172
|
interface ScalingDiscrete extends ScalingBase {
|
|
151
|
-
|
|
152
|
-
|
|
173
|
+
mode: "discrete";
|
|
174
|
+
step?: number;
|
|
175
|
+
rounding?: "nearest" | "ceil" | "floor";
|
|
153
176
|
}
|
|
154
177
|
interface ScalingProportional extends ScalingBase {
|
|
155
|
-
|
|
178
|
+
mode: "proportional";
|
|
156
179
|
factor?: number;
|
|
157
180
|
}
|
|
158
181
|
interface ScalingFixed extends ScalingBase {
|
|
159
|
-
|
|
182
|
+
mode: "fixed";
|
|
183
|
+
}
|
|
184
|
+
interface ScalingToTaste {
|
|
185
|
+
mode: "toTaste";
|
|
160
186
|
}
|
|
161
|
-
interface ScalingBakersPercentage
|
|
162
|
-
|
|
187
|
+
interface ScalingBakersPercentage {
|
|
188
|
+
mode: "bakersPercent";
|
|
189
|
+
/** The percentage relative to the reference (e.g. 2 for 2%) */
|
|
190
|
+
percent: number;
|
|
163
191
|
/** The ID of the flour/base ingredient this is relative to */
|
|
164
|
-
|
|
165
|
-
/** The percentage relative to the reference (e.g. 0.02 for 2%) */
|
|
166
|
-
factor?: number;
|
|
192
|
+
of: string;
|
|
167
193
|
}
|
|
168
194
|
type InstructionItem = string | Instruction | InstructionSubsection;
|
|
169
195
|
interface InstructionSubsection {
|
|
170
|
-
|
|
171
|
-
|
|
196
|
+
section: string;
|
|
197
|
+
steps: InstructionItem[];
|
|
172
198
|
}
|
|
173
199
|
interface SoustackInstruction {
|
|
174
200
|
id?: string;
|
|
175
201
|
text: string;
|
|
176
|
-
destination?: string;
|
|
177
202
|
/** IDs of steps that must complete before this one starts */
|
|
178
203
|
dependsOn?: string[];
|
|
179
204
|
/** IDs of ingredients used in this step */
|
|
180
205
|
inputs?: string[];
|
|
206
|
+
/** IDs of techniques used in this step */
|
|
207
|
+
techniqueIds?: string[];
|
|
208
|
+
/** IDs of equipment used in this step */
|
|
209
|
+
usesEquipment?: string[];
|
|
181
210
|
timing?: StepTiming;
|
|
182
|
-
|
|
183
|
-
|
|
211
|
+
temperature?: Temperature;
|
|
212
|
+
images?: string[];
|
|
213
|
+
videos?: string[];
|
|
214
|
+
metadata?: Record<string, unknown>;
|
|
215
|
+
[k: `x-${string}`]: unknown;
|
|
184
216
|
}
|
|
185
217
|
type Instruction = SoustackInstruction;
|
|
186
218
|
interface StepTiming {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
219
|
+
activity: "active" | "passive";
|
|
220
|
+
duration?: DurationMinutes | DurationRange;
|
|
221
|
+
completionCue?: string;
|
|
222
|
+
metadata?: Record<string, unknown>;
|
|
223
|
+
[k: `x-${string}`]: unknown;
|
|
224
|
+
}
|
|
225
|
+
interface DurationRange {
|
|
226
|
+
minMinutes: number;
|
|
227
|
+
maxMinutes: number;
|
|
228
|
+
metadata?: Record<string, unknown>;
|
|
229
|
+
[k: `x-${string}`]: unknown;
|
|
190
230
|
}
|
|
191
231
|
interface Storage {
|
|
192
232
|
roomTemp?: StorageMethod;
|
|
@@ -225,24 +265,11 @@ interface NutritionFacts {
|
|
|
225
265
|
calories?: number;
|
|
226
266
|
protein_g?: number;
|
|
227
267
|
}
|
|
228
|
-
interface
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
interface TaxonomyModule {
|
|
234
|
-
keywords?: string[];
|
|
235
|
-
category?: string;
|
|
236
|
-
cuisine?: string;
|
|
237
|
-
}
|
|
238
|
-
interface MediaModule {
|
|
239
|
-
images?: string[];
|
|
240
|
-
videos?: string[];
|
|
241
|
-
}
|
|
242
|
-
interface TimesModule {
|
|
243
|
-
prepMinutes?: number;
|
|
244
|
-
cookMinutes?: number;
|
|
245
|
-
totalMinutes?: number;
|
|
268
|
+
interface Temperature {
|
|
269
|
+
value: number;
|
|
270
|
+
unit: "celsius" | "fahrenheit";
|
|
271
|
+
metadata?: Record<string, unknown>;
|
|
272
|
+
[k: `x-${string}`]: unknown;
|
|
246
273
|
}
|
|
247
274
|
|
|
248
275
|
interface ScaleRecipeOptions {
|
|
@@ -254,32 +281,76 @@ interface ScaleRecipeOptions {
|
|
|
254
281
|
}
|
|
255
282
|
declare function scaleRecipe(recipe: Recipe, options?: ScaleRecipeOptions): Recipe;
|
|
256
283
|
|
|
257
|
-
type
|
|
258
|
-
interface
|
|
284
|
+
type ConformanceSeverity = "error" | "warning";
|
|
285
|
+
interface ConformanceIssue {
|
|
286
|
+
code: string;
|
|
259
287
|
path: string;
|
|
260
288
|
message: string;
|
|
261
|
-
|
|
289
|
+
severity: ConformanceSeverity;
|
|
262
290
|
}
|
|
263
|
-
|
|
291
|
+
|
|
292
|
+
type ProfileName = "base" | "equipped" | "illustrated" | "lite" | "prepped" | "scalable" | "timed";
|
|
293
|
+
interface NormalizedError {
|
|
264
294
|
path: string;
|
|
265
295
|
message: string;
|
|
296
|
+
keyword?: string;
|
|
266
297
|
}
|
|
298
|
+
/**
|
|
299
|
+
* Validation modes for recipe validation.
|
|
300
|
+
* - "schema": JSON Schema only
|
|
301
|
+
* - "full": JSON Schema + semantic conformance checks
|
|
302
|
+
*/
|
|
303
|
+
type ValidateMode = "schema" | "full";
|
|
267
304
|
interface ValidateOptions {
|
|
268
305
|
profile?: ProfileName;
|
|
269
306
|
schema?: string;
|
|
270
307
|
collectAllErrors?: boolean;
|
|
308
|
+
mode?: ValidateMode;
|
|
309
|
+
includeNormalized?: boolean;
|
|
271
310
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
311
|
+
/**
|
|
312
|
+
* Result payload for recipe validation. Schema validation always runs first;
|
|
313
|
+
* conformance issues are only included when running in full mode.
|
|
314
|
+
*/
|
|
315
|
+
interface ValidateResult {
|
|
316
|
+
ok: boolean;
|
|
317
|
+
schemaErrors: NormalizedError[];
|
|
318
|
+
conformanceIssues: ConformanceIssue[];
|
|
319
|
+
warnings: string[];
|
|
320
|
+
normalizedRecipe?: Recipe;
|
|
277
321
|
}
|
|
278
|
-
|
|
322
|
+
/**
|
|
323
|
+
* Legacy validateRecipe function - now uses the new validateRecipeSchema internally
|
|
324
|
+
* but maintains backward compatibility with profile/stack-based validation
|
|
325
|
+
* Also includes semantic conformance validation.
|
|
326
|
+
*/
|
|
327
|
+
/**
|
|
328
|
+
* Validates a recipe with explicit validation modes.
|
|
329
|
+
* - mode="schema": JSON Schema only
|
|
330
|
+
* - mode="full": schema + semantic conformance (only if schema passes)
|
|
331
|
+
*/
|
|
332
|
+
declare function validateRecipe(input: any, options?: ValidateOptions): ValidateResult;
|
|
279
333
|
declare function detectProfiles(recipe: any): ProfileName[];
|
|
280
334
|
|
|
281
335
|
declare function fromSchemaOrg(input: unknown): Recipe | null;
|
|
282
336
|
|
|
337
|
+
interface NormalizationResult {
|
|
338
|
+
recipe: Recipe;
|
|
339
|
+
warnings: string[];
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Normalizes a recipe input to the current spec format:
|
|
343
|
+
* - Rejects inputs with legacy field (unsupported)
|
|
344
|
+
* - Converts legacy `stacks` array format to map format
|
|
345
|
+
* - Ensures `stacks` exists even if empty
|
|
346
|
+
* - Preserves existing `stacks` map format
|
|
347
|
+
*
|
|
348
|
+
* @param input - Raw recipe input (may have legacy formats)
|
|
349
|
+
* @returns Normalized recipe with warnings for any issues encountered
|
|
350
|
+
* @throws Error if input contains legacy field
|
|
351
|
+
*/
|
|
352
|
+
declare function normalizeRecipe(input: unknown): NormalizationResult;
|
|
353
|
+
|
|
283
354
|
interface SchemaOrgRecipe$1 {
|
|
284
355
|
'@context'?: string | Array<string | Record<string, unknown>> | Record<string, unknown>;
|
|
285
356
|
'@type'?: string | string[];
|
|
@@ -304,6 +375,7 @@ interface SchemaOrgRecipe$1 {
|
|
|
304
375
|
nutrition?: NutritionInformation;
|
|
305
376
|
video?: SchemaOrgImage;
|
|
306
377
|
'@graph'?: unknown;
|
|
378
|
+
$schema?: string;
|
|
307
379
|
}
|
|
308
380
|
type SchemaOrgIngredientList = string | string[];
|
|
309
381
|
type SchemaOrgInstructionList = string | HowToStep$1 | HowToSection | Array<string | HowToStep$1 | HowToSection>;
|
|
@@ -351,9 +423,9 @@ interface NutritionInformation {
|
|
|
351
423
|
/**
|
|
352
424
|
* Convert a Soustack recipe to Schema.org JSON-LD format.
|
|
353
425
|
*
|
|
354
|
-
* BREAKING CHANGE in v0.
|
|
355
|
-
* and only includes
|
|
356
|
-
*
|
|
426
|
+
* BREAKING CHANGE in v0.0.2: This function now targets the "minimal" profile
|
|
427
|
+
* and only includes stacks that are schemaOrgMappable (as defined in the
|
|
428
|
+
* stacks registry). Non-mappable stacks (e.g., nutrition@1, schedule@1)
|
|
357
429
|
* are excluded from the conversion.
|
|
358
430
|
*/
|
|
359
431
|
declare function toSchemaOrg(recipe: Recipe): SchemaOrgRecipe$1;
|
|
@@ -383,7 +455,7 @@ interface SchemaOrgRecipe {
|
|
|
383
455
|
|
|
384
456
|
declare function extractSchemaOrgRecipeFromHTML(html: string): SchemaOrgRecipe | null;
|
|
385
457
|
|
|
386
|
-
declare const SOUSTACK_SPEC_VERSION = "0.
|
|
458
|
+
declare const SOUSTACK_SPEC_VERSION = "0.0.2";
|
|
387
459
|
|
|
388
460
|
type ConvertTarget = 'metric';
|
|
389
461
|
type ConvertMode = 'volume' | 'mass';
|
|
@@ -448,4 +520,4 @@ interface MiseEnPlacePlan {
|
|
|
448
520
|
}
|
|
449
521
|
declare function miseEnPlace(ingredients: Ingredient[]): MiseEnPlacePlan;
|
|
450
522
|
|
|
451
|
-
export { type Alternative, type
|
|
523
|
+
export { type Alternative, type ConvertMode, type ConvertTarget, type ConvertedLineItem, type DurationMinutes, type DurationRange, type Equipment, type EquipmentCountScaling, type EquipmentThresholdScaling, type EquipmentThresholdStep, type EquipmentUpgradeRecommendation, type EquipmentUpgradeRule, type FrozenStorageMethod, type Ingredient$1 as Ingredient, type IngredientItem, type IngredientSubsection, type Instruction, type InstructionItem, type InstructionSubsection, type LineItem, type MakeAheadComponent, type Ingredient as MiseEnPlaceIngredient, type MiseEnPlacePlan, type Quantity as MiseEnPlaceQuantity, type MiseEnPlaceTask, MissingEquivalencyError, type NormalizationResult, type NutritionFacts, type ParsedIngredient, type ParsedYield, type Quantity$1 as Quantity, type Recipe, type RoundMode, SOUSTACK_SPEC_VERSION, type ScaledRecipe, type Scaling, type ScalingBakersPercentage, type ScalingBase, type ScalingDiscrete, type ScalingFixed, type ScalingLinear, type ScalingMetadata, type ScalingProportional, type ScalingToTaste, type Source, type SoustackInstruction, type SoustackRecipe, type StepTiming, type Storage, type StorageMethod, type Substitution, type Temperature, type Time, UnknownUnitError, UnsupportedConversionError, type ValidateMode, type ValidateResult, type Yield, convertLineItemToMetric, detectProfiles, extractSchemaOrgRecipeFromHTML, fromSchemaOrg, miseEnPlace, normalizeRecipe, scaleRecipe, toSchemaOrg, validateRecipe };
|