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
@@ -0,0 +1,50 @@
1
+ {
2
+ "$schema": "https://soustack.spec/soustack.schema.json",
3
+ "stacks": {
4
+ "structured": 1,
5
+ "timed": 1
6
+ },
7
+ "name": "Rested dough",
8
+ "yield": {
9
+ "amount": 2,
10
+ "unit": "loaves"
11
+ },
12
+ "time": {
13
+ "total": {
14
+ "minutes": 180
15
+ }
16
+ },
17
+ "ingredients": [
18
+ {
19
+ "id": "f",
20
+ "name": "flour"
21
+ },
22
+ {
23
+ "id": "w",
24
+ "name": "water"
25
+ }
26
+ ],
27
+ "instructions": [
28
+ {
29
+ "id": "mix",
30
+ "text": "Mix flour and water",
31
+ "timing": {
32
+ "activity": "active",
33
+ "duration": {
34
+ "minutes": 10
35
+ }
36
+ }
37
+ },
38
+ {
39
+ "id": "rest",
40
+ "text": "Let the dough rest",
41
+ "dependsOn": [
42
+ "mix"
43
+ ],
44
+ "timing": {
45
+ "activity": "passive",
46
+ "completionCue": "doubled in size"
47
+ }
48
+ }
49
+ ]
50
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://soustack.spec/soustack.schema.json",
3
+ "stacks": {
4
+ "structured": 1,
5
+ "timed": 1
6
+ },
7
+ "name": "Bad Range",
8
+ "yield": {
9
+ "amount": 2,
10
+ "unit": "servings"
11
+ },
12
+ "time": {
13
+ "total": {
14
+ "minutes": 15
15
+ }
16
+ },
17
+ "ingredients": [
18
+ "water"
19
+ ],
20
+ "instructions": [
21
+ {
22
+ "id": "s1",
23
+ "text": "Wait",
24
+ "timing": {
25
+ "activity": "passive",
26
+ "duration": {
27
+ "minMinutes": 10,
28
+ "maxMinutes": 5
29
+ }
30
+ }
31
+ }
32
+ ]
33
+ }
@@ -0,0 +1,76 @@
1
+ {
2
+ "$schema": "https://soustack.spec/soustack.schema.json",
3
+ "stacks": {
4
+ "equipment": 1
5
+ },
6
+ "name": "Recipe with Scaling-Aware Equipment",
7
+ "yield": {
8
+ "amount": 1,
9
+ "unit": "serving"
10
+ },
11
+ "time": {
12
+ "total": {
13
+ "minutes": 30
14
+ }
15
+ },
16
+ "equipment": [
17
+ {
18
+ "id": "pan",
19
+ "name": "8-inch skillet",
20
+ "count": 1,
21
+ "countScaling": "fixed"
22
+ },
23
+ {
24
+ "id": "bowl",
25
+ "name": "Mixing bowl",
26
+ "count": 2,
27
+ "countScaling": "linear"
28
+ },
29
+ {
30
+ "id": "sheet_pan",
31
+ "name": "Baking sheet",
32
+ "count": 1,
33
+ "countScaling": {
34
+ "mode": "threshold",
35
+ "steps": [
36
+ {
37
+ "maxFactor": 1.0,
38
+ "count": 1
39
+ },
40
+ {
41
+ "maxFactor": 2.0,
42
+ "count": 2
43
+ },
44
+ {
45
+ "maxFactor": 4.0,
46
+ "count": 3
47
+ }
48
+ ]
49
+ }
50
+ },
51
+ {
52
+ "id": "skillet_small",
53
+ "name": "8-inch skillet",
54
+ "upgrades": [
55
+ {
56
+ "minFactor": 2.0,
57
+ "use": "skillet_large"
58
+ }
59
+ ]
60
+ },
61
+ {
62
+ "id": "skillet_large",
63
+ "name": "12-inch skillet"
64
+ }
65
+ ],
66
+ "ingredients": [
67
+ {
68
+ "id": "flour",
69
+ "name": "Flour"
70
+ }
71
+ ],
72
+ "instructions": [
73
+ "Mix ingredients",
74
+ "Bake"
75
+ ]
76
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "https://soustack.spec/soustack.schema.json",
3
+ "stacks": {
4
+ "equipment": 1
5
+ },
6
+ "name": "Simple Recipe with Equipment",
7
+ "yield": {
8
+ "amount": 1,
9
+ "unit": "serving"
10
+ },
11
+ "time": {
12
+ "total": {
13
+ "minutes": 30
14
+ }
15
+ },
16
+ "equipment": [
17
+ "mixing bowl",
18
+ "whisk",
19
+ "oven"
20
+ ],
21
+ "ingredients": [
22
+ {
23
+ "id": "flour",
24
+ "name": "Flour"
25
+ }
26
+ ],
27
+ "instructions": [
28
+ "Mix ingredients",
29
+ "Bake in oven"
30
+ ]
31
+ }
@@ -0,0 +1,47 @@
1
+ {
2
+ "$schema": "https://soustack.spec/soustack.schema.json",
3
+ "stacks": {
4
+ "equipment": 1,
5
+ "structured": 1
6
+ },
7
+ "name": "Recipe with Structured Equipment Usage",
8
+ "yield": {
9
+ "amount": 1,
10
+ "unit": "serving"
11
+ },
12
+ "time": {
13
+ "total": {
14
+ "minutes": 30
15
+ }
16
+ },
17
+ "equipment": [
18
+ {
19
+ "id": "skillet",
20
+ "name": "8-inch skillet"
21
+ },
22
+ {
23
+ "id": "spatula",
24
+ "name": "Spatula"
25
+ }
26
+ ],
27
+ "ingredients": [
28
+ {
29
+ "id": "meat",
30
+ "name": "Meat"
31
+ }
32
+ ],
33
+ "instructions": [
34
+ {
35
+ "id": "sear",
36
+ "text": "Sear the meat in the skillet",
37
+ "usesEquipment": [
38
+ "skillet",
39
+ "spatula"
40
+ ]
41
+ },
42
+ {
43
+ "id": "rest",
44
+ "text": "Let rest for 5 minutes"
45
+ }
46
+ ]
47
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "https://soustack.spec/soustack.schema.json",
3
+ "stacks": {
4
+ "prep": 1
5
+ },
6
+ "name": "Recipe with Basic Mise En Place",
7
+ "yield": {
8
+ "amount": 1,
9
+ "unit": "serving"
10
+ },
11
+ "time": {
12
+ "total": {
13
+ "minutes": 30
14
+ }
15
+ },
16
+ "ingredients": [
17
+ "onion",
18
+ "garlic"
19
+ ],
20
+ "instructions": [
21
+ "Cook the ingredients"
22
+ ],
23
+ "miseEnPlace": [
24
+ {
25
+ "text": "Finely dice the onion"
26
+ },
27
+ {
28
+ "text": "Mince the garlic"
29
+ }
30
+ ]
31
+ }
@@ -0,0 +1,51 @@
1
+ {
2
+ "$schema": "https://soustack.spec/soustack.schema.json",
3
+ "stacks": {
4
+ "prep": 1,
5
+ "referenced": 1,
6
+ "structured": 1,
7
+ "equipment": 1
8
+ },
9
+ "name": "Recipe with Mise En Place References",
10
+ "yield": {
11
+ "amount": 1,
12
+ "unit": "serving"
13
+ },
14
+ "time": {
15
+ "total": {
16
+ "minutes": 30
17
+ }
18
+ },
19
+ "equipment": [
20
+ {
21
+ "id": "knife",
22
+ "name": "Chef's knife"
23
+ }
24
+ ],
25
+ "ingredients": [
26
+ {
27
+ "id": "onion",
28
+ "name": "Onion"
29
+ }
30
+ ],
31
+ "instructions": [
32
+ {
33
+ "id": "cook",
34
+ "text": "Cook the onion",
35
+ "inputs": [
36
+ "onion"
37
+ ]
38
+ }
39
+ ],
40
+ "miseEnPlace": [
41
+ {
42
+ "text": "Dice the onion with a sharp knife",
43
+ "inputs": [
44
+ "onion"
45
+ ],
46
+ "usesEquipment": [
47
+ "knife"
48
+ ]
49
+ }
50
+ ]
51
+ }
@@ -0,0 +1,48 @@
1
+ {
2
+ "$schema": "https://soustack.spec/soustack.schema.json",
3
+ "stacks": {
4
+ "prep": 1,
5
+ "quantified": 1
6
+ },
7
+ "name": "Recipe with Ingredient Prep Strings",
8
+ "yield": {
9
+ "amount": 1,
10
+ "unit": "serving"
11
+ },
12
+ "time": {
13
+ "total": {
14
+ "minutes": 30
15
+ }
16
+ },
17
+ "ingredients": [
18
+ {
19
+ "id": "onion",
20
+ "name": "Onion",
21
+ "quantity": {
22
+ "amount": 1,
23
+ "unit": "medium"
24
+ },
25
+ "prep": "finely diced"
26
+ },
27
+ {
28
+ "id": "garlic",
29
+ "name": "Garlic",
30
+ "quantity": {
31
+ "amount": 2,
32
+ "unit": "cloves"
33
+ },
34
+ "prep": [
35
+ "peeled",
36
+ "minced"
37
+ ]
38
+ }
39
+ ],
40
+ "instructions": [
41
+ "Cook the ingredients"
42
+ ],
43
+ "miseEnPlace": [
44
+ {
45
+ "text": "Prepare ingredients as specified"
46
+ }
47
+ ]
48
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "$schema": "https://soustack.spec/soustack.schema.json",
3
+ "stacks": {
4
+ "prep": 1,
5
+ "quantified": 1
6
+ },
7
+ "name": "Recipe with Structured Prep Items",
8
+ "yield": {
9
+ "amount": 1,
10
+ "unit": "serving"
11
+ },
12
+ "time": {
13
+ "total": {
14
+ "minutes": 30
15
+ }
16
+ },
17
+ "ingredients": [
18
+ {
19
+ "id": "tomato",
20
+ "name": "Tomato",
21
+ "quantity": {
22
+ "amount": 2,
23
+ "unit": "medium"
24
+ },
25
+ "prep": [
26
+ {
27
+ "verb": "dice",
28
+ "detail": "fine"
29
+ },
30
+ {
31
+ "verb": "reserve",
32
+ "detail": "half for garnish"
33
+ }
34
+ ]
35
+ }
36
+ ],
37
+ "instructions": [
38
+ "Use the prepared ingredients"
39
+ ],
40
+ "miseEnPlace": [
41
+ {
42
+ "text": "Prepare ingredients as specified"
43
+ }
44
+ ]
45
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "$schema": "https://soustack.spec/soustack.schema.json",
3
+ "profile": "equipped",
4
+ "stacks": {
5
+ "equipment": 1
6
+ },
7
+ "name": "Simple Recipe with Equipment",
8
+ "yield": {
9
+ "amount": 2,
10
+ "unit": "servings"
11
+ },
12
+ "time": {
13
+ "total": {
14
+ "minutes": 15
15
+ }
16
+ },
17
+ "equipment": [
18
+ "mixing bowl",
19
+ "whisk"
20
+ ],
21
+ "ingredients": [
22
+ "flour",
23
+ "eggs"
24
+ ],
25
+ "instructions": [
26
+ "Mix ingredients in a bowl",
27
+ "Whisk until smooth"
28
+ ]
29
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "$schema": "https://soustack.spec/soustack.schema.json",
3
+ "profile": "prepped",
4
+ "stacks": {
5
+ "prep": 1
6
+ },
7
+ "name": "Prepped Profile Recipe",
8
+ "yield": {
9
+ "amount": 4,
10
+ "unit": "servings"
11
+ },
12
+ "time": {
13
+ "total": {
14
+ "minutes": 20
15
+ }
16
+ },
17
+ "ingredients": [
18
+ "onion",
19
+ "garlic"
20
+ ],
21
+ "instructions": [
22
+ "Cook the ingredients"
23
+ ],
24
+ "miseEnPlace": [
25
+ {
26
+ "text": "Finely dice the onion"
27
+ },
28
+ {
29
+ "text": "Mince the garlic"
30
+ }
31
+ ]
32
+ }
@@ -0,0 +1,61 @@
1
+ {
2
+ "$schema": "https://soustack.spec/soustack.schema.json",
3
+ "stacks": {
4
+ "quantified": 1
5
+ },
6
+ "name": "Nested Ingredient Sections",
7
+ "yield": {
8
+ "amount": 1,
9
+ "unit": "batch"
10
+ },
11
+ "time": {
12
+ "total": {
13
+ "minutes": 30
14
+ }
15
+ },
16
+ "ingredients": [
17
+ {
18
+ "section": "Dough",
19
+ "ingredients": [
20
+ {
21
+ "section": "Dry",
22
+ "ingredients": [
23
+ {
24
+ "id": "flour",
25
+ "name": "Flour",
26
+ "quantity": {
27
+ "amount": 500,
28
+ "unit": "g"
29
+ }
30
+ },
31
+ {
32
+ "id": "salt",
33
+ "name": "Salt",
34
+ "quantity": {
35
+ "amount": 10,
36
+ "unit": "g"
37
+ }
38
+ }
39
+ ]
40
+ },
41
+ {
42
+ "section": "Wet",
43
+ "ingredients": [
44
+ {
45
+ "id": "water",
46
+ "name": "Water",
47
+ "quantity": {
48
+ "amount": 300,
49
+ "unit": "ml"
50
+ }
51
+ }
52
+ ]
53
+ }
54
+ ]
55
+ }
56
+ ],
57
+ "instructions": [
58
+ "Mix ingredients",
59
+ "Knead dough"
60
+ ]
61
+ }
@@ -0,0 +1,67 @@
1
+ {
2
+ "$schema": "https://soustack.spec/soustack.schema.json",
3
+ "stacks": {
4
+ "quantified": 1,
5
+ "scaling": 1,
6
+ "structured": 1,
7
+ "referenced": 1
8
+ },
9
+ "name": "Referenced with Scaling",
10
+ "yield": {
11
+ "amount": 1,
12
+ "unit": "loaf"
13
+ },
14
+ "time": {
15
+ "total": {
16
+ "minutes": 60
17
+ }
18
+ },
19
+ "ingredients": [
20
+ {
21
+ "id": "flour",
22
+ "name": "Bread flour",
23
+ "quantity": {
24
+ "amount": 500,
25
+ "unit": "g"
26
+ }
27
+ },
28
+ {
29
+ "id": "water",
30
+ "name": "Water",
31
+ "quantity": {
32
+ "amount": 325,
33
+ "unit": "g"
34
+ },
35
+ "scaling": {
36
+ "mode": "bakersPercent",
37
+ "percent": 65,
38
+ "of": "flour"
39
+ }
40
+ }
41
+ ],
42
+ "instructions": [
43
+ {
44
+ "id": "mix",
45
+ "text": "Mix flour and water",
46
+ "inputs": [
47
+ "flour",
48
+ "water"
49
+ ]
50
+ },
51
+ {
52
+ "id": "bake",
53
+ "text": "Bake the bread",
54
+ "inputs": [
55
+ "flour",
56
+ "water"
57
+ ]
58
+ }
59
+ ],
60
+ "scaling": {
61
+ "discrete": {
62
+ "min": 1,
63
+ "max": 4,
64
+ "step": 1
65
+ }
66
+ }
67
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "https://soustack.spec/soustack.schema.json",
3
+ "stacks": {
4
+ "storage": 1
5
+ },
6
+ "name": "Soup with Simple Leftovers",
7
+ "ingredients": [
8
+ "soup"
9
+ ],
10
+ "instructions": [
11
+ "Cook the soup"
12
+ ],
13
+ "storage": {
14
+ "refrigerated": {
15
+ "duration": {
16
+ "iso8601": "P4D"
17
+ }
18
+ },
19
+ "leftovers": {
20
+ "notes": "Store in an airtight container.",
21
+ "reheat": [
22
+ "Microwave 2\u20133 minutes, stirring halfway.",
23
+ "Or warm in a skillet over medium heat with a splash of water."
24
+ ]
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,43 @@
1
+ {
2
+ "$schema": "https://soustack.spec/soustack.schema.json",
3
+ "stacks": {
4
+ "storage": 1
5
+ },
6
+ "name": "Casserole with Structured Reheating",
7
+ "ingredients": [
8
+ "casserole ingredients"
9
+ ],
10
+ "instructions": [
11
+ "Prepare the casserole"
12
+ ],
13
+ "storage": {
14
+ "frozen": {
15
+ "duration": {
16
+ "iso8601": "P2M"
17
+ }
18
+ },
19
+ "leftovers": {
20
+ "portioning": {
21
+ "notes": "Cool completely, then portion into containers."
22
+ },
23
+ "reheat": [
24
+ {
25
+ "method": "microwave",
26
+ "duration": {
27
+ "minMinutes": 2,
28
+ "maxMinutes": 3
29
+ },
30
+ "notes": "Stir halfway."
31
+ },
32
+ {
33
+ "method": "oven",
34
+ "temp": {
35
+ "value": 350,
36
+ "unit": "F"
37
+ },
38
+ "notes": "Cover and heat until hot throughout."
39
+ }
40
+ ]
41
+ }
42
+ }
43
+ }