xnlogic 1.0.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.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +31 -0
  6. data/Rakefile +43 -0
  7. data/bin/xnlogic +13 -0
  8. data/lib/xnlogic/cli/application.rb +60 -0
  9. data/lib/xnlogic/cli.rb +73 -0
  10. data/lib/xnlogic/friendly_errors.rb +50 -0
  11. data/lib/xnlogic/man/xnlogic +46 -0
  12. data/lib/xnlogic/man/xnlogic.txt +42 -0
  13. data/lib/xnlogic/templates/application/.rspec.tt +2 -0
  14. data/lib/xnlogic/templates/application/Gemfile.tt +6 -0
  15. data/lib/xnlogic/templates/application/Readme.md.tt +86 -0
  16. data/lib/xnlogic/templates/application/gitignore.tt +9 -0
  17. data/lib/xnlogic/templates/application/lib/fixtures/sample_fixtures.rb.tt +53 -0
  18. data/lib/xnlogic/templates/application/lib/gemname/fixtures.rb.tt +108 -0
  19. data/lib/xnlogic/templates/application/lib/gemname/initializers/inflections.rb.tt +13 -0
  20. data/lib/xnlogic/templates/application/lib/gemname/models.rb.tt +37 -0
  21. data/lib/xnlogic/templates/application/lib/gemname/parts/has_notes.rb.tt +10 -0
  22. data/lib/xnlogic/templates/application/lib/gemname/parts/note.rb.tt +41 -0
  23. data/lib/xnlogic/templates/application/lib/gemname/permissions.rb.tt +136 -0
  24. data/lib/xnlogic/templates/application/lib/gemname/type/url.rb.tt +13 -0
  25. data/lib/xnlogic/templates/application/lib/gemname/type.rb.tt +10 -0
  26. data/lib/xnlogic/templates/application/lib/gemname/version.rb.tt +3 -0
  27. data/lib/xnlogic/templates/application/lib/gemname.rb.tt +116 -0
  28. data/lib/xnlogic/templates/application/spec/gemname/gemname_spec.rb.tt +7 -0
  29. data/lib/xnlogic/templates/application/spec/spec_helper.rb.tt +44 -0
  30. data/lib/xnlogic/ui/shell.rb +96 -0
  31. data/lib/xnlogic/ui/silent.rb +45 -0
  32. data/lib/xnlogic/ui.rb +7 -0
  33. data/lib/xnlogic/version.rb +3 -0
  34. data/lib/xnlogic.rb +33 -0
  35. data/man/xnlogic.ronn +38 -0
  36. data/xnlogic.gemspec +27 -0
  37. metadata +149 -0
@@ -0,0 +1,13 @@
1
+ # Some of our part/model names aren't inflected correctly by default.
2
+ # Here we exclude them:
3
+ ActiveSupport::Inflector.inflections do |inflect|
4
+ inflect.uncountable "media"
5
+ inflect.uncountable "software"
6
+
7
+ inflect.irregular "vrf", "vrfs"
8
+
9
+ inflect.acronym 'DNS'
10
+ inflect.acronym 'FEX'
11
+ inflect.acronym 'GW'
12
+ inflect.acronym 'GWs'
13
+ end
@@ -0,0 +1,37 @@
1
+ module <%= config[:constant_name] %>
2
+ module M
3
+ end
4
+
5
+ # NOTE: The ORDER that the class parts are specified in within each model
6
+ # IS IMPORTANT here. If two parts define the same method, the one that is
7
+ # included later will win. It can also call `super` because a real class
8
+ # heirarchy is created.
9
+ #
10
+ # Tools rely on models' parts being defined in order of significance.
11
+ #
12
+ # NOTE NOTE
13
+ # NOTE The LAST PART in the list SHOULD BEST DESCRIBE THE MODEL NOTE
14
+ # NOTE (if possible) NOTE
15
+ #
16
+ client_models = {
17
+ user_account: [PacerModel::Extensions::Permission, PacerModel::Extensions::User],
18
+ group: [PacerModel::Extensions::Permission, PacerModel::Extensions::Group],
19
+ token: [PacerModel::Extensions::Token],
20
+ external_record: [PacerModel::Extensions::ExternalRecord],
21
+ data_source: [PacerModel::Extensions::DataSource],
22
+ import_record: [PacerModel::Extensions::ImportRecord],
23
+ import: [PacerModel::Extensions::Import],
24
+
25
+ # Metadata models
26
+ note: [Note],
27
+ }
28
+
29
+ client_models.each do |name, parts|
30
+ <%= config[:constant_name] %>.models[name.to_s] = PacerModel::Model.new(:gemname,
31
+ name: name,
32
+ namespace: <%= config[:constant_name] %>::M,
33
+ core_parts: [PacerModel::Extensions::Record],
34
+ parts: ([HasNotes] + parts)
35
+ )
36
+ end
37
+ end
@@ -0,0 +1,10 @@
1
+ module <%= config[:constant_name] %>
2
+ module HasNotes
3
+ xn_part
4
+
5
+ not_descriptive!
6
+ not_cloneable!
7
+
8
+ to_many :Note, custom_sort: proc { |a, b| b[:created_at] <=> a[:created_at] }
9
+ end
10
+ end
@@ -0,0 +1,41 @@
1
+ module <%= config[:constant_name] %>
2
+ module Note
3
+ xn_part
4
+
5
+ not_cloneable!
6
+
7
+ from_one PacerModel::Extensions::User, from: :author, to: :authored_notes, default: ->{ Thread.current[:context].current_user }
8
+ from_one :HasNotes
9
+
10
+ property :text, type: :text, filter: true
11
+
12
+ display :author_info do
13
+ if author
14
+ {
15
+ id: author.element_id,
16
+ name: author.name,
17
+ email: author.email,
18
+ email_md5: author.email_md5
19
+ }
20
+ end
21
+ end
22
+
23
+ action :delete_note, guard: :guard_delete_note do |ctx|
24
+ delete!
25
+ end
26
+
27
+ module Vertex
28
+ def guard_delete_note(errors)
29
+ if created_at < 15.minutes.ago
30
+ errors.add(:created_at, "Notes can only be deleted for 15 minutes")
31
+ end
32
+
33
+ if author != Thread.current[:context].current_user
34
+ errors.add(:author, "You can only delete notes you created")
35
+ end
36
+
37
+ # TODO Discuss the pros cons to having additional rules here, like only deleting the last note
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,136 @@
1
+ # This module maps out the groups to Part permissions.
2
+ #
3
+ # We define CRUD permissions as well as an 'action_access' permission and the scheme
4
+ # is DENY all unless explicitly allowed by this matrix.
5
+ #
6
+ # NB: 'action_access' refers to both the 'action' and 'job' methods in PacerModel
7
+ # 'read_access' includes the route_traversal, document and display methds
8
+ #
9
+ # Also, these permissions are merely the default. Clients may choose to modify them
10
+ # in any way they wish.
11
+ #
12
+ # Some standard users and groups are also created in PacerModel::Application::Security.
13
+ module <%= config[:constant_name] %>
14
+ module CreatePermissions
15
+ # Implementation details. See module/classes defined below.
16
+ def initialize(app)
17
+ @app = app
18
+ end
19
+ def load!
20
+ @app.graph.transaction(nesting: true) do
21
+ groups.inject({}) do |result, (key, name)|
22
+ result[key] = group key
23
+ result
24
+ end
25
+ end
26
+ end
27
+ # This method completely resets existing groups' permissions.
28
+ def group(key)
29
+ name = groups[key]
30
+ group = @app.find_or_create @app.group_model, name: name, key: key.to_s
31
+ group.revoke_access!
32
+ group.inherit_full_access [ @app.core_permissions_group ]
33
+ access_types.each do |access|
34
+ metaparts = send(key, access).map do |part|
35
+ mp = @app.find_metapart part
36
+ puts "WARNING: No metapart for #{ part.inspect }" unless mp
37
+ mp
38
+ end
39
+ group.send("add_#{ access }", metaparts.compact)
40
+ end
41
+ end
42
+ def access_types
43
+ [:create_access, :read_access, :update_access, :action_access, :delete_access]
44
+ end
45
+ end
46
+
47
+
48
+ # This module is used to create Groups of parts that can easily be assigned to
49
+ # user groups in the permission generation strategy classes, below:
50
+ module PartGroups
51
+ include <%= config[:constant_name] %>
52
+
53
+ # Use this method to determine if any of the app's parts are not part of
54
+ # any of the group definitions below.
55
+ def missing
56
+ @app.all_parts - internal_only - users - external - client_models
57
+ end
58
+
59
+ # Use this technique to group together subgroups of parts, which is very useful in larger, more complex models!
60
+ def client_models
61
+ base + note + comments
62
+ end
63
+
64
+ # NOTE: only the xnlogic administrator should have access to these
65
+ def internal_only
66
+ Set[ PacerModel::Extensions::Part, PacerModel::Extensions::Token,
67
+ PacerModel::Extensions::XnInfraAdmin ]
68
+ end
69
+
70
+ # Other parts that are built in to XN
71
+
72
+ def users
73
+ Set[ PacerModel::Extensions::Permission, PacerModel::Extensions::User, PacerModel::Extensions::Group ]
74
+ end
75
+
76
+ def external
77
+ Set[ PacerModel::Extensions::DataSource, PacerModel::Extensions::ExternalRecord ]
78
+ end
79
+
80
+ def base
81
+ Set[ PacerModel::Extensions::Record, HasNotes, PacerModel::Extensions::User, ]
82
+ end
83
+
84
+ # Your Application-specific parts should go in a bunch of groups starting here:
85
+
86
+ def note
87
+ Set[ Note, ]
88
+ end
89
+
90
+ def comments
91
+ # Placeholder for theoretical comments part...
92
+ Set[ ]
93
+ end
94
+ end
95
+
96
+
97
+ # A sophisticated role based access model
98
+ class RoleBasedPermissions
99
+ include CreatePermissions
100
+ include PartGroups
101
+
102
+ def initialize(app)
103
+ super
104
+ end
105
+
106
+ def groups
107
+ {
108
+ support: 'Support',
109
+ staff: 'Staff',
110
+ read_only: 'Read Only'
111
+ }
112
+ end
113
+
114
+ def support(access)
115
+ base + users + client_models
116
+ end
117
+
118
+ def read_only(access)
119
+ case access
120
+ when :read_access
121
+ base + client_models
122
+ else
123
+ []
124
+ end
125
+ end
126
+
127
+ def staff(access)
128
+ case access
129
+ when :delete_access
130
+ base + comments
131
+ when :read_access, :update_access, :create_access, :action_access
132
+ base + client_models
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,13 @@
1
+ module <%= config[:constant_name] %>
2
+ module Type
3
+
4
+ # URL can be a property's type
5
+ Property::URL = {
6
+ type: :text,
7
+ label: 'URL',
8
+ }.freeze
9
+
10
+ # URL can be an argument in an action as well. Definition is identical to Property::URL:
11
+ Argument::URL = Property::URL
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ module <%= config[:constant_name] %>
2
+ module Type
3
+ module Argument; end
4
+ module Property; end
5
+ end
6
+ end
7
+
8
+ # Specialized types
9
+ require '<%= config[:namespaced_path] %>/type/url'
10
+
@@ -0,0 +1,3 @@
1
+ module <%= config[:constant_name] %>
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,116 @@
1
+ if RUBY_VERSION == '1.8.7'
2
+ STDERR.puts <<WARNING
3
+ WARNING: XN Logic is developed using JRuby in 1.9 mode. I recommend you
4
+ restart JRuby in 1.9 mode, either with the --1.9 flag, or by
5
+ defaulting to 1.9 mode by setting the environment variable
6
+ JRUBY_OPTS=--1.9
7
+ WARNING
8
+ raise "1.8 mode: no go"
9
+ end
10
+
11
+ require 'rubygems'
12
+ require 'bundler/setup'
13
+ require 'active_model'
14
+ require 'active_model/naming'
15
+ require 'active_support/core_ext'
16
+ require 'pacer'
17
+ require 'pacer-model'
18
+ require 'pathname'
19
+
20
+ require '<%= config[:namespaced_path] %>/initializers/inflections'
21
+
22
+ module <%= config[:constant_name] %>
23
+ VertexDsl = PacerModel::VertexDsl
24
+ START_TIME = Time.now unless const_defined? :START_TIME
25
+
26
+ class << self
27
+ include PacerModel::AppBase
28
+
29
+ def lib_dir
30
+ Pathname.new(File.expand_path(__FILE__)).parent
31
+ end
32
+
33
+ def sample_app(args)
34
+ unless args.is_a? Hash
35
+ puts "sample_app takes an args hash with :graph and :client_name required."
36
+ return
37
+ end
38
+ unless args.keys.include? :client_name and args.keys.include? :graph
39
+ puts ":graph and :client_name are required arguments"
40
+ return
41
+ end
42
+ require '<%= config[:namespaced_path] %>/fixtures'
43
+ Dir[<%= config[:constant_name] %>.lib_dir + "fixtures/*.{rb,class}"].each do |file|
44
+ require Pathname.new(file).relative_path_from(<%= config[:constant_name] %>.lib_dir)
45
+ end
46
+ a = app(args)
47
+ Fixtures.load_fixtures(a)
48
+ a
49
+ end
50
+
51
+ # Usage: permission_models[x].new(app).load!
52
+ # Note, it's load! method must be idempotent.
53
+ def permission_models
54
+ {
55
+ 'role_based' => <%= config[:constant_name] %>::RoleBasedPermissions
56
+ }
57
+ end
58
+
59
+ # Returns the time pacer was last reloaded (or when it was started).
60
+ def reload_time
61
+ if defined? @reload_time
62
+ @reload_time
63
+ else
64
+ START_TIME
65
+ end
66
+ end
67
+
68
+ # Reload all Ruby modified files in the Pacer library. Useful for debugging
69
+ # in the console. Does not do any of the fancy stuff that Rails reloading
70
+ # does. Certain types of changes will still require restarting the
71
+ # session.
72
+ def reload!
73
+ lib_dir.find do |path|
74
+ if path.extname == '.rb' and path.mtime > reload_time
75
+ puts path.to_s
76
+ load path.to_s rescue nil
77
+ end
78
+ end
79
+ @reload_time = Time.now
80
+ end
81
+ end
82
+ end
83
+
84
+ require '<%= config[:namespaced_path] %>/version'
85
+ require '<%= config[:namespaced_path] %>/type'
86
+
87
+ PacerModel.applications['<%= config[:name] %>'] = <%= config[:constant_name] %>
88
+ PacerModel.property_namespaces << <%= config[:constant_name] %>::Type::Property
89
+ PacerModel.argument_namespaces << <%= config[:constant_name] %>::Type::Argument
90
+ PacerModel.part_namespaces << <%= config[:constant_name] %>
91
+ PacerModel.on_part_registered << lambda do |part|
92
+ if part.name =~ /^<%= config[:constant_name] %>::/
93
+ <%= config[:constant_name] %>.parts[part.key.to_s] = part
94
+ end
95
+ end
96
+
97
+ #NOTE: meta contains some common parts. So, load meta first to ensure
98
+ # common parts are loaded into other parts on boot
99
+ Dir[<%= config[:constant_name] %>.lib_dir + '<%= config[:namespaced_path] %>/meta/*.{class,rb}'].each do |file|
100
+ require Pathname.new(file).relative_path_from(<%= config[:constant_name] %>.lib_dir)
101
+ end
102
+ <%= config[:constant_name] %>.common_parts!
103
+ # dirs under lib/<%= config[:namespaced_path] %> that contain groupings of parts
104
+ sections = %w[
105
+ parts
106
+ ]
107
+
108
+ # Now that we have DEFAULT_CONSTANTS being referenced, if load order is important...
109
+ #require <%= config[:constant_name] %>.lib_dir + "<%= config[:namespaced_path] %>/group/part"
110
+
111
+ Dir[<%= config[:constant_name] %>.lib_dir + "<%= config[:namespaced_path] %>/{#{sections.join ','}}/*.{rb,class}"].each do |file|
112
+ require Pathname.new(file).relative_path_from(<%= config[:constant_name] %>.lib_dir)
113
+ end
114
+
115
+ require '<%= config[:namespaced_path] %>/models'
116
+ require '<%= config[:namespaced_path] %>/permissions'
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe <%= config[:constant_name] %> do
4
+ it 'should boot' do
5
+ <%= config[:constant_name] %>.should be_a Module
6
+ end
7
+ end
@@ -0,0 +1,44 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup :default, :development
4
+
5
+ require '<%= config[:namespaced_path] %>'
6
+
7
+ Bundler.require :development
8
+ require 'pp'
9
+
10
+ Dir['./spec/support/**/*.rb'].map {|f| require f}
11
+
12
+ class RSpec::Core::ExampleGroup
13
+ def self.run_all(reporter=nil)
14
+ run(reporter || NullObject.new)
15
+ end
16
+ end
17
+
18
+ def in_editor?
19
+ ENV.has_key?('TM_MODE') || ENV.has_key?('EMACS') || ENV.has_key?('VIM')
20
+ end
21
+
22
+ RSpec.configure do |c|
23
+ c.color_enabled = !in_editor?
24
+ c.filter_run :focus => true
25
+ c.run_all_when_everything_filtered = true
26
+ Pacer.hide_route_elements = true
27
+ Pacer.verbose = false
28
+ JRuby.objectspace = true
29
+ c.mock_with :rr
30
+
31
+ SpecApp = <%= config[:constant_name] %>.app graph: Pacer.tg, client_name: 'specs'
32
+ SpecApp.add_to_models!
33
+ SpecApp.add_to_parts!
34
+
35
+ puts "Using JRuby #{ JRUBY_VERSION } in #{ RUBY_VERSION } mode."
36
+ end
37
+
38
+
39
+ def use_simple_fixtures
40
+ before { <%= config[:constant_name] %>.graph = Pacer.tg }
41
+ let(:graph) { <%= config[:constant_name] %>.graph }
42
+ let(:manufacturer) { graph.create_vertex <%= config[:constant_name] %>::Manufacturer }
43
+ let(:device_model){ graph.create_vertex <%= config[:constant_name] %>::DeviceModel }
44
+ end
@@ -0,0 +1,96 @@
1
+ module Xnlogic
2
+ module UI
3
+ class Shell
4
+ LEVELS = %w(silent error warn confirm info debug)
5
+
6
+ attr_writer :shell
7
+
8
+ def initialize(options = {})
9
+ if options["no-color"] || !STDOUT.tty?
10
+ Thor::Base.shell = Thor::Shell::Basic
11
+ end
12
+ @shell = Thor::Base.shell.new
13
+ @level = ENV['DEBUG'] ? "debug" : "info"
14
+ end
15
+
16
+ def info(msg, newline = nil)
17
+ tell_me(msg, nil, newline) if level("info")
18
+ end
19
+
20
+ def confirm(msg, newline = nil)
21
+ tell_me(msg, :green, newline) if level("confirm")
22
+ end
23
+
24
+ def warn(msg, newline = nil)
25
+ tell_me(msg, :yellow, newline) if level("warn")
26
+ end
27
+
28
+ def error(msg, newline = nil)
29
+ tell_me(msg, :red, newline) if level("error")
30
+ end
31
+
32
+ def debug(msg, newline = nil)
33
+ tell_me(msg, nil, newline) if level("debug")
34
+ end
35
+
36
+ def debug?
37
+ # needs to be false instead of nil to be newline param to other methods
38
+ level("debug")
39
+ end
40
+
41
+ def quiet?
42
+ LEVELS.index(@level) <= LEVELS.index("warn")
43
+ end
44
+
45
+ def ask(msg)
46
+ @shell.ask(msg)
47
+ end
48
+
49
+ def level=(level)
50
+ raise ArgumentError unless LEVELS.include?(level.to_s)
51
+ @level = level
52
+ end
53
+
54
+ def level(name = nil)
55
+ name ? LEVELS.index(name) <= LEVELS.index(@level) : @level
56
+ end
57
+
58
+ def trace(e, newline = nil)
59
+ return unless debug?
60
+ msg = "#{e.class}: #{e.message}\n#{e.backtrace.join("\n ")}"
61
+ tell_me(msg, nil, newline)
62
+ end
63
+
64
+ def silence
65
+ old_level, @level = @level, "silent"
66
+ yield
67
+ ensure
68
+ @level = old_level
69
+ end
70
+
71
+ private
72
+
73
+ # valimism
74
+ def tell_me(msg, color = nil, newline = nil)
75
+ msg = word_wrap(msg) if newline.is_a?(Hash) && newline[:wrap]
76
+ if newline.nil?
77
+ @shell.say(msg, color)
78
+ else
79
+ @shell.say(msg, color, newline)
80
+ end
81
+ end
82
+
83
+ def strip_leading_spaces(text)
84
+ spaces = text[/\A\s+/, 0]
85
+ spaces ? text.gsub(/#{spaces}/, '') : text
86
+ end
87
+
88
+ def word_wrap(text, line_width = @shell.terminal_width)
89
+ strip_leading_spaces(text).split("\n").collect do |line|
90
+ line.length > line_width ? line.gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip : line
91
+ end * "\n"
92
+ end
93
+ end
94
+ end
95
+ end
96
+
@@ -0,0 +1,45 @@
1
+ module Xnlogic
2
+ module UI
3
+ class Silent
4
+ def info(message, newline = nil)
5
+ end
6
+
7
+ def confirm(message, newline = nil)
8
+ end
9
+
10
+ def warn(message, newline = nil)
11
+ end
12
+
13
+ def error(message, newline = nil)
14
+ end
15
+
16
+ def debug(message, newline = nil)
17
+ end
18
+
19
+ def debug?
20
+ false
21
+ end
22
+
23
+ def quiet?
24
+ false
25
+ end
26
+
27
+ def ask(message)
28
+ end
29
+
30
+ def level=(name)
31
+ end
32
+
33
+ def level(name = nil)
34
+ end
35
+
36
+ def trace(message, newline = nil)
37
+ end
38
+
39
+ def silence
40
+ yield
41
+ end
42
+ end
43
+ end
44
+ end
45
+
data/lib/xnlogic/ui.rb ADDED
@@ -0,0 +1,7 @@
1
+ module Xnlogic
2
+ module UI
3
+ autoload :Shell, 'xnlogic/ui/shell'
4
+ autoload :Silent, 'xnlogic/ui/silent'
5
+ end
6
+ end
7
+
@@ -0,0 +1,3 @@
1
+ module Xnlogic
2
+ VERSION = "1.0.0"
3
+ end
data/lib/xnlogic.rb ADDED
@@ -0,0 +1,33 @@
1
+ require 'xnlogic/version'
2
+ require 'fileutils'
3
+ require 'pathname'
4
+ require 'xnlogic/ui'
5
+
6
+ module Xnlogic
7
+ class XnlogicError < StandardError
8
+ def self.status_code(code)
9
+ define_method(:status_code) { code }
10
+ end
11
+ end
12
+
13
+ class InvalidOption < XnlogicError; status_code(15) ; end
14
+
15
+ class << self
16
+ attr_writer :ui
17
+
18
+ def ui
19
+ @ui ||= UI::Silent.new
20
+ end
21
+
22
+ def which(executable)
23
+ if File.file?(executable) && File.executable?(executable)
24
+ executable
25
+ elsif ENV['PATH']
26
+ path = ENV['PATH'].split(File::PATH_SEPARATOR).find do |p|
27
+ File.executable?(File.join(p, executable))
28
+ end
29
+ path && File.expand_path(executable, path)
30
+ end
31
+ end
32
+ end
33
+ end
data/man/xnlogic.ronn ADDED
@@ -0,0 +1,38 @@
1
+ xnlogic(1) -- XN Logic Command-line Tools
2
+ =========================================
3
+
4
+ ## SYNOPSIS
5
+
6
+ `xnlogic` COMMAND [--no-color] [--verbose] [ARGS]
7
+
8
+ ## DESCRIPTION
9
+
10
+ XN Logic is a graph database-backed application framework.
11
+
12
+ See [the XN Logic website](https://xnlogic.com) for information on getting
13
+ started, or https://xnlogic.zendesk.com/hc/en-us for support.
14
+
15
+ ## OPTIONS
16
+
17
+ * `--no-color`:
18
+ Prints all output without color
19
+
20
+ * `--verbose`:
21
+ Prints out additional logging information
22
+
23
+ ## COMMANDS
24
+
25
+ We divide `xnlogic` subcommands into primary commands and utilities.
26
+
27
+ ## PRIMARY COMMANDS
28
+
29
+ * ...
30
+
31
+ * `xnlogic help(1)`:
32
+ Displays detailed help for each subcommand
33
+
34
+ ## UTILITIES
35
+
36
+ * `xnlogic application(1)`:
37
+ Create a simple application, suitable for development with xnlogic
38
+