soustack 0.3.0 → 0.4.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/README.md CHANGED
@@ -37,7 +37,7 @@ npm install soustack
37
37
 
38
38
  ## What's Included
39
39
 
40
- - **Validation**: `validateRecipe()` validates Soustack JSON against the bundled schema.
40
+ - **Validation**: `validateRecipe()` validates Soustack JSON against the bundled schema and optional conformance checks.
41
41
  - **Scaling & Computation**: `scaleRecipe()` scales a recipe while honoring per-ingredient scaling rules and instruction timing.
42
42
  - **Schema.org Conversion**:
43
43
  - `fromSchemaOrg()` (Schema.org JSON-LD → Soustack)
@@ -54,15 +54,21 @@ Validate and scale a recipe in just a few lines:
54
54
  ```ts
55
55
  import { validateRecipe, scaleRecipe } from 'soustack';
56
56
 
57
- // Validate against the bundled Soustack schema
58
- const { valid, errors, warnings } = validateRecipe(recipe);
59
- if (!valid) {
60
- throw new Error(JSON.stringify(errors, null, 2));
57
+ // Validate against the bundled Soustack schema + conformance rules
58
+ const { ok, schemaErrors, conformanceIssues, warnings } = validateRecipe(recipe);
59
+ if (!ok) {
60
+ throw new Error(JSON.stringify({ schemaErrors, conformanceIssues }, null, 2));
61
61
  }
62
62
  if (warnings?.length) {
63
63
  console.warn('Non-blocking warnings', warnings);
64
64
  }
65
65
 
66
+ // Schema-only validation (skip conformance checks)
67
+ const schemaOnly = validateRecipe(recipe, { mode: 'schema' });
68
+ if (!schemaOnly.ok) {
69
+ console.error(schemaOnly.schemaErrors);
70
+ }
71
+
66
72
  // Scale to a new yield (multiplier, target yield, or servings)
67
73
  const scaled = scaleRecipe(recipe, { multiplier: 2 });
68
74
  ```
@@ -70,24 +76,29 @@ const scaled = scaleRecipe(recipe, { multiplier: 2 });
70
76
  ### Profile-aware validation
71
77
 
72
78
  Use profiles to enforce integration contracts. Available profiles:
73
- - **minimal**: Basic recipe structure with minimal requirements
74
- - **core**: Enhanced profile with structured ingredients and instructions
79
+ - **base**
80
+ - **equipped**
81
+ - **illustrated**
82
+ - **lite**
83
+ - **prepped**
84
+ - **scalable**
85
+ - **timed**
75
86
 
76
87
  ```ts
77
88
  import { detectProfiles, validateRecipe } from 'soustack';
78
89
 
79
90
  // Discover which profiles a recipe already satisfies
80
- const profiles = detectProfiles(recipe); // e.g. ['minimal', 'core']
91
+ const profiles = detectProfiles(recipe);
81
92
 
82
- // Validate with a specific profile (defaults to 'core' if not specified)
83
- const result = validateRecipe(recipe, { profile: 'minimal' });
84
- if (!result.valid) {
85
- console.error('Profile validation failed', result.errors);
93
+ // Validate with a specific profile
94
+ const result = validateRecipe(recipe, { profile: 'base' });
95
+ if (!result.ok) {
96
+ console.error('Profile validation failed', result.schemaErrors);
86
97
  }
87
98
 
88
99
  // Validate with modules
89
100
  const recipeWithModules = {
90
- profile: 'minimal',
101
+ profile: 'base',
91
102
  modules: ['nutrition@1', 'times@1'],
92
103
  name: 'Test Recipe',
93
104
  ingredients: ['1 cup flour'],
@@ -96,7 +107,7 @@ const recipeWithModules = {
96
107
  times: { prepMinutes: 10, cookMinutes: 20, totalMinutes: 30 }, // v0.3: uses *Minutes fields
97
108
  };
98
109
  const result2 = validateRecipe(recipeWithModules);
99
- // Validates using: base + minimal profile + nutrition@1 module + times@1 module
110
+ // Validates using: base + profile + nutrition@1 module + times@1 module
100
111
  // Module contract: if module is declared, payload must exist (and vice versa)
101
112
  ```
102
113
 
@@ -154,11 +165,11 @@ Soustack v0.3.0 uses a **composed validation model** where recipes are validated
154
165
 
155
166
  The validator:
156
167
  - **Base schema**: Defines the core recipe structure (`@type`, `name`, `ingredients`, `instructions`, `profile`, `modules`)
157
- - **Profile overlay**: Adds profile-specific requirements (e.g., `minimal` or `core`)
168
+ - **Profile overlay**: Adds profile-specific requirements (e.g., `base` or `lite`)
158
169
  - **Module overlays**: Each declared module adds its own validation rules
159
170
 
160
171
  **Defaults:**
161
- - If `profile` is missing, it defaults to `"core"`
172
+ - If `profile` is missing, it defaults to the schema bundle's configured default
162
173
  - If `modules` is missing, it defaults to `[]`
163
174
 
164
175
  **Module Contract:** Modules enforce a symmetric contract:
@@ -177,7 +188,7 @@ Modules are resolved to schema references using the pattern:
177
188
  The module registry (`schemas/registry/modules.json`) defines which modules are available and their properties, including:
178
189
  - `schemaOrgMappable`: Whether the module can be converted to Schema.org format
179
190
  - `minProfile`: Minimum profile required to use the module
180
- - `allowedOnMinimal`: Whether the module can be used with the minimal profile
191
+ - `allowedOnLite`: Whether the module can be used with the lite profile
181
192
 
182
193
  **Available Modules (v0.3.0):**
183
194
  - `attribution@1`: Source attribution (url, author, datePublished)
@@ -185,7 +196,7 @@ The module registry (`schemas/registry/modules.json`) defines which modules are
185
196
  - `media@1`: Images and videos (images, videos arrays)
186
197
  - `times@1`: Timing information (prepMinutes, cookMinutes, totalMinutes)
187
198
  - `nutrition@1`: Nutritional data (calories, protein_g as numbers)
188
- - `schedule@1`: Task scheduling (requires core profile, includes instruction dependencies)
199
+ - `schedule@1`: Task scheduling (requires timed profile, includes instruction dependencies)
189
200
 
190
201
  ## Programmatic Usage
191
202
 
@@ -204,9 +215,9 @@ import {
204
215
  } from 'soustack/scrape';
205
216
 
206
217
  // Validate a Soustack recipe JSON object with profile enforcement
207
- const validation = validateRecipe(recipe, { profile: 'core' });
208
- if (!validation.valid) {
209
- console.error(validation.errors);
218
+ const validation = validateRecipe(recipe, { profile: 'base' });
219
+ if (!validation.ok) {
220
+ console.error({ schemaErrors: validation.schemaErrors, conformanceIssues: validation.conformanceIssues });
210
221
  }
211
222
 
212
223
  // Scale a recipe to a target yield amount (returns a "computed recipe")
@@ -258,7 +269,7 @@ async function convert(url: string) {
258
269
 
259
270
  Use the helpers to move between Schema.org JSON-LD and Soustack's structured recipe format. The conversion automatically handles image normalization, supporting multiple image formats from Schema.org.
260
271
 
261
- **BREAKING CHANGE in v0.3.0:** `toSchemaOrg()` now targets the **minimal profile** and only includes modules that are marked as `schemaOrgMappable` in the modules registry. Non-mappable modules (e.g., `nutrition@1`, `schedule@1`) are excluded from the conversion.
272
+ **BREAKING CHANGE in v0.3.0:** `toSchemaOrg()` now targets the **lite profile** and only includes modules that are marked as `schemaOrgMappable` in the modules registry. Non-mappable modules (e.g., `nutrition@1`, `schedule@1`) are excluded from the conversion.
262
273
 
263
274
  ```ts
264
275
  import { fromSchemaOrg, toSchemaOrg, normalizeImage } from 'soustack';
@@ -361,10 +372,16 @@ const parsed = extractRecipeFromHTML(html);
361
372
 
362
373
  ```bash
363
374
  # Validate with profiles (JSON output for pipelines)
364
- npx soustack validate recipe.soustack.json --profile block --strict --json
375
+ npx soustack validate recipe.soustack.json --profile base --strict --json
376
+
377
+ # Schema-only validation (skip semantic conformance checks)
378
+ npx soustack validate recipe.soustack.json --schema-only
379
+
380
+ # Stable JSON conformance report for CI
381
+ npx soustack check recipe.soustack.json --json
365
382
 
366
383
  # Repo-wide test run (validates every *.soustack.json)
367
- npx soustack test --profile block
384
+ npx soustack test --profile base
368
385
 
369
386
  # Convert Schema.org ↔ Soustack
370
387
  npx soustack convert --from schemaorg --to soustack recipe.jsonld -o recipe.soustack.json