adapt-schemas 1.0.3 → 1.2.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.
@@ -15,11 +15,11 @@ jobs:
15
15
  id-token: write # to enable use of OIDC for trusted publishing and npm provenance
16
16
  steps:
17
17
  - name: Checkout
18
- uses: actions/checkout@v3
18
+ uses: actions/checkout@v4
19
19
  with:
20
20
  fetch-depth: 0
21
21
  - name: Setup Node.js
22
- uses: actions/setup-node@v3
22
+ uses: actions/setup-node@v4
23
23
  with:
24
24
  node-version: 'lts/*'
25
25
  - name: Update npm
package/lib/Schema.js CHANGED
@@ -373,6 +373,33 @@ class Schema extends EventEmitter {
373
373
  : s.default
374
374
  })
375
375
  }
376
+
377
+ /**
378
+ * Walks the built schema alongside data, returning fields matching a predicate.
379
+ * @param {Object} data - The data object to walk
380
+ * @param {Function} predicate - `(schemaField) => boolean`
381
+ * @param {Object} [schema] - Internal: schema properties to walk (defaults to built.properties)
382
+ * @param {string} [parentPath=''] - Internal: the slash-delimited path accumulated so far
383
+ * @returns {Array<Object>} Array of `{ path, key, data, value }` matches
384
+ */
385
+ walk (data, predicate, schema, parentPath = '') {
386
+ schema = schema ?? this.built.properties
387
+ const matches = []
388
+ for (const [key, val] of Object.entries(schema)) {
389
+ if (data[key] === undefined) continue
390
+ const currentPath = parentPath ? `${parentPath}/${key}` : key
391
+ if (val.properties) {
392
+ matches.push(...this.walk(data[key], predicate, val.properties, currentPath))
393
+ } else if (val?.items?.properties) {
394
+ data[key].forEach((item, i) => {
395
+ matches.push(...this.walk(item, predicate, val.items.properties, `${currentPath}/${i}`))
396
+ })
397
+ } else if (predicate(val)) {
398
+ matches.push({ path: currentPath, key, data, value: data[key] })
399
+ }
400
+ }
401
+ return matches
402
+ }
376
403
  }
377
404
 
378
405
  export default Schema
package/package.json CHANGED
@@ -1,6 +1,10 @@
1
1
  {
2
2
  "name": "adapt-schemas",
3
- "version": "1.0.3",
3
+ "repository": {
4
+ "type": "git",
5
+ "url": "https://github.com/cgkineo/adapt-schemas"
6
+ },
7
+ "version": "1.2.0",
4
8
  "description": "Standalone JSON Schema library for the Adapt framework",
5
9
  "type": "module",
6
10
  "main": "index.js",
package/test.js CHANGED
@@ -274,6 +274,27 @@ async function runTests () {
274
274
  await library.registerSchema(newSchemaPath)
275
275
  console.log('')
276
276
 
277
+ // Test 11: Schema.walk
278
+ console.log('Test 11: Schema.walk')
279
+ const courseSchema = await library.getSchema('course')
280
+ const walkData = {
281
+ title: 'Test',
282
+ description: 'A course',
283
+ _globals: {
284
+ _accessibility: {
285
+ _isEnabled: true,
286
+ skipNavigationText: 'Skip'
287
+ }
288
+ }
289
+ }
290
+ const stringFields = courseSchema.walk(walkData, val => val.type === 'string')
291
+ const paths = stringFields.map(r => r.path)
292
+ console.log(` ✓ Found ${stringFields.length} string fields: ${paths.join(', ')}`)
293
+ const hasTitle = paths.includes('title')
294
+ const hasNested = paths.includes('_globals/_accessibility/skipNavigationText')
295
+ console.log(` ✓ Includes top-level field: ${hasTitle}`)
296
+ console.log(` ✓ Includes nested field: ${hasNested}\n`)
297
+
277
298
  console.log('=== All tests passed! ===')
278
299
  } finally {
279
300
  if (!hasSpecifiedPath) {