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.
Files changed (148) hide show
  1. package/README.md +44 -27
  2. package/dist/cli/index.js +5225 -992
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/index.d.mts +163 -91
  5. package/dist/index.d.ts +163 -91
  6. package/dist/index.js +5077 -1007
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.mjs +5076 -1007
  9. package/dist/index.mjs.map +1 -1
  10. package/dist/{scrape.d.mts → scrape/index.d.mts} +88 -74
  11. package/dist/{scrape.d.ts → scrape/index.d.ts} +88 -74
  12. package/dist/{scrape.js → scrape/index.js} +255 -124
  13. package/dist/scrape/index.js.map +1 -0
  14. package/dist/{scrape.mjs → scrape/index.mjs} +255 -124
  15. package/dist/scrape/index.mjs.map +1 -0
  16. package/package.json +21 -9
  17. package/spec/.sync-meta.json +149 -0
  18. package/spec/SOUSTACK_SPEC_VERSION +1 -0
  19. package/spec/defs/common.schema.json +46 -0
  20. package/spec/defs/duration.schema.json +33 -0
  21. package/spec/defs/entities.schema.json +111 -0
  22. package/spec/defs/ingredientQuantified.schema.json +9 -0
  23. package/spec/defs/quantity.schema.json +16 -0
  24. package/spec/defs/scalingRule.schema.json +127 -0
  25. package/spec/defs/temperature.schema.json +63 -0
  26. package/spec/fixtures/content/illustrated-step.valid.json +24 -0
  27. package/spec/fixtures/invalid/equipment-unknown-reference.invalid.json +38 -0
  28. package/spec/fixtures/invalid/mise-en-place-unknown-equipment.invalid.json +37 -0
  29. package/spec/fixtures/invalid/mise-en-place-unknown-input.invalid.json +41 -0
  30. package/spec/fixtures/invalid/storage-leftovers-missing-method.invalid.json +31 -0
  31. package/spec/fixtures/invalid/storage-leftovers-wrong-type.invalid.json +23 -0
  32. package/spec/fixtures/level/base-full.valid.json +162 -0
  33. package/spec/fixtures/level/base-missing-yield.invalid.json +12 -0
  34. package/spec/fixtures/level/lite-min.valid.json +14 -0
  35. package/spec/fixtures/profile/profile-base.valid.json +20 -0
  36. package/spec/fixtures/profile/profile-equipped.valid.json +28 -0
  37. package/spec/fixtures/profile/profile-illustrated.valid.json +28 -0
  38. package/spec/fixtures/profile/profile-lite.valid.json +13 -0
  39. package/spec/fixtures/profile/profile-prepped.valid.json +31 -0
  40. package/spec/fixtures/profile/profile-scalable-missing-scaling.invalid.json +29 -0
  41. package/spec/fixtures/profile/profile-scalable.valid.json +49 -0
  42. package/spec/fixtures/profile/profile-timed-missing-structured.invalid.json +30 -0
  43. package/spec/fixtures/scaling/bakers-percent-missing-ref.invalid.json +41 -0
  44. package/spec/fixtures/scaling/bakers-percent.valid.json +51 -0
  45. package/spec/fixtures/scaling/discrete-range.invalid.json +36 -0
  46. package/spec/fixtures/scaling/missing-quantified.invalid.json +40 -0
  47. package/spec/fixtures/scaling/reject-bakersPercentage.invalid.json +50 -0
  48. package/spec/fixtures/stacks/compute-missing-timed.invalid.json +32 -0
  49. package/spec/fixtures/stacks/dietary-no-signal.invalid.json +16 -0
  50. package/spec/fixtures/stacks/illustrated-empty.invalid.json +13 -0
  51. package/spec/fixtures/stacks/quantified-string.invalid.json +22 -0
  52. package/spec/fixtures/stacks/referenced-missing-input.invalid.json +32 -0
  53. package/spec/fixtures/stacks/storage-min.valid.json +20 -0
  54. package/spec/fixtures/stacks/storage-no-duration.invalid.json +16 -0
  55. package/spec/fixtures/stacks/timed-implies-structured.valid.json +50 -0
  56. package/spec/fixtures/stacks/timed-range.invalid.json +33 -0
  57. package/spec/fixtures/valid/equipment-scaling-rules.valid.json +76 -0
  58. package/spec/fixtures/valid/equipment-strings.valid.json +31 -0
  59. package/spec/fixtures/valid/equipment-structured-uses.valid.json +47 -0
  60. package/spec/fixtures/valid/mise-en-place-basic.valid.json +31 -0
  61. package/spec/fixtures/valid/mise-en-place-referenced-equipment.valid.json +51 -0
  62. package/spec/fixtures/valid/prep-ingredient-strings.valid.json +48 -0
  63. package/spec/fixtures/valid/prep-ingredient-structured.valid.json +45 -0
  64. package/spec/fixtures/valid/profile-equipped.valid.json +29 -0
  65. package/spec/fixtures/valid/profile-prepped.valid.json +32 -0
  66. package/spec/fixtures/valid/quantified-nested-ingredient-sections.valid.json +61 -0
  67. package/spec/fixtures/valid/referenced-scaling.valid.json +67 -0
  68. package/spec/fixtures/valid/storage-leftovers-simple.valid.json +27 -0
  69. package/spec/fixtures/valid/storage-leftovers-structured.valid.json +43 -0
  70. package/spec/fixtures/valid/structured-nested-step-sections.valid.json +84 -0
  71. package/spec/schemas/stacks-registry.schema.json +108 -0
  72. package/spec/soustack.schema.json +2379 -0
  73. package/spec/stacks/compute.schema.json +7 -0
  74. package/spec/stacks/compute@1.md +22 -0
  75. package/spec/stacks/dietary.schema.json +45 -0
  76. package/spec/stacks/dietary@1.md +24 -0
  77. package/spec/stacks/equipment.schema.json +98 -0
  78. package/spec/stacks/equipment@1.md +244 -0
  79. package/spec/stacks/illustrated.schema.json +54 -0
  80. package/spec/stacks/illustrated@1.md +24 -0
  81. package/spec/stacks/prep.schema.json +76 -0
  82. package/spec/stacks/prep@1.md +276 -0
  83. package/spec/stacks/quantified.schema.json +74 -0
  84. package/spec/stacks/quantified@1.md +24 -0
  85. package/spec/stacks/referenced.schema.json +96 -0
  86. package/spec/stacks/referenced@1.md +23 -0
  87. package/spec/stacks/registry.json +112 -0
  88. package/spec/stacks/scaling.schema.json +99 -0
  89. package/spec/stacks/scaling@1.md +238 -0
  90. package/spec/stacks/storage.schema.json +132 -0
  91. package/spec/stacks/storage@1.md +256 -0
  92. package/spec/stacks/structured.schema.json +48 -0
  93. package/spec/stacks/structured@1.md +24 -0
  94. package/spec/stacks/substitutions.schema.json +43 -0
  95. package/spec/stacks/substitutions@1.md +24 -0
  96. package/spec/stacks/techniques.schema.json +28 -0
  97. package/spec/stacks/techniques@1.md +23 -0
  98. package/spec/stacks/timed.schema.json +60 -0
  99. package/spec/stacks/timed@1.md +23 -0
  100. package/src/defs/common.schema.json +46 -0
  101. package/src/defs/duration.schema.json +33 -0
  102. package/src/defs/entities.schema.json +111 -0
  103. package/src/defs/ingredientQuantified.schema.json +9 -0
  104. package/src/defs/quantity.schema.json +16 -0
  105. package/src/defs/scalingRule.schema.json +127 -0
  106. package/src/defs/temperature.schema.json +63 -0
  107. package/src/profiles/base.schema.json +2 -2
  108. package/src/profiles/equipped.schema.json +10 -0
  109. package/src/profiles/illustrated.schema.json +4 -4
  110. package/src/profiles/lite.schema.json +10 -0
  111. package/src/profiles/prepped.schema.json +10 -0
  112. package/src/profiles/scalable.schema.json +6 -6
  113. package/src/profiles/timed.schema.json +10 -0
  114. package/src/schema.json +2271 -248
  115. package/src/schemas/stacks-registry.schema.json +108 -0
  116. package/src/soustack.schema.json +2271 -248
  117. package/src/stacks/compute.schema.json +7 -0
  118. package/src/stacks/compute@1.md +22 -0
  119. package/src/stacks/dietary.schema.json +45 -0
  120. package/src/stacks/dietary@1.md +24 -0
  121. package/src/stacks/equipment.schema.json +98 -0
  122. package/src/stacks/equipment@1.md +244 -0
  123. package/src/stacks/illustrated.schema.json +54 -0
  124. package/src/stacks/illustrated@1.md +24 -0
  125. package/src/stacks/prep.schema.json +76 -0
  126. package/src/stacks/prep@1.md +276 -0
  127. package/src/stacks/quantified.schema.json +74 -0
  128. package/src/stacks/quantified@1.md +24 -0
  129. package/src/stacks/referenced.schema.json +96 -0
  130. package/src/stacks/referenced@1.md +23 -0
  131. package/src/stacks/registry.json +112 -0
  132. package/src/stacks/scaling.schema.json +99 -0
  133. package/src/stacks/scaling@1.md +238 -0
  134. package/src/stacks/storage.schema.json +132 -0
  135. package/src/stacks/storage@1.md +256 -0
  136. package/src/stacks/structured.schema.json +48 -0
  137. package/src/stacks/structured@1.md +24 -0
  138. package/src/stacks/substitutions.schema.json +43 -0
  139. package/src/stacks/substitutions@1.md +24 -0
  140. package/src/stacks/techniques.schema.json +28 -0
  141. package/src/stacks/techniques@1.md +23 -0
  142. package/src/stacks/timed.schema.json +60 -0
  143. package/src/stacks/timed@1.md +23 -0
  144. package/dist/scrape.js.map +0 -1
  145. package/dist/scrape.mjs.map +0 -1
  146. package/src/profiles/cookable.schema.json +0 -18
  147. package/src/profiles/quantified.schema.json +0 -43
  148. 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.3.0
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?: string;
12
- /** Enabled module identifiers (e.g., "nutrition@1") */
13
- modules?: string[];
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 can be structured (machine-readable) or simple (strings).
76
- * Structured time takes precedence if both exist.
71
+ * Time uses DurationMinutes format (vNext).
72
+ * Required total field with minutes.
77
73
  */
78
- type Time = StructuredTime | SimpleTime;
79
- interface StructuredTime {
80
- prep?: number;
81
- active?: number;
82
- passive?: number;
83
- total?: number;
84
- }
85
- interface SimpleTime {
86
- prepTime?: string;
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
- subsection: string;
106
- items: (string | Ingredient$1)[];
130
+ section: string;
131
+ ingredients: IngredientItem[];
107
132
  }
108
133
  interface Ingredient$1 {
109
134
  id?: string;
110
- /** Full human-readable text (e.g. "2 cups flour") */
111
- item: string;
135
+ /** Ingredient name (required in vNext) */
136
+ name: string;
112
137
  quantity?: Quantity$1;
113
- name?: string;
114
- aisle?: string;
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
- item: string;
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
- type: "linear";
170
+ mode: "linear";
149
171
  }
150
172
  interface ScalingDiscrete extends ScalingBase {
151
- type: "discrete";
152
- roundTo?: number;
173
+ mode: "discrete";
174
+ step?: number;
175
+ rounding?: "nearest" | "ceil" | "floor";
153
176
  }
154
177
  interface ScalingProportional extends ScalingBase {
155
- type: "proportional";
178
+ mode: "proportional";
156
179
  factor?: number;
157
180
  }
158
181
  interface ScalingFixed extends ScalingBase {
159
- type: "fixed";
182
+ mode: "fixed";
183
+ }
184
+ interface ScalingToTaste {
185
+ mode: "toTaste";
160
186
  }
161
- interface ScalingBakersPercentage extends ScalingBase {
162
- type: 'bakers_percentage';
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
- referenceId: string;
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
- subsection: string;
171
- items: (string | Instruction)[];
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
- /** Optional image URL for this instruction */
183
- image?: string;
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
- duration: number | string;
188
- type: "active" | "passive";
189
- scaling?: "linear" | "fixed" | "sqrt";
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 AttributionModule {
229
- url?: string;
230
- author?: string;
231
- datePublished?: string;
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 ProfileName = "minimal" | "core";
258
- interface NormalizedError {
284
+ type ConformanceSeverity = "error" | "warning";
285
+ interface ConformanceIssue {
286
+ code: string;
259
287
  path: string;
260
288
  message: string;
261
- keyword?: string;
289
+ severity: ConformanceSeverity;
262
290
  }
263
- interface NormalizedWarning {
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
- interface ValidationResult {
273
- valid: boolean;
274
- errors: NormalizedError[];
275
- warnings: NormalizedWarning[];
276
- normalized?: Recipe;
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
- declare function validateRecipe(input: any, options?: ValidateOptions): ValidationResult;
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.3.0: This function now targets the "minimal" profile
355
- * and only includes modules that are schemaOrgMappable (as defined in the
356
- * modules registry). Non-mappable modules (e.g., nutrition@1, schedule@1)
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.3.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 AttributionModule, type ConvertMode, type ConvertTarget, type ConvertedLineItem, type Equipment, type FrozenStorageMethod, type Ingredient$1 as Ingredient, type IngredientItem, type IngredientSubsection, type Instruction, type InstructionItem, type InstructionSubsection, type LineItem, type MakeAheadComponent, type MediaModule, type Ingredient as MiseEnPlaceIngredient, type MiseEnPlacePlan, type Quantity as MiseEnPlaceQuantity, type MiseEnPlaceTask, MissingEquivalencyError, type NutritionFacts, type ParsedIngredient, type ParsedYield, type Quantity$1 as Quantity, type Recipe, type RoundMode, SOUSTACK_SPEC_VERSION, type Scaling, type ScalingBakersPercentage, type ScalingBase, type ScalingDiscrete, type ScalingFixed, type ScalingLinear, type ScalingProportional, type SimpleTime, type Source, type SoustackInstruction, type SoustackRecipe, type StepTiming, type Storage, type StorageMethod, type StructuredTime, type Substitution, type TaxonomyModule, type Time, type TimesModule, UnknownUnitError, UnsupportedConversionError, type Yield, convertLineItemToMetric, detectProfiles, extractSchemaOrgRecipeFromHTML, fromSchemaOrg, miseEnPlace, scaleRecipe, toSchemaOrg, validateRecipe };
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 };