@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.
Files changed (92) hide show
  1. package/LICENSE +121 -0
  2. package/README.md +275 -0
  3. package/SOUSTACK_SPEC_VERSION +1 -0
  4. package/SPEC.md +226 -0
  5. package/defs/common.schema.json +46 -0
  6. package/defs/duration.schema.json +33 -0
  7. package/defs/entities.schema.json +111 -0
  8. package/defs/ingredientQuantified.schema.json +9 -0
  9. package/defs/quantity.schema.json +16 -0
  10. package/defs/scalingRule.schema.json +127 -0
  11. package/defs/temperature.schema.json +63 -0
  12. package/dist/index.d.ts +4 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +4 -0
  15. package/dist/index.js.map +1 -0
  16. package/fixtures/content/illustrated-step.valid.json +24 -0
  17. package/fixtures/invalid/equipment-unknown-reference.invalid.json +38 -0
  18. package/fixtures/invalid/mise-en-place-unknown-equipment.invalid.json +37 -0
  19. package/fixtures/invalid/mise-en-place-unknown-input.invalid.json +41 -0
  20. package/fixtures/invalid/storage-leftovers-missing-method.invalid.json +31 -0
  21. package/fixtures/invalid/storage-leftovers-wrong-type.invalid.json +23 -0
  22. package/fixtures/level/base-full.valid.json +162 -0
  23. package/fixtures/level/base-missing-yield.invalid.json +12 -0
  24. package/fixtures/level/lite-min.valid.json +14 -0
  25. package/fixtures/profile/profile-base.valid.json +20 -0
  26. package/fixtures/profile/profile-equipped.valid.json +28 -0
  27. package/fixtures/profile/profile-illustrated.valid.json +28 -0
  28. package/fixtures/profile/profile-lite.valid.json +13 -0
  29. package/fixtures/profile/profile-prepped.valid.json +31 -0
  30. package/fixtures/profile/profile-scalable-missing-scaling.invalid.json +29 -0
  31. package/fixtures/profile/profile-scalable.valid.json +49 -0
  32. package/fixtures/profile/profile-timed-missing-structured.invalid.json +30 -0
  33. package/fixtures/scaling/bakers-percent-missing-ref.invalid.json +41 -0
  34. package/fixtures/scaling/bakers-percent.valid.json +51 -0
  35. package/fixtures/scaling/discrete-range.invalid.json +36 -0
  36. package/fixtures/scaling/missing-quantified.invalid.json +40 -0
  37. package/fixtures/scaling/reject-bakersPercentage.invalid.json +50 -0
  38. package/fixtures/stacks/compute-missing-timed.invalid.json +32 -0
  39. package/fixtures/stacks/dietary-no-signal.invalid.json +16 -0
  40. package/fixtures/stacks/illustrated-empty.invalid.json +13 -0
  41. package/fixtures/stacks/quantified-string.invalid.json +22 -0
  42. package/fixtures/stacks/referenced-missing-input.invalid.json +32 -0
  43. package/fixtures/stacks/storage-min.valid.json +20 -0
  44. package/fixtures/stacks/storage-no-duration.invalid.json +16 -0
  45. package/fixtures/stacks/timed-implies-structured.valid.json +50 -0
  46. package/fixtures/stacks/timed-range.invalid.json +33 -0
  47. package/fixtures/valid/equipment-scaling-rules.valid.json +76 -0
  48. package/fixtures/valid/equipment-strings.valid.json +31 -0
  49. package/fixtures/valid/equipment-structured-uses.valid.json +47 -0
  50. package/fixtures/valid/mise-en-place-basic.valid.json +31 -0
  51. package/fixtures/valid/mise-en-place-referenced-equipment.valid.json +51 -0
  52. package/fixtures/valid/prep-ingredient-strings.valid.json +48 -0
  53. package/fixtures/valid/prep-ingredient-structured.valid.json +45 -0
  54. package/fixtures/valid/profile-equipped.valid.json +29 -0
  55. package/fixtures/valid/profile-prepped.valid.json +32 -0
  56. package/fixtures/valid/quantified-nested-ingredient-sections.valid.json +61 -0
  57. package/fixtures/valid/referenced-scaling.valid.json +67 -0
  58. package/fixtures/valid/storage-leftovers-simple.valid.json +27 -0
  59. package/fixtures/valid/storage-leftovers-structured.valid.json +43 -0
  60. package/fixtures/valid/structured-nested-step-sections.valid.json +84 -0
  61. package/package.json +54 -0
  62. package/schemas/stacks-registry.schema.json +108 -0
  63. package/soustack.schema.json +2379 -0
  64. package/src/index.js +3 -0
  65. package/src/index.ts +3 -0
  66. package/stacks/compute.schema.json +7 -0
  67. package/stacks/compute@1.md +22 -0
  68. package/stacks/dietary.schema.json +45 -0
  69. package/stacks/dietary@1.md +24 -0
  70. package/stacks/equipment.schema.json +98 -0
  71. package/stacks/equipment@1.md +244 -0
  72. package/stacks/illustrated.schema.json +54 -0
  73. package/stacks/illustrated@1.md +24 -0
  74. package/stacks/prep.schema.json +76 -0
  75. package/stacks/prep@1.md +276 -0
  76. package/stacks/quantified.schema.json +74 -0
  77. package/stacks/quantified@1.md +24 -0
  78. package/stacks/referenced.schema.json +96 -0
  79. package/stacks/referenced@1.md +23 -0
  80. package/stacks/registry.json +112 -0
  81. package/stacks/scaling.schema.json +99 -0
  82. package/stacks/scaling@1.md +238 -0
  83. package/stacks/storage.schema.json +132 -0
  84. package/stacks/storage@1.md +256 -0
  85. package/stacks/structured.schema.json +48 -0
  86. package/stacks/structured@1.md +24 -0
  87. package/stacks/substitutions.schema.json +43 -0
  88. package/stacks/substitutions@1.md +24 -0
  89. package/stacks/techniques.schema.json +28 -0
  90. package/stacks/techniques@1.md +23 -0
  91. package/stacks/timed.schema.json +60 -0
  92. 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
+ }