lms-api 1.2.9 → 1.3.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.
- checksums.yaml +4 -4
- data/lib/canvas_api.rb +4 -0
- data/lib/canvas_api/builder.rb +59 -0
- data/lib/canvas_api/graphql_helpers.rb +99 -0
- data/lib/canvas_api/js_helpers.rb +54 -0
- data/lib/canvas_api/render.rb +73 -0
- data/lib/canvas_api/ruby_helpers.rb +9 -0
- data/lib/canvas_api/templates/constant.erb +10 -0
- data/lib/canvas_api/templates/constants.erb +4 -0
- data/lib/canvas_api/templates/graphql_model.erb +9 -0
- data/lib/canvas_api/templates/graphql_mutation.erb +0 -0
- data/lib/canvas_api/templates/graphql_mutations.erb +6 -0
- data/lib/canvas_api/templates/graphql_queries.erb +7 -0
- data/lib/canvas_api/templates/graphql_query.erb +7 -0
- data/lib/canvas_api/templates/graphql_types.erb +100 -0
- data/lib/canvas_api/templates/js_url.erb +1 -0
- data/lib/canvas_api/templates/js_urls.erb +3 -0
- data/lib/canvas_api/templates/rb_url.erb +1 -0
- data/lib/canvas_api/templates/rb_urls.erb +5 -0
- data/lib/lms/canvas.rb +2 -1
- data/lib/lms/version.rb +1 -1
- metadata +21 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 777bf9afd9565fde961baae2844dc52c76805923
|
4
|
+
data.tar.gz: fac9b9652c3bd22324495f1773bac632299c89d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a1b01e99e069189e1ffa1904946f44975f01dd47aaf4c6da0e6fe4d050823edfd2cbbf5edc888d8d501fdf5c049b851941c93c0ba44526ac96b4cf18878394d
|
7
|
+
data.tar.gz: f4bad4474f786009e32df7aec3a916a0b6e3a49ee30f2f30c72976394470f2778f4be7bba5a60fa00b76b36c80ec8727cc8505a951abcfd4ea6103f86b9a9601
|
data/lib/canvas_api.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require "canvas_api/render"
|
2
|
+
|
3
|
+
module CanvasApi
|
4
|
+
|
5
|
+
class Builder
|
6
|
+
|
7
|
+
#
|
8
|
+
# project_root: This is the directory where the canvas_urls.rb file will be written. This file contains all urls and functions for access to the Canvas API from this gem (lms_api).
|
9
|
+
# client_app_path: This where all client side Javascript for accessing the Canvas API will be written.
|
10
|
+
# server_app_path: This is where all server side Javascript for accessing the Canvas API will be written. Currently, this is generating GraphQL for Javascript
|
11
|
+
#
|
12
|
+
def self.build(project_root, client_app_path, server_app_path)
|
13
|
+
endpoint = "https://canvas.instructure.com/doc/api"
|
14
|
+
directory = HTTParty.get("#{endpoint}/api-docs.json")
|
15
|
+
|
16
|
+
lms_urls_rb = []
|
17
|
+
lms_urls_js = []
|
18
|
+
models = []
|
19
|
+
queries = []
|
20
|
+
mutations = []
|
21
|
+
directory["apis"].each do |api|
|
22
|
+
puts "Generating #{api['description']}"
|
23
|
+
resource = HTTParty.get("#{endpoint}#{api['path']}")
|
24
|
+
constants = []
|
25
|
+
resource["apis"].each do |resource_api|
|
26
|
+
resource_api["operations"].each do |operation|
|
27
|
+
parameters = operation["parameters"]
|
28
|
+
constants << CanvasApi::Render.new("./templates/constant.erb", api, resource, resource_api, operation, parameters, nil, nil).render
|
29
|
+
lms_urls_rb << CanvasApi::Render.new("./templates/rb_url.erb", api, resource, resource_api, operation, parameters, nil, nil).render
|
30
|
+
lms_urls_js << CanvasApi::Render.new("./templates/js_url.erb", api, resource, resource_api, operation, parameters, nil, nil).render
|
31
|
+
if "GET" == operation["method"].upcase
|
32
|
+
queries << CanvasApi::Render.new("./templates/graphql_query.erb", api, resource, resource_api, operation, parameters, nil, nil).render
|
33
|
+
else
|
34
|
+
mutations << CanvasApi::Render.new("./templates/graphql_mutation.erb", api, resource, resource_api, operation, parameters, nil, nil).render
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
resource["models"].map do |_name, model|
|
39
|
+
if model["properties"] # Don't generate models without properties
|
40
|
+
models << CanvasApi::Render.new("./templates/graphql_model.erb", api, resource, nil, nil, nil, nil, model).render
|
41
|
+
end
|
42
|
+
end
|
43
|
+
# Generate one file of constants for every LMS API
|
44
|
+
constants_renderer = CanvasApi::Render.new("./templates/constants.erb", api, resource, nil, nil, nil, constants, nil)
|
45
|
+
constants_renderer.save("#{client_app_path}/#{constants_renderer.name}.js")
|
46
|
+
end
|
47
|
+
|
48
|
+
CanvasApi::Render.new("./templates/rb_urls.erb", nil, nil, nil, nil, nil, lms_urls_rb, nil).save("#{project_root}/lib/lms/canvas_urls.rb")
|
49
|
+
CanvasApi::Render.new("./templates/js_urls.erb", nil, nil, nil, nil, nil, lms_urls_js, nil).save("#{server_app_path}/lib/canvas/urls.js")
|
50
|
+
|
51
|
+
# GraphQL - still not complete
|
52
|
+
CanvasApi::Render.new("./templates/graphql_types.erb", nil, nil, nil, nil, nil, models.compact, nil).save("#{server_app_path}/lib/canvas/graphql_types.js")
|
53
|
+
CanvasApi::Render.new("./templates/graphql_queries.erb", nil, nil, nil, nil, nil, queries, nil).save("#{server_app_path}/lib/canvas/graphql_queries.js")
|
54
|
+
CanvasApi::Render.new("./templates/graphql_mutations.erb", nil, nil, nil, nil, nil, mutations, nil).save("#{server_app_path}/lib/canvas/graphql_mutations.js")
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'byebug'
|
2
|
+
module CanvasApi
|
3
|
+
|
4
|
+
module GraphQLHelpers
|
5
|
+
|
6
|
+
def graphql_type(name, property)
|
7
|
+
if property["$ref"]
|
8
|
+
"#{property['$ref']}, resolve: function(model){ return model.#{name}; }"
|
9
|
+
else
|
10
|
+
type = property["type"]
|
11
|
+
case type
|
12
|
+
when "integer", "string", "boolean", "datetime", "number"
|
13
|
+
graphql_primitive(type, property["format"])
|
14
|
+
when "array"
|
15
|
+
begin
|
16
|
+
type = if property["items"]["$ref"]
|
17
|
+
property["items"]["$ref"]
|
18
|
+
else
|
19
|
+
graphql_primitive(property["items"]["type"], property["items"]["format"])
|
20
|
+
end
|
21
|
+
rescue
|
22
|
+
puts "Unable to discover list type for '#{name}' ('#{property}'). Defaulting to GraphQLString"
|
23
|
+
type = "GraphQLString"
|
24
|
+
end
|
25
|
+
"new GraphQLList(#{type})"
|
26
|
+
when "object"
|
27
|
+
puts "Using string type for '#{name}' ('#{property}') of type object."
|
28
|
+
"GraphQLString"
|
29
|
+
else
|
30
|
+
puts "Unable to match '#{name}' requested property '#{property}' to GraphQL Type."
|
31
|
+
"GraphQLString"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def graphql_primitive(type, format)
|
37
|
+
case type
|
38
|
+
when "integer"
|
39
|
+
"GraphQLInt"
|
40
|
+
when "number"
|
41
|
+
if format == "float64"
|
42
|
+
"GraphQLFloat"
|
43
|
+
else
|
44
|
+
# TODO many of the LMS types with 'number' don't indicate a type so we have to guess
|
45
|
+
# Hopefully that changes. For now we go with float
|
46
|
+
"GraphQLFloat"
|
47
|
+
end
|
48
|
+
when "string"
|
49
|
+
"GraphQLString"
|
50
|
+
when "boolean"
|
51
|
+
"GraphQLBoolean"
|
52
|
+
when "datetime"
|
53
|
+
"GraphQLDateTime"
|
54
|
+
else
|
55
|
+
raise "Unable to match requested primitive '#{type}' to GraphQL Type."
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def graphql_resolve(name, property)
|
60
|
+
if property["$ref"]
|
61
|
+
"resolve(model){ return model.#{name}; }"
|
62
|
+
elsif property["type"] == "array" && property["items"] && property["items"]["$ref"]
|
63
|
+
"resolve(model){ return model.#{name}; }"
|
64
|
+
end
|
65
|
+
"resolve(model){ return model.#{name}; }"
|
66
|
+
end
|
67
|
+
|
68
|
+
def graphql_fields(model, resource_name)
|
69
|
+
model["properties"].map do |name, property|
|
70
|
+
# HACK. This property doesn't have any metadata. Throw in a couple lines of code
|
71
|
+
# specific to this field.
|
72
|
+
if name == "created_source" && property == "manual|sis|api"
|
73
|
+
"#{name}: new GraphQLEnumType({ name: '#{name}', values: { manual: { value: 'manual' }, sis: { value: 'sis' }, api: { value: 'api' } } })"
|
74
|
+
else
|
75
|
+
|
76
|
+
description = ""
|
77
|
+
if property["description"].present? && property["example"].present?
|
78
|
+
description << "#{safe_js(property['description'])}. Example: #{safe_js(property['example'])}".gsub("..", "").gsub("\n", " ")
|
79
|
+
end
|
80
|
+
|
81
|
+
if type = graphql_type(name, property)
|
82
|
+
resolve = graphql_resolve(name, property)
|
83
|
+
resolve = "#{resolve}, " if resolve.present?
|
84
|
+
"#{name}: { type: #{type}, #{resolve}description: \"#{description}\" }"
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end.compact
|
89
|
+
end
|
90
|
+
|
91
|
+
def safe_js(str)
|
92
|
+
str = str.join(", ") if str.is_a?(Array)
|
93
|
+
str = str.map { |_k, v| v }.join(", ") if str.is_a?(Hash)
|
94
|
+
return str unless str.is_a?(String)
|
95
|
+
str.gsub('"', "'")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module CanvasApi
|
2
|
+
module JsHelpers
|
3
|
+
|
4
|
+
def js_url_parts(api_url)
|
5
|
+
api_url.split(/(\{[a-z_]+\})/).map do |part|
|
6
|
+
if part[0] == "{"
|
7
|
+
arg = part.gsub(/[\{\}]/, "")
|
8
|
+
"args['#{arg}']"
|
9
|
+
else
|
10
|
+
%{"#{part}"}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def js_args(args)
|
16
|
+
if args.present?
|
17
|
+
"['#{args.join("', '")}']"
|
18
|
+
else
|
19
|
+
"[]"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def parameters_doc(operation)
|
24
|
+
if operation["parameters"].present?
|
25
|
+
parameters = operation["parameters"].
|
26
|
+
reject { |p| p["paramType"] == "path" }.
|
27
|
+
map { |p| "#{p['name']}#{p['required'] ? ' (required)' : ''}" }.
|
28
|
+
compact
|
29
|
+
if parameters.present?
|
30
|
+
"\n// const query = {\n// #{parameters.join("\n// ")}\n// }"
|
31
|
+
else
|
32
|
+
""
|
33
|
+
end
|
34
|
+
else
|
35
|
+
""
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def key_args(args)
|
40
|
+
if args.blank?
|
41
|
+
""
|
42
|
+
elsif args.length > 1
|
43
|
+
"#{nickname}_{#{args.join('}_{')}}"
|
44
|
+
else
|
45
|
+
"#{nickname}_#{args[0]}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def reducer_key(nickname, args)
|
50
|
+
"#{nickname}#{key_args(args)}"
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require "canvas_api/graphql_helpers"
|
2
|
+
require "canvas_api/js_helpers"
|
3
|
+
require "canvas_api/ruby_helpers"
|
4
|
+
|
5
|
+
module CanvasApi
|
6
|
+
|
7
|
+
class Render
|
8
|
+
include CanvasApi::GraphQLHelpers
|
9
|
+
include CanvasApi::JsHelpers
|
10
|
+
include CanvasApi::RubyHelpers
|
11
|
+
attr_accessor :template, :description, :resource, :api_url, :operation,
|
12
|
+
:args, :method, :api, :name, :resource_name, :resource_api,
|
13
|
+
:nickname, :notes, :content, :summary, :model, :model_name
|
14
|
+
|
15
|
+
def initialize(template, api, resource, resource_api, operation, parameters, content, model)
|
16
|
+
@template = File.read(File.expand_path(template, __dir__))
|
17
|
+
if api
|
18
|
+
@api = api
|
19
|
+
@name = @api["path"].gsub("/", "").gsub(".json", "")
|
20
|
+
@description = @api["description"]
|
21
|
+
end
|
22
|
+
if resource
|
23
|
+
@resource = resource
|
24
|
+
@resource_name = resource["resourcePath"].gsub("/", "")
|
25
|
+
end
|
26
|
+
if resource_api
|
27
|
+
@resource_api = resource_api
|
28
|
+
@api_url = resource_api["path"].gsub("/v1/", "")
|
29
|
+
@args = args(@api_url)
|
30
|
+
end
|
31
|
+
if operation
|
32
|
+
nickname = operation["nickname"]
|
33
|
+
nickname = "#{@name}_#{nickname}" if [
|
34
|
+
"upload_file",
|
35
|
+
"query_by_course",
|
36
|
+
"preview_processed_html",
|
37
|
+
"create_peer_review_courses",
|
38
|
+
"create_peer_review_sections",
|
39
|
+
"set_extensions_for_student_quiz_submissions"
|
40
|
+
].include?(nickname)
|
41
|
+
|
42
|
+
@method = operation["method"]
|
43
|
+
@operation = operation
|
44
|
+
@nickname = nickname
|
45
|
+
@notes = operation["notes"].gsub("\n", "\n// ")
|
46
|
+
@summary = operation["summary"]
|
47
|
+
end
|
48
|
+
if parameters
|
49
|
+
@parameters = parameters.map { |p| p.delete("description"); p }
|
50
|
+
end
|
51
|
+
@content = content
|
52
|
+
@model = model
|
53
|
+
end
|
54
|
+
|
55
|
+
def args(api_url)
|
56
|
+
api_url.split("/").map do |part|
|
57
|
+
if part[0] == "{"
|
58
|
+
part.gsub(/[\{\}]/, "")
|
59
|
+
end
|
60
|
+
end.compact
|
61
|
+
end
|
62
|
+
|
63
|
+
def render
|
64
|
+
ERB.new(@template, nil, "-").result(binding).strip
|
65
|
+
end
|
66
|
+
|
67
|
+
def save(file)
|
68
|
+
File.write(file, render)
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<% parameters_doc = parameters_doc(operation) -%>
|
2
|
+
// <%=@summary%>
|
3
|
+
// <%=@notes%>
|
4
|
+
//
|
5
|
+
// API Docs: https://canvas.instructure.com/doc/api/<%=@resource_name%>.html
|
6
|
+
// API Url: <%=@api_url%>
|
7
|
+
//
|
8
|
+
// Example:<%=parameters_doc%>
|
9
|
+
// return canvasRequest(<%=@nickname%>, {<%=@args.join(', ')%>}<%= parameters_doc.present? ? ", query" : ""%>);
|
10
|
+
export const <%=@nickname.camelcase(:lower)%> = { type: '<%=@nickname.upcase%>', method: '<%=@method.downcase%>', key: '<%=reducer_key(@nickname, @args)%>', required: <%=js_args(@args)%> };
|
@@ -0,0 +1,9 @@
|
|
1
|
+
const <%=@model['id']%> = new GraphQLObjectType({
|
2
|
+
name: "<%=@model['id']%>",
|
3
|
+
description: "<%=@description%>. API Docs: https://canvas.instructure.com/doc/api/<%=@name%>.html",
|
4
|
+
fields() {
|
5
|
+
return {
|
6
|
+
<%=graphql_fields(@model, @resource_name).join(",\n ")%>
|
7
|
+
};
|
8
|
+
}
|
9
|
+
});
|
File without changes
|
@@ -0,0 +1,100 @@
|
|
1
|
+
import {
|
2
|
+
GraphQLBoolean,
|
3
|
+
GraphQLFloat,
|
4
|
+
GraphQLID,
|
5
|
+
GraphQLInt,
|
6
|
+
GraphQLList,
|
7
|
+
GraphQLNonNull,
|
8
|
+
GraphQLObjectType,
|
9
|
+
GraphQLSchema,
|
10
|
+
GraphQLString
|
11
|
+
} from 'graphql';
|
12
|
+
|
13
|
+
import {
|
14
|
+
connectionArgs,
|
15
|
+
connectionDefinitions,
|
16
|
+
connectionFromArray,
|
17
|
+
fromGlobalId,
|
18
|
+
globalIdField,
|
19
|
+
mutationWithClientMutationId,
|
20
|
+
nodeDefinitions,
|
21
|
+
connectionFromPromisedArray
|
22
|
+
} from 'graphql-relay';
|
23
|
+
|
24
|
+
import {
|
25
|
+
GraphQLLimitedString,
|
26
|
+
GraphQLDateTime
|
27
|
+
} from 'graphql-custom-types';
|
28
|
+
|
29
|
+
/**
|
30
|
+
* We get the node interface and field from the Relay library.
|
31
|
+
*
|
32
|
+
* The first method defines the way we resolve an ID to its object.
|
33
|
+
* The second defines the way we resolve an object to its GraphQL type.
|
34
|
+
*/
|
35
|
+
var {nodeInterface, nodeField} = nodeDefinitions(
|
36
|
+
(globalId) => {
|
37
|
+
var {type, id} = fromGlobalId(globalId);
|
38
|
+
if (type === 'User') {
|
39
|
+
return getUser(id);
|
40
|
+
} else if (type === 'Widget') {
|
41
|
+
return getWidget(id);
|
42
|
+
} else {
|
43
|
+
return null;
|
44
|
+
}
|
45
|
+
},
|
46
|
+
(obj) => {
|
47
|
+
if (obj instanceof User) {
|
48
|
+
return userType;
|
49
|
+
} else if (obj instanceof Widget) {
|
50
|
+
return widgetType;
|
51
|
+
} else {
|
52
|
+
return null;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
);
|
56
|
+
|
57
|
+
<%=@content.join("\n\n")%>
|
58
|
+
|
59
|
+
const Query = new GraphQLObjectType({
|
60
|
+
name: 'Query',
|
61
|
+
description: 'Root query',
|
62
|
+
fields: () => ({
|
63
|
+
node: nodeField,
|
64
|
+
peopleRelay: {
|
65
|
+
type: PersonConnection,
|
66
|
+
description: 'Person connection test',
|
67
|
+
args: connectionArgs,
|
68
|
+
resolve (root, args) {
|
69
|
+
return connectionFromPromisedArray(Db.models.person.findAll(), args);
|
70
|
+
}
|
71
|
+
},
|
72
|
+
person: {
|
73
|
+
type: personType,
|
74
|
+
resolve (root, args) {
|
75
|
+
return Db.models.person.findOne({ where: args });
|
76
|
+
}
|
77
|
+
},
|
78
|
+
people: {
|
79
|
+
type: new GraphQLList(personType),
|
80
|
+
args: {
|
81
|
+
id: {
|
82
|
+
type: GraphQLInt
|
83
|
+
},
|
84
|
+
email: {
|
85
|
+
type: GraphQLString
|
86
|
+
}
|
87
|
+
},
|
88
|
+
resolve (root, args) {
|
89
|
+
return Db.models.person.findAll({ where: args });
|
90
|
+
}
|
91
|
+
}
|
92
|
+
})
|
93
|
+
});
|
94
|
+
|
95
|
+
const Schema = new GraphQLSchema({
|
96
|
+
query: Query,
|
97
|
+
//mutation: Mutuation
|
98
|
+
});
|
99
|
+
|
100
|
+
export default Schema;
|
@@ -0,0 +1 @@
|
|
1
|
+
<%=@nickname.upcase%>: { uri: function(args){return <%=js_url_parts(@api_url).join(' + ')%>}, method: "<%=@method%>", parameters: <%=@parameters.to_json%> }
|
@@ -0,0 +1 @@
|
|
1
|
+
"<%=@nickname.upcase%>" => { uri: ->(<%=@args.map{|a| "#{a}:"}.join(', ')%>) { "<%=ruby_api_url(@api_url)%>" }, method: "<%=@method%>", parameters: <%=@parameters%> }
|
data/lib/lms/canvas.rb
CHANGED
@@ -282,6 +282,7 @@ module LMS
|
|
282
282
|
end
|
283
283
|
|
284
284
|
def self.lms_url(type, params, payload = nil)
|
285
|
+
params = params.to_h
|
285
286
|
endpoint = LMS::CANVAS_URLs[type]
|
286
287
|
parameters = endpoint[:parameters]
|
287
288
|
|
@@ -311,7 +312,7 @@ module LMS
|
|
311
312
|
uri_proc = endpoint[:uri]
|
312
313
|
path_parameters = parameters.select { |p| p["paramType"] == "path" }.
|
313
314
|
map { |p| p["name"].to_sym }
|
314
|
-
args = params.slice(*path_parameters)
|
315
|
+
args = params.slice(*path_parameters)
|
315
316
|
uri = args.blank? ? uri_proc.call : uri_proc.call(**args)
|
316
317
|
|
317
318
|
# Handle scopes in the url. These API endpoints allow for additional path
|
data/lib/lms/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lms-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Atomic Jolt
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2017-
|
13
|
+
date: 2017-04-14 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -107,6 +107,24 @@ files:
|
|
107
107
|
- MIT-LICENSE
|
108
108
|
- README.md
|
109
109
|
- Rakefile
|
110
|
+
- lib/canvas_api.rb
|
111
|
+
- lib/canvas_api/builder.rb
|
112
|
+
- lib/canvas_api/graphql_helpers.rb
|
113
|
+
- lib/canvas_api/js_helpers.rb
|
114
|
+
- lib/canvas_api/render.rb
|
115
|
+
- lib/canvas_api/ruby_helpers.rb
|
116
|
+
- lib/canvas_api/templates/constant.erb
|
117
|
+
- lib/canvas_api/templates/constants.erb
|
118
|
+
- lib/canvas_api/templates/graphql_model.erb
|
119
|
+
- lib/canvas_api/templates/graphql_mutation.erb
|
120
|
+
- lib/canvas_api/templates/graphql_mutations.erb
|
121
|
+
- lib/canvas_api/templates/graphql_queries.erb
|
122
|
+
- lib/canvas_api/templates/graphql_query.erb
|
123
|
+
- lib/canvas_api/templates/graphql_types.erb
|
124
|
+
- lib/canvas_api/templates/js_url.erb
|
125
|
+
- lib/canvas_api/templates/js_urls.erb
|
126
|
+
- lib/canvas_api/templates/rb_url.erb
|
127
|
+
- lib/canvas_api/templates/rb_urls.erb
|
110
128
|
- lib/lms/canvas.rb
|
111
129
|
- lib/lms/canvas_urls.rb
|
112
130
|
- lib/lms/helper_urls.rb
|
@@ -145,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
145
163
|
version: '0'
|
146
164
|
requirements: []
|
147
165
|
rubyforge_project:
|
148
|
-
rubygems_version: 2.
|
166
|
+
rubygems_version: 2.6.8
|
149
167
|
signing_key:
|
150
168
|
specification_version: 4
|
151
169
|
summary: Wrapper for the Instructure Canvas API
|