@soustack/spec 0.0.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/LICENSE +121 -0
- package/README.md +275 -0
- package/SOUSTACK_SPEC_VERSION +1 -0
- package/SPEC.md +226 -0
- package/defs/common.schema.json +46 -0
- package/defs/duration.schema.json +33 -0
- package/defs/entities.schema.json +111 -0
- package/defs/ingredientQuantified.schema.json +9 -0
- package/defs/quantity.schema.json +16 -0
- package/defs/scalingRule.schema.json +127 -0
- package/defs/temperature.schema.json +63 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/fixtures/content/illustrated-step.valid.json +24 -0
- package/fixtures/invalid/equipment-unknown-reference.invalid.json +38 -0
- package/fixtures/invalid/mise-en-place-unknown-equipment.invalid.json +37 -0
- package/fixtures/invalid/mise-en-place-unknown-input.invalid.json +41 -0
- package/fixtures/invalid/storage-leftovers-missing-method.invalid.json +31 -0
- package/fixtures/invalid/storage-leftovers-wrong-type.invalid.json +23 -0
- package/fixtures/level/base-full.valid.json +162 -0
- package/fixtures/level/base-missing-yield.invalid.json +12 -0
- package/fixtures/level/lite-min.valid.json +14 -0
- package/fixtures/profile/profile-base.valid.json +20 -0
- package/fixtures/profile/profile-equipped.valid.json +28 -0
- package/fixtures/profile/profile-illustrated.valid.json +28 -0
- package/fixtures/profile/profile-lite.valid.json +13 -0
- package/fixtures/profile/profile-prepped.valid.json +31 -0
- package/fixtures/profile/profile-scalable-missing-scaling.invalid.json +29 -0
- package/fixtures/profile/profile-scalable.valid.json +49 -0
- package/fixtures/profile/profile-timed-missing-structured.invalid.json +30 -0
- package/fixtures/scaling/bakers-percent-missing-ref.invalid.json +41 -0
- package/fixtures/scaling/bakers-percent.valid.json +51 -0
- package/fixtures/scaling/discrete-range.invalid.json +36 -0
- package/fixtures/scaling/missing-quantified.invalid.json +40 -0
- package/fixtures/scaling/reject-bakersPercentage.invalid.json +50 -0
- package/fixtures/stacks/compute-missing-timed.invalid.json +32 -0
- package/fixtures/stacks/dietary-no-signal.invalid.json +16 -0
- package/fixtures/stacks/illustrated-empty.invalid.json +13 -0
- package/fixtures/stacks/quantified-string.invalid.json +22 -0
- package/fixtures/stacks/referenced-missing-input.invalid.json +32 -0
- package/fixtures/stacks/storage-min.valid.json +20 -0
- package/fixtures/stacks/storage-no-duration.invalid.json +16 -0
- package/fixtures/stacks/timed-implies-structured.valid.json +50 -0
- package/fixtures/stacks/timed-range.invalid.json +33 -0
- package/fixtures/valid/equipment-scaling-rules.valid.json +76 -0
- package/fixtures/valid/equipment-strings.valid.json +31 -0
- package/fixtures/valid/equipment-structured-uses.valid.json +47 -0
- package/fixtures/valid/mise-en-place-basic.valid.json +31 -0
- package/fixtures/valid/mise-en-place-referenced-equipment.valid.json +51 -0
- package/fixtures/valid/prep-ingredient-strings.valid.json +48 -0
- package/fixtures/valid/prep-ingredient-structured.valid.json +45 -0
- package/fixtures/valid/profile-equipped.valid.json +29 -0
- package/fixtures/valid/profile-prepped.valid.json +32 -0
- package/fixtures/valid/quantified-nested-ingredient-sections.valid.json +61 -0
- package/fixtures/valid/referenced-scaling.valid.json +67 -0
- package/fixtures/valid/storage-leftovers-simple.valid.json +27 -0
- package/fixtures/valid/storage-leftovers-structured.valid.json +43 -0
- package/fixtures/valid/structured-nested-step-sections.valid.json +84 -0
- package/package.json +54 -0
- package/schemas/stacks-registry.schema.json +108 -0
- package/soustack.schema.json +2379 -0
- package/src/index.js +3 -0
- package/src/index.ts +3 -0
- package/stacks/compute.schema.json +7 -0
- package/stacks/compute@1.md +22 -0
- package/stacks/dietary.schema.json +45 -0
- package/stacks/dietary@1.md +24 -0
- package/stacks/equipment.schema.json +98 -0
- package/stacks/equipment@1.md +244 -0
- package/stacks/illustrated.schema.json +54 -0
- package/stacks/illustrated@1.md +24 -0
- package/stacks/prep.schema.json +76 -0
- package/stacks/prep@1.md +276 -0
- package/stacks/quantified.schema.json +74 -0
- package/stacks/quantified@1.md +24 -0
- package/stacks/referenced.schema.json +96 -0
- package/stacks/referenced@1.md +23 -0
- package/stacks/registry.json +112 -0
- package/stacks/scaling.schema.json +99 -0
- package/stacks/scaling@1.md +238 -0
- package/stacks/storage.schema.json +132 -0
- package/stacks/storage@1.md +256 -0
- package/stacks/structured.schema.json +48 -0
- package/stacks/structured@1.md +24 -0
- package/stacks/substitutions.schema.json +43 -0
- package/stacks/substitutions@1.md +24 -0
- package/stacks/techniques.schema.json +28 -0
- package/stacks/techniques@1.md +23 -0
- package/stacks/timed.schema.json +60 -0
- package/stacks/timed@1.md +23 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://spec.soustack.org/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://spec.soustack.org/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://spec.soustack.org/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
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://spec.soustack.org/soustack.schema.json",
|
|
3
|
+
"stacks": {
|
|
4
|
+
"structured": 1,
|
|
5
|
+
"timed": 1
|
|
6
|
+
},
|
|
7
|
+
"name": "Nested Step Sections",
|
|
8
|
+
"yield": {
|
|
9
|
+
"amount": 1,
|
|
10
|
+
"unit": "dish"
|
|
11
|
+
},
|
|
12
|
+
"time": {
|
|
13
|
+
"total": {
|
|
14
|
+
"minutes": 90
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"ingredients": [
|
|
18
|
+
{
|
|
19
|
+
"id": "flour",
|
|
20
|
+
"name": "Flour"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": "water",
|
|
24
|
+
"name": "Water"
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"instructions": [
|
|
28
|
+
{
|
|
29
|
+
"section": "Main",
|
|
30
|
+
"steps": [
|
|
31
|
+
{
|
|
32
|
+
"section": "Prep",
|
|
33
|
+
"steps": [
|
|
34
|
+
{
|
|
35
|
+
"id": "prep1",
|
|
36
|
+
"text": "Prepare ingredients",
|
|
37
|
+
"timing": {
|
|
38
|
+
"activity": "active",
|
|
39
|
+
"duration": {
|
|
40
|
+
"minutes": 10
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"id": "prep2",
|
|
46
|
+
"text": "Measure everything",
|
|
47
|
+
"timing": {
|
|
48
|
+
"activity": "active",
|
|
49
|
+
"duration": {
|
|
50
|
+
"minutes": 5
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"section": "Cooking",
|
|
58
|
+
"steps": [
|
|
59
|
+
{
|
|
60
|
+
"id": "cook1",
|
|
61
|
+
"text": "Mix everything together",
|
|
62
|
+
"timing": {
|
|
63
|
+
"activity": "active",
|
|
64
|
+
"duration": {
|
|
65
|
+
"minutes": 15
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"id": "cook2",
|
|
71
|
+
"text": "Cook until done",
|
|
72
|
+
"timing": {
|
|
73
|
+
"activity": "active",
|
|
74
|
+
"duration": {
|
|
75
|
+
"minutes": 30
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@soustack/spec",
|
|
3
|
+
"publishConfig": { "access": "public" },
|
|
4
|
+
"version": "0.0.2",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "CC0-1.0",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/RichardHerold/soustack-spec.git"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"soustack.schema.json",
|
|
13
|
+
"defs/",
|
|
14
|
+
"stacks/",
|
|
15
|
+
"schemas/",
|
|
16
|
+
"fixtures/",
|
|
17
|
+
"src/",
|
|
18
|
+
"dist/",
|
|
19
|
+
"SOUSTACK_SPEC_VERSION",
|
|
20
|
+
"SPEC.md",
|
|
21
|
+
"README.md"
|
|
22
|
+
],
|
|
23
|
+
"main": "./dist/index.js",
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"import": "./dist/index.js"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc -p tsconfig.json",
|
|
33
|
+
"prepack": "npm run build",
|
|
34
|
+
"guard": "node scripts/guard-no-legacy.mjs",
|
|
35
|
+
"guard:canonical-host": "node scripts/guard-canonical-host.mjs",
|
|
36
|
+
"check-refs": "node scripts/check-schema-refs.mjs",
|
|
37
|
+
"validate": "node scripts/validate-fixtures.mjs",
|
|
38
|
+
"verify:version": "node scripts/verify-version.mjs",
|
|
39
|
+
"verify:registry": "node scripts/validate-registry.mjs",
|
|
40
|
+
"verify:stack-docs": "node scripts/verify-stack-docs.mjs",
|
|
41
|
+
"build:schemas": "node scripts/generate-stack-gating.mjs",
|
|
42
|
+
"docs:sync": "node scripts/generate-docs-from-registry.mjs",
|
|
43
|
+
"verify:generated": "node scripts/verify-generated-clean.mjs",
|
|
44
|
+
"verify": "npm run verify:version && npm run verify:registry && npm run verify:stack-docs && npm run check-refs && npm run guard && npm run guard:canonical-host && npm run validate && npm run verify:generated",
|
|
45
|
+
"test": "npm run verify"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"typescript": "^5.9.3"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"ajv": "^8.17.1",
|
|
52
|
+
"ajv-formats": "^3.0.1"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "../schemas/stacks-registry.schema.json",
|
|
4
|
+
"title": "Soustack Stacks Registry Schema",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"$schema": { "type": "string" },
|
|
8
|
+
"registryVersion": { "type": "integer", "minimum": 1 },
|
|
9
|
+
"spec": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"properties": {
|
|
12
|
+
"name": { "type": "string" },
|
|
13
|
+
"currentSpecVersion": { "type": "string" },
|
|
14
|
+
"canonicalStacksFormat": { "type": "string", "enum": ["map"] }
|
|
15
|
+
},
|
|
16
|
+
"required": ["name", "currentSpecVersion", "canonicalStacksFormat"],
|
|
17
|
+
"additionalProperties": false
|
|
18
|
+
},
|
|
19
|
+
"profiles": {
|
|
20
|
+
"type": "object",
|
|
21
|
+
"propertyNames": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"pattern": "^[a-z][a-z0-9-]*$"
|
|
24
|
+
},
|
|
25
|
+
"additionalProperties": {
|
|
26
|
+
"type": "object",
|
|
27
|
+
"properties": {
|
|
28
|
+
"title": { "type": "string" },
|
|
29
|
+
"description": { "type": "string" },
|
|
30
|
+
"requiresProfiles": {
|
|
31
|
+
"type": "array",
|
|
32
|
+
"items": { "type": "string" }
|
|
33
|
+
},
|
|
34
|
+
"requiresStacks": {
|
|
35
|
+
"type": "array",
|
|
36
|
+
"items": { "type": "string" }
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"required": ["title", "description"],
|
|
40
|
+
"anyOf": [
|
|
41
|
+
{ "required": ["requiresProfiles"] },
|
|
42
|
+
{ "required": ["requiresStacks"] }
|
|
43
|
+
],
|
|
44
|
+
"additionalProperties": false
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"stacks": {
|
|
48
|
+
"type": "object",
|
|
49
|
+
"propertyNames": {
|
|
50
|
+
"anyOf": [
|
|
51
|
+
{
|
|
52
|
+
"type": "string",
|
|
53
|
+
"pattern": "^[a-z][a-z0-9-]*$"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"type": "string",
|
|
57
|
+
"pattern": "^x-[a-z0-9-]+(?:\\.[a-z0-9-]+)*$"
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
"additionalProperties": {
|
|
62
|
+
"type": "object",
|
|
63
|
+
"properties": {
|
|
64
|
+
"title": { "type": "string" },
|
|
65
|
+
"latestMajor": { "type": "integer", "minimum": 1 },
|
|
66
|
+
"requires": {
|
|
67
|
+
"type": "array",
|
|
68
|
+
"items": { "type": "string" }
|
|
69
|
+
},
|
|
70
|
+
"schema": {
|
|
71
|
+
"type": "object",
|
|
72
|
+
"properties": {
|
|
73
|
+
"major": {
|
|
74
|
+
"type": "object",
|
|
75
|
+
"propertyNames": {
|
|
76
|
+
"type": "string",
|
|
77
|
+
"pattern": "^[0-9]+$"
|
|
78
|
+
},
|
|
79
|
+
"additionalProperties": { "type": "string" }
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"required": ["major"],
|
|
83
|
+
"additionalProperties": false
|
|
84
|
+
},
|
|
85
|
+
"docs": {
|
|
86
|
+
"type": "object",
|
|
87
|
+
"properties": {
|
|
88
|
+
"major": {
|
|
89
|
+
"type": "object",
|
|
90
|
+
"propertyNames": {
|
|
91
|
+
"type": "string",
|
|
92
|
+
"pattern": "^[0-9]+$"
|
|
93
|
+
},
|
|
94
|
+
"additionalProperties": { "type": "string" }
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"required": ["major"],
|
|
98
|
+
"additionalProperties": false
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"required": ["title", "latestMajor", "requires", "schema"],
|
|
102
|
+
"additionalProperties": false
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"required": ["registryVersion", "spec", "profiles", "stacks"],
|
|
107
|
+
"additionalProperties": false
|
|
108
|
+
}
|