soustack 0.2.3 → 0.3.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/index.d.mts CHANGED
@@ -1,10 +1,24 @@
1
1
  /**
2
- * Soustack Recipe Schema v0.2.1
2
+ * Soustack Recipe Schema v0.3.0
3
3
  * A portable, scalable, interoperable recipe format.
4
4
  */
5
5
  interface SoustackRecipe {
6
+ /** Document marker for Soustack recipes */
7
+ '@type'?: 'Recipe';
6
8
  /** Optional $schema pointer for profile-aware validation */
7
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;
8
22
  /** Unique identifier (slug or UUID) */
9
23
  id?: string;
10
24
  /** Optional display title */
@@ -77,25 +91,25 @@ interface Equipment {
77
91
  name: string;
78
92
  required?: boolean;
79
93
  label?: string;
80
- capacity?: Quantity;
94
+ capacity?: Quantity$1;
81
95
  scalingLimit?: number;
82
96
  alternatives?: string[];
83
97
  }
84
- interface Quantity {
98
+ interface Quantity$1 {
85
99
  amount: number;
86
100
  /** Unit string (e.g. "g", "cup") or null for count-based items (e.g. "2 eggs") */
87
101
  unit: string | null;
88
102
  }
89
- type IngredientItem = string | Ingredient | IngredientSubsection;
103
+ type IngredientItem = string | Ingredient$1 | IngredientSubsection;
90
104
  interface IngredientSubsection {
91
105
  subsection: string;
92
- items: (string | Ingredient)[];
106
+ items: (string | Ingredient$1)[];
93
107
  }
94
- interface Ingredient {
108
+ interface Ingredient$1 {
95
109
  id?: string;
96
110
  /** Full human-readable text (e.g. "2 cups flour") */
97
111
  item: string;
98
- quantity?: Quantity;
112
+ quantity?: Quantity$1;
99
113
  name?: string;
100
114
  aisle?: string;
101
115
  /** Required prep state (e.g. "diced") */
@@ -208,15 +222,27 @@ interface Alternative {
208
222
  dietary?: string[];
209
223
  }
210
224
  interface NutritionFacts {
211
- calories?: string;
212
- fatContent?: string;
213
- carbohydrateContent?: string;
214
- proteinContent?: string;
215
- fiberContent?: string;
216
- sugarContent?: string;
217
- sodiumContent?: string;
218
- servingSize?: string;
219
- [key: string]: string | number | null | string[] | undefined;
225
+ calories?: number;
226
+ protein_g?: number;
227
+ }
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;
220
246
  }
221
247
 
222
248
  interface ScaleRecipeOptions {
@@ -228,7 +254,7 @@ interface ScaleRecipeOptions {
228
254
  }
229
255
  declare function scaleRecipe(recipe: Recipe, options?: ScaleRecipeOptions): Recipe;
230
256
 
231
- type ProfileName = "base" | "cookable" | "scalable" | "quantified" | "illustrated" | "schedulable";
257
+ type ProfileName = "minimal" | "core";
232
258
  interface NormalizedError {
233
259
  path: string;
234
260
  message: string;
@@ -276,6 +302,7 @@ interface SchemaOrgRecipe$1 {
276
302
  datePublished?: string;
277
303
  dateModified?: string;
278
304
  nutrition?: NutritionInformation;
305
+ video?: SchemaOrgImage;
279
306
  '@graph'?: unknown;
280
307
  }
281
308
  type SchemaOrgIngredientList = string | string[];
@@ -321,6 +348,14 @@ interface NutritionInformation {
321
348
  [key: string]: string | number | null | undefined;
322
349
  }
323
350
 
351
+ /**
352
+ * Convert a Soustack recipe to Schema.org JSON-LD format.
353
+ *
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)
357
+ * are excluded from the conversion.
358
+ */
324
359
  declare function toSchemaOrg(recipe: Recipe): SchemaOrgRecipe$1;
325
360
 
326
361
  interface HowToStep {
@@ -348,6 +383,69 @@ interface SchemaOrgRecipe {
348
383
 
349
384
  declare function extractSchemaOrgRecipeFromHTML(html: string): SchemaOrgRecipe | null;
350
385
 
351
- declare const SOUSTACK_SPEC_VERSION = "0.2.1";
386
+ declare const SOUSTACK_SPEC_VERSION = "0.3.0";
387
+
388
+ type ConvertTarget = 'metric';
389
+ type ConvertMode = 'volume' | 'mass';
390
+ type RoundMode = 'none' | 'sane';
391
+ interface LineItem {
392
+ ingredient: string;
393
+ quantity: number;
394
+ unit: string | null;
395
+ }
396
+ interface ConvertedLineItem extends LineItem {
397
+ notes?: string;
398
+ }
399
+ declare class UnknownUnitError extends Error {
400
+ readonly unit: string;
401
+ constructor(unit: string);
402
+ }
403
+ declare class UnsupportedConversionError extends Error {
404
+ readonly unit: string;
405
+ readonly mode: ConvertMode;
406
+ constructor(unit: string, mode: ConvertMode);
407
+ }
408
+ declare class MissingEquivalencyError extends Error {
409
+ readonly ingredient: string;
410
+ readonly unit: string;
411
+ constructor(ingredient: string, unit: string);
412
+ }
413
+ declare function convertLineItemToMetric(item: LineItem, mode: ConvertMode, opts?: {
414
+ round?: RoundMode;
415
+ }): ConvertedLineItem;
416
+
417
+ interface Quantity {
418
+ amount: number;
419
+ unit?: string | null;
420
+ }
421
+ interface Ingredient {
422
+ id?: string;
423
+ item: string;
424
+ quantity?: Quantity;
425
+ name?: string;
426
+ prep?: string;
427
+ prepAction?: string;
428
+ prepActions?: string[];
429
+ form?: string;
430
+ prepTime?: number;
431
+ optional?: boolean;
432
+ notes?: string;
433
+ }
434
+ interface MiseEnPlaceTask {
435
+ category: 'prep' | 'state' | 'measure' | 'other';
436
+ action?: string;
437
+ form?: string;
438
+ items: Array<{
439
+ ingredient: string;
440
+ quantity?: Quantity;
441
+ optional?: boolean;
442
+ notes?: string;
443
+ }>;
444
+ }
445
+ interface MiseEnPlacePlan {
446
+ tasks: MiseEnPlaceTask[];
447
+ ungrouped: Ingredient[];
448
+ }
449
+ declare function miseEnPlace(ingredients: Ingredient[]): MiseEnPlacePlan;
352
450
 
353
- export { type Alternative, type Equipment, type FrozenStorageMethod, type Ingredient, type IngredientItem, type IngredientSubsection, type Instruction, type InstructionItem, type InstructionSubsection, type MakeAheadComponent, type NutritionFacts, type ParsedIngredient, type ParsedYield, type Quantity, type Recipe, 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 Time, type Yield, detectProfiles, extractSchemaOrgRecipeFromHTML, fromSchemaOrg, scaleRecipe, toSchemaOrg, validateRecipe };
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 };
package/dist/index.d.ts CHANGED
@@ -1,10 +1,24 @@
1
1
  /**
2
- * Soustack Recipe Schema v0.2.1
2
+ * Soustack Recipe Schema v0.3.0
3
3
  * A portable, scalable, interoperable recipe format.
4
4
  */
5
5
  interface SoustackRecipe {
6
+ /** Document marker for Soustack recipes */
7
+ '@type'?: 'Recipe';
6
8
  /** Optional $schema pointer for profile-aware validation */
7
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;
8
22
  /** Unique identifier (slug or UUID) */
9
23
  id?: string;
10
24
  /** Optional display title */
@@ -77,25 +91,25 @@ interface Equipment {
77
91
  name: string;
78
92
  required?: boolean;
79
93
  label?: string;
80
- capacity?: Quantity;
94
+ capacity?: Quantity$1;
81
95
  scalingLimit?: number;
82
96
  alternatives?: string[];
83
97
  }
84
- interface Quantity {
98
+ interface Quantity$1 {
85
99
  amount: number;
86
100
  /** Unit string (e.g. "g", "cup") or null for count-based items (e.g. "2 eggs") */
87
101
  unit: string | null;
88
102
  }
89
- type IngredientItem = string | Ingredient | IngredientSubsection;
103
+ type IngredientItem = string | Ingredient$1 | IngredientSubsection;
90
104
  interface IngredientSubsection {
91
105
  subsection: string;
92
- items: (string | Ingredient)[];
106
+ items: (string | Ingredient$1)[];
93
107
  }
94
- interface Ingredient {
108
+ interface Ingredient$1 {
95
109
  id?: string;
96
110
  /** Full human-readable text (e.g. "2 cups flour") */
97
111
  item: string;
98
- quantity?: Quantity;
112
+ quantity?: Quantity$1;
99
113
  name?: string;
100
114
  aisle?: string;
101
115
  /** Required prep state (e.g. "diced") */
@@ -208,15 +222,27 @@ interface Alternative {
208
222
  dietary?: string[];
209
223
  }
210
224
  interface NutritionFacts {
211
- calories?: string;
212
- fatContent?: string;
213
- carbohydrateContent?: string;
214
- proteinContent?: string;
215
- fiberContent?: string;
216
- sugarContent?: string;
217
- sodiumContent?: string;
218
- servingSize?: string;
219
- [key: string]: string | number | null | string[] | undefined;
225
+ calories?: number;
226
+ protein_g?: number;
227
+ }
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;
220
246
  }
221
247
 
222
248
  interface ScaleRecipeOptions {
@@ -228,7 +254,7 @@ interface ScaleRecipeOptions {
228
254
  }
229
255
  declare function scaleRecipe(recipe: Recipe, options?: ScaleRecipeOptions): Recipe;
230
256
 
231
- type ProfileName = "base" | "cookable" | "scalable" | "quantified" | "illustrated" | "schedulable";
257
+ type ProfileName = "minimal" | "core";
232
258
  interface NormalizedError {
233
259
  path: string;
234
260
  message: string;
@@ -276,6 +302,7 @@ interface SchemaOrgRecipe$1 {
276
302
  datePublished?: string;
277
303
  dateModified?: string;
278
304
  nutrition?: NutritionInformation;
305
+ video?: SchemaOrgImage;
279
306
  '@graph'?: unknown;
280
307
  }
281
308
  type SchemaOrgIngredientList = string | string[];
@@ -321,6 +348,14 @@ interface NutritionInformation {
321
348
  [key: string]: string | number | null | undefined;
322
349
  }
323
350
 
351
+ /**
352
+ * Convert a Soustack recipe to Schema.org JSON-LD format.
353
+ *
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)
357
+ * are excluded from the conversion.
358
+ */
324
359
  declare function toSchemaOrg(recipe: Recipe): SchemaOrgRecipe$1;
325
360
 
326
361
  interface HowToStep {
@@ -348,6 +383,69 @@ interface SchemaOrgRecipe {
348
383
 
349
384
  declare function extractSchemaOrgRecipeFromHTML(html: string): SchemaOrgRecipe | null;
350
385
 
351
- declare const SOUSTACK_SPEC_VERSION = "0.2.1";
386
+ declare const SOUSTACK_SPEC_VERSION = "0.3.0";
387
+
388
+ type ConvertTarget = 'metric';
389
+ type ConvertMode = 'volume' | 'mass';
390
+ type RoundMode = 'none' | 'sane';
391
+ interface LineItem {
392
+ ingredient: string;
393
+ quantity: number;
394
+ unit: string | null;
395
+ }
396
+ interface ConvertedLineItem extends LineItem {
397
+ notes?: string;
398
+ }
399
+ declare class UnknownUnitError extends Error {
400
+ readonly unit: string;
401
+ constructor(unit: string);
402
+ }
403
+ declare class UnsupportedConversionError extends Error {
404
+ readonly unit: string;
405
+ readonly mode: ConvertMode;
406
+ constructor(unit: string, mode: ConvertMode);
407
+ }
408
+ declare class MissingEquivalencyError extends Error {
409
+ readonly ingredient: string;
410
+ readonly unit: string;
411
+ constructor(ingredient: string, unit: string);
412
+ }
413
+ declare function convertLineItemToMetric(item: LineItem, mode: ConvertMode, opts?: {
414
+ round?: RoundMode;
415
+ }): ConvertedLineItem;
416
+
417
+ interface Quantity {
418
+ amount: number;
419
+ unit?: string | null;
420
+ }
421
+ interface Ingredient {
422
+ id?: string;
423
+ item: string;
424
+ quantity?: Quantity;
425
+ name?: string;
426
+ prep?: string;
427
+ prepAction?: string;
428
+ prepActions?: string[];
429
+ form?: string;
430
+ prepTime?: number;
431
+ optional?: boolean;
432
+ notes?: string;
433
+ }
434
+ interface MiseEnPlaceTask {
435
+ category: 'prep' | 'state' | 'measure' | 'other';
436
+ action?: string;
437
+ form?: string;
438
+ items: Array<{
439
+ ingredient: string;
440
+ quantity?: Quantity;
441
+ optional?: boolean;
442
+ notes?: string;
443
+ }>;
444
+ }
445
+ interface MiseEnPlacePlan {
446
+ tasks: MiseEnPlaceTask[];
447
+ ungrouped: Ingredient[];
448
+ }
449
+ declare function miseEnPlace(ingredients: Ingredient[]): MiseEnPlacePlan;
352
450
 
353
- export { type Alternative, type Equipment, type FrozenStorageMethod, type Ingredient, type IngredientItem, type IngredientSubsection, type Instruction, type InstructionItem, type InstructionSubsection, type MakeAheadComponent, type NutritionFacts, type ParsedIngredient, type ParsedYield, type Quantity, type Recipe, 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 Time, type Yield, detectProfiles, extractSchemaOrgRecipeFromHTML, fromSchemaOrg, scaleRecipe, toSchemaOrg, validateRecipe };
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 };