Skip to content

yetanalytics/xapi-schema

Repository files navigation

xapi-schema

https://github.com/yetanalytics/xapi-schema/actions/workflows/main.yml/badge.svg https://img.shields.io/badge/license-Eclipse-blue.svg https://img.shields.io/clojars/v/com.yetanalytics/xapi-schema.svg

Clojure(script) schema for Experience API 1.0.3. Provides validation of Statements and other xAPI objects.

Demo

You can use xapi-schema to validate (and generate) statements in real-time with this demo.

Getting Started

  1. Add to your project dependencies:
    [[com.yetanalytics/xapi-schema "1.2.1"]]
        
  2. Require in your project:
    (ns your-project.core
      (:require [xapi-schema.core :as xs]))
        

Usage

Clojure(script)

Validate a Statement or Statements in edn

(def statement
  {"id" "fd41c918-b88b-4b20-a0a5-a4c32391aaa0"
   "actor" {"objectType" "Agent"
            "name" "Project Tin Can API"
            "mbox" "mailto:user@example.com"}
   "verb" {"id" "http://example.com/xapi/verbs#sent-a-statement",
           "display" {"en-US" "sent"}}
   "object" {"id" "http://example.com/xapi/activity/simplestatement",
             "definition"
             {"name" {"en-US" "simple statement"}
              "description"
              {"en-US" "A simple Experience API statement. Note that the LRS
                does not need to have any prior information about the Actor (learner), the
                verb, or the Activity/object."}}}})

(xs/validate-statement-data statement) ;; => returns the statement

(xs/validate-statement-data [stmt1 stmt2 stmt3]) ;; => returns the statements

(let [bad-statement (dissoc statement "actor")]
  (xs/validate-statement-data bad-statement))  ;; => throws ExceptionInfo

Validate a Statement from JSON (Clojurescript)

(let [json-statement (clj->js statement)]
  (xs/validate-statement-data-js json-statement)) ;; => returns the statement

Validate a Statement from a JSON string (Clojure(script))

(def statement-str
  "{\"object\":{\"id\":\"http://example.com/xapi/activity/simplestatement\",
  \"definition\":{\"name\":{\"en-US\":\"simple statement\"},\"description\":
  {\"en-US\":\"A simple Experience API statement. Note that the LRS\\n
  does not need to have any prior information about the Actor (learner), the\\n
  verb, or the Activity/object.\"}}},\"verb\":{\"id\":\"http://example.com/xapi
  /verbs#sent-a-statement\",\"display\":{\"en-US\":\"sent\"}},\"id\":\"fd41c918-
  b88b-4b20-a0a5-a4c32391aaa0\",\"actor\":{\"mbox\":\"mailto:user@example.com\"
  ,\"name\":\"Project Tin Can API\",\"objectType\":\"Agent\"}}")

(xs/validate-statement-data statement-str) ;; => returns statement edn

‘Check’ a Statement

Checking a statement will return nil if it is valid, or a map of errors.

(xs/statement-checker statement) ;; => nil
(let [bad-statement (-> statement
                        (dissoc "actor")
                        (assoc "id" 123)]
  (xs/statement-checker bad-statement)))
  ;; => {:cljs.spec.alpha/problems (...

Use SubSchemata

All of the subschemata in xapi-schema.spec are valid Clojure Specs:

(ns your-project.core
  (:require [xapi-schema.core :as xs]
            [xapi-schema.spec :as json]
            [clojure.spec.alpha :as s]))
(s/explain-data ::json/agent {"mbox" "mailto:bob@example.com"}) ;; => nil

Generate Statements

You can use spec’s generation functions to generate conformant statements containing random data:

  1. Include the test.check dependency:
    [[com.yetanalytics/xapi-schema "1.0.0-alpha2"]
     [org.clojure/test.check "0.10.0-alpha2"]]
        
  2. Include the extra namespaces and generate!
    (ns your-project.core
      (:require [xapi-schema.spec :as xapispec]
                [clojure.spec.alpha :as s :include-macros true]
                [clojure.spec.gen.alpha :as sgen :include-macros true]
                 clojure.test.check.generators))
    (sgen/generate (s/gen ::xapispec/statement)) ;; => {"actor" {...
        

Plain ol’ JavaScript

If you want to use validations from JavaScript, first build the js: $ lein do cljx, cljsbuild once release. Then include the generated file, target/js/xapi_schema.js and invoke:

var statement_str = '{"id":"fd41c918-b88b-4b20-a0a5-a4c32391aaa0", "actor":{"objectType": "Agent","name":"Project Tin Can API","mbox":"mailto:user@example.com"},"verb":{"id":"http://example.com/xapi/verbs#sent-a-statement","display":{ "en-US":"sent" }},"object":{"id":"http://example.com/xapi/activity/simplestatement","definition":{"name":{ "en-US":"simple statement" },"description":{ "en-US":"A simple Experience API statement. Note that the LRS does not need to have any prior information about the Actor (learner), the verb, or the Activity/object." }}}}';
var statement_json = JSON.parse(s);
xapi_schema.core.validate_statement_data_js(statement_str); // => statement JSON
xapi_schema.core.validate_statement_data_js(statement_json); // => statement JSON

Testing

Clojure

$ make test-clj

ClojureScript

$ make test-cljs

Both

$ make ci

License

Copyright © 2015-2024 Yet Analytics, Inc.

Distributed under the Eclipse Public License, the same as Clojure. See the file LICENSE for details.