k_manager 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/main.yml +31 -0
  3. data/.gitignore +50 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +85 -0
  6. data/Assessment1.md +127 -0
  7. data/Assessment2.md +88 -0
  8. data/CODE_OF_CONDUCT.md +74 -0
  9. data/Gemfile +25 -0
  10. data/Guardfile +30 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +82 -0
  13. data/Rakefile +33 -0
  14. data/STORIES.md +42 -0
  15. data/ToDo.md +8 -0
  16. data/USAGE.md +19 -0
  17. data/bin/console +16 -0
  18. data/bin/k +36 -0
  19. data/bin/kgitsync +76 -0
  20. data/bin/khotfix +244 -0
  21. data/bin/setup +11 -0
  22. data/hooks/pre-commit +87 -0
  23. data/hooks/update-version +33 -0
  24. data/k_manager.gemspec +47 -0
  25. data/lib/k_manager.rb +50 -0
  26. data/lib/k_manager/configuration/project_config.rb +14 -0
  27. data/lib/k_manager/create_document.rb +31 -0
  28. data/lib/k_manager/documents/basic_document.rb +21 -0
  29. data/lib/k_manager/documents/builder_document.rb +18 -0
  30. data/lib/k_manager/documents/document_taggable.rb +94 -0
  31. data/lib/k_manager/documents/model_document.rb +19 -0
  32. data/lib/k_manager/project.rb +50 -0
  33. data/lib/k_manager/resources/base_resource.rb +182 -0
  34. data/lib/k_manager/resources/csv_file_resource.rb +27 -0
  35. data/lib/k_manager/resources/factories/document_factory.rb +52 -0
  36. data/lib/k_manager/resources/factories/ruby_document_factory.rb +57 -0
  37. data/lib/k_manager/resources/file_resource.rb +93 -0
  38. data/lib/k_manager/resources/json_file_resource.rb +22 -0
  39. data/lib/k_manager/resources/ruby_file_resource.rb +32 -0
  40. data/lib/k_manager/resources/unknown_file_resource.rb +22 -0
  41. data/lib/k_manager/resources/x_resource.rb +243 -0
  42. data/lib/k_manager/resources/yaml_file_resource.rb +21 -0
  43. data/lib/k_manager/version.rb +5 -0
  44. data/lib/k_manager/x_project.rb +698 -0
  45. data/lib/k_manager/x_project_manager.rb +133 -0
  46. data/lib/k_manager/x_register.rb +199 -0
  47. data/lib/k_manager/x_resource_documents/resource_document.rb +51 -0
  48. metadata +150 -0
data/bin/setup ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # frozen_string_literal: true
4
+
5
+ set -euo pipefail
6
+ IFS=$'\n\t'
7
+ set -vx
8
+
9
+ bundle install
10
+
11
+ # Do any other automated setup that you need to do here
data/hooks/pre-commit ADDED
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'English'
5
+
6
+ # NOTE: you may need change file permissions
7
+ # chmod +x hooks/pre-commit
8
+
9
+ exit 0 if ARGV.include?('--no-verify')
10
+
11
+ warning_keywords = %w[console.log]
12
+ keywords = %w[binding.pry console.dir byebug debugger]
13
+ files_changed = `git diff-index --name-only HEAD --`.split
14
+
15
+ # puts '----------------------------------------------------------------------'
16
+ # puts remove files changed from the pre-commit checking if they are one of the following files
17
+ # puts '----------------------------------------------------------------------'
18
+ # files_changed = files_changed - ['hooks/pre-commit']
19
+ # files_changed = files_changed - ['hooks/update-version']
20
+
21
+ # byebug may need to be in these files
22
+ files_changed -= ['Gemfile']
23
+ files_changed -= ['Gemfile.lock']
24
+ files_changed -= ['.gitignore']
25
+ files_changed -= ['README.md']
26
+
27
+ files_changed = files_changed.reject { |f| f.downcase.end_with?('.json') }
28
+ files_changed = files_changed.reject { |f| f.downcase.end_with?('.yml') }
29
+
30
+ # ignore files from specific folders
31
+
32
+ file_groups = files_changed.select do |item|
33
+ item.start_with?('hooks') # ||
34
+ # item.start_with?('lib/generators')
35
+ end
36
+
37
+ files_changed -= file_groups
38
+
39
+ # remove files that are changed because they are deleted
40
+ files_changed = files_changed.select { |filename| File.file?(filename) }
41
+
42
+ # puts '----------------------------------------------------------------------'
43
+ # puts 'Files Changed'
44
+ # puts '----------------------------------------------------------------------'
45
+ # puts files_changed
46
+ # puts '----------------------------------------------------------------------'
47
+
48
+ unless files_changed.length.zero?
49
+ # puts "#{keywords.join('|')}"
50
+ # puts "#{files_changed.join(' ')}"
51
+
52
+ `git grep -q -E "#{warning_keywords.join('|')}" #{files_changed.join(' ')}`
53
+
54
+ if $CHILD_STATUS.exitstatus.zero?
55
+ puts '' # Check following lines:''
56
+ puts $CHILD_STATUS.exitstatus
57
+ files_changed.each do |file|
58
+ warning_keywords.each do |keyword|
59
+ # puts "#{keyword} ::: #{file}"
60
+ `git grep -q -E #{keyword} #{file}`
61
+ if $CHILD_STATUS.exitstatus.zero?
62
+ line = `git grep -n #{keyword} #{file} | awk -F ":" '{print $2}'`.split.join(', ')
63
+ puts "WARNING:\t\033[31m#{file}\033[0m contains #{keyword} at line \033[33m#{line}\033[0m."
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ `git grep -q -E "#{keywords.join('|')}" #{files_changed.join(' ')}`
70
+
71
+ if $CHILD_STATUS.exitstatus.zero?
72
+ puts '' # Check following lines:''
73
+ puts $CHILD_STATUS.exitstatus
74
+ files_changed.each do |file|
75
+ keywords.each do |keyword|
76
+ # puts "#{keyword} ::: #{file}"
77
+ `git grep -q -E #{keyword} #{file}`
78
+ if $CHILD_STATUS.exitstatus.zero?
79
+ line = `git grep -n #{keyword} #{file} | awk -F ":" '{print $2}'`.split.join(', ')
80
+ puts "ERROR :\t\033[31m#{file}\033[0m contains #{keyword} at line \033[33m#{line}\033[0m."
81
+ end
82
+ end
83
+ end
84
+ puts '# Force commit with --no-verify'
85
+ exit 1
86
+ end
87
+ end
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # NOTE: you may need change file permissions
5
+ # chmod +x hooks/update-version
6
+
7
+ exit 1 if ARGV.empty?
8
+
9
+ version = ARGV[0]
10
+ version = version[1..-1] # revoke 'v' character, e.g. v0.1.1 becomes 0.1.1
11
+
12
+ namespaces = %w[KManager]
13
+
14
+ indent = 0
15
+ output = ['# frozen_string_literal: true', '']
16
+
17
+ namespaces.each do |namespace|
18
+ output.push "#{' ' * indent}module #{namespace}"
19
+ indent += 1
20
+ end
21
+
22
+ output.push "#{' ' * indent}VERSION = \'#{version}'"
23
+ indent -= 1
24
+
25
+ namespaces.each do
26
+ output.push "#{' ' * indent}end"
27
+ indent -= 1
28
+ end
29
+
30
+ output.push('')
31
+
32
+ printf "%-25<label>s : %<version>s\n", label: 'GEM VERSION', version: version
33
+ File.open('lib/k_manager/version.rb', 'w+') { |f| f.write(output.join("\n")) }
data/k_manager.gemspec ADDED
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/k_manager/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.required_ruby_version = '>= 2.5'
7
+ spec.name = 'k_manager'
8
+ spec.version = KManager::VERSION
9
+ spec.authors = ['David Cruwys']
10
+ spec.email = ['david@ideasmen.com.au']
11
+
12
+ spec.summary = 'K Manager provides a managed host for documents, resources and code generator execution'
13
+ spec.description = <<-TEXT
14
+ K Manager provides a managed host for documents, resources and code generator execution
15
+ TEXT
16
+ spec.homepage = 'http://appydave.com/gems/k-manager'
17
+ spec.license = 'MIT'
18
+
19
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
20
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
21
+ raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.' unless spec.respond_to?(:metadata)
22
+
23
+ # spec.metadata['allowed_push_host'] = "Set to 'http://mygemserver.com'"
24
+
25
+ spec.metadata['homepage_uri'] = spec.homepage
26
+ spec.metadata['source_code_uri'] = 'https://github.com/klueless-io/k_manager'
27
+ spec.metadata['changelog_uri'] = 'https://github.com/klueless-io/k_manager/commits/master'
28
+
29
+ # Specify which files should be added to the gem when it is released.
30
+ # The `git ls-files -z` loads the RubyGem files that have been added into git.
31
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
32
+ `git ls-files -z`.split("\x0").reject do |f|
33
+ f.match(%r{^(test|spec|features)/})
34
+ end
35
+ end
36
+ spec.bindir = 'exe'
37
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
38
+ spec.require_paths = ['lib']
39
+ # spec.extensions = ['ext/k_manager/extconf.rb']
40
+
41
+ spec.add_dependency 'k_builder', '~> 0.0.0'
42
+ spec.add_dependency 'k_doc', '~> 0.0.0'
43
+ spec.add_dependency 'k_ext-github', '~> 0.0.0'
44
+ spec.add_dependency 'k_log', '~> 0.0.0'
45
+ # spec.add_dependency 'k_type' , '~> 0.0.0'
46
+ # spec.add_dependency 'k_util' , '~> 0.0.0'
47
+ end
data/lib/k_manager.rb ADDED
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'k_doc'
4
+ require 'k_builder'
5
+ require 'k_ext/github'
6
+ require 'k_log'
7
+
8
+ require 'k_manager/create_document'
9
+ require 'k_manager/version'
10
+ require 'k_manager/configuration/project_config'
11
+ require 'k_manager/documents/document_taggable'
12
+ require 'k_manager/documents/basic_document'
13
+ require 'k_manager/documents/model_document'
14
+ require 'k_manager/documents/builder_document'
15
+ require 'k_manager/resources/base_resource'
16
+ require 'k_manager/resources/file_resource'
17
+ require 'k_manager/resources/csv_file_resource'
18
+ require 'k_manager/resources/json_file_resource'
19
+ require 'k_manager/resources/ruby_file_resource'
20
+ require 'k_manager/resources/yaml_file_resource'
21
+ require 'k_manager/resources/unknown_file_resource'
22
+ require 'k_manager/project'
23
+
24
+ module KManager
25
+ extend CreateDocument
26
+
27
+ # raise KManager::Error, 'Sample message'
28
+ class Error < StandardError; end
29
+
30
+ class << self
31
+ def new_project_config(&block)
32
+ config = KManager::Configuration::ProjectConfig.new
33
+ block.call(config) if block_given?
34
+ config
35
+ end
36
+
37
+ # Instance of the currently focused resource
38
+ # if document get created dynamically due to class_eval then they
39
+ # can attach themselves to the currently focussed resource via
40
+ # KManager.target_resource.add_document(document)
41
+ attr_accessor :target_resource
42
+ end
43
+ end
44
+
45
+ if ENV['KLUE_DEBUG']&.to_s&.downcase == 'true'
46
+ namespace = 'KManager::Version'
47
+ file_path = $LOADED_FEATURES.find { |f| f.include?('k_manager/version') }
48
+ version = KManager::VERSION.ljust(9)
49
+ puts "#{namespace.ljust(35)} : #{version.ljust(9)} : #{file_path}"
50
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KManager
4
+ module Configuration
5
+ # Project configuration class for KManager
6
+ #
7
+ # This configuration contains template and target folders as used
8
+ # by all k_builders, it also has additional configuration that makes
9
+ # sense for a project, such as the GitHub repository configuration
10
+ class ProjectConfig < KBuilder::Configuration
11
+ attach_to(KExt::Github::Configuration, self, :github)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KManager
4
+ module CreateDocument
5
+ def model(key = nil, **opts)
6
+ opts = { key: key }.merge(opts) unless key.nil?
7
+ document = new_document(KManager::Documents::ModelDocument, **opts)
8
+
9
+ attach_to_resource(document, change_resource_type: :dsl)
10
+ end
11
+
12
+ def attach_to_resource(document, change_resource_type: :dsl)
13
+ KManager.target_resource&.attach_document(document, change_resource_type: :dsl)
14
+ document
15
+ end
16
+
17
+ # Create an instance of a document
18
+ #
19
+ # @param [Class<DocumentTaggable>] klass type of document to create
20
+ def new_document(klass, **opts)
21
+ key = KManager.target_resource.documents.length.zero? ? KManager.target_resource.infer_key : nil
22
+
23
+ opts = {
24
+ resource: KManager.target_resource,
25
+ key: key
26
+ }.merge(opts)
27
+
28
+ klass.new(**opts)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KManager
4
+ module Documents
5
+ # A basic document stores a simple data object with tags for
6
+ # unique key, type, namespace and project.
7
+ class BasicDocument < KDoc::Container
8
+ include KLog::Logging
9
+ include KManager::Documents::DocumentTaggable
10
+
11
+ def initialize(**opts)
12
+ super(**opts)
13
+ initialize_document_tags(**opts)
14
+ end
15
+
16
+ def default_document_type
17
+ :basic
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KManager
4
+ module Documents
5
+ class BuilderDocument
6
+ include KLog::Logging
7
+ include KManager::Documents::DocumentTaggable
8
+
9
+ def initialize(**opts)
10
+ initialize_document_tags(**opts)
11
+ end
12
+
13
+ # def default_document_type
14
+ # nil
15
+ # end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KManager
4
+ module Documents
5
+ # Tag a document with attributes that can be used to uniquely identify
6
+ # a document within a project or namespace
7
+ #
8
+ # Examples:
9
+ # User DSL could be tagged user_entity
10
+ # Blue print DSL for building a data layer User could be tagged user_blueprint
11
+ # Users.csv file could be tagged data_files_users_csv
12
+ # Account DSL in the CRM project could be tagged crm_account_entity
13
+ # AccountController DSL in the CRM project could be tagged crm_controllers_account_controller
14
+ module DocumentTaggable
15
+ # Name of the document (required)
16
+ #
17
+ # Examples: user, account, country
18
+ attr_reader :key
19
+
20
+ # Type of document (optional, but will set to :default_document_type if not provided)
21
+ #
22
+ # Examples by data type
23
+ # :csv, :yaml, :json, :xml
24
+ #
25
+ # Examples by shape of the data in a DSL
26
+ # :entity, :microapp, blueprint
27
+ attr_reader :type
28
+
29
+ # Namespace of the document (optional, '' if not set)
30
+ #
31
+ # When using a data file, this should be based on the relative file path
32
+ # When using a DSL data file, this will be manually configured
33
+ attr_reader :namespace
34
+
35
+ # Resource that this document belongs to (optional)
36
+ attr_accessor :resource
37
+
38
+ # Project that this document belongs to (optional)
39
+ attr_reader :project
40
+
41
+ # Project key is inferred from the attached project ('' if project not set)
42
+ attr_reader :project_key
43
+
44
+ # Errors in documents can be stored against the document
45
+ #
46
+ # This helps debugging invalid DSL's and data documents
47
+ attr_reader :error
48
+
49
+ def initialize_document_tags(**opts)
50
+ @key = opts[:key] || SecureRandom.alphanumeric(4)
51
+ @type = opts[:type] || default_document_type
52
+ @namespace = opts[:namespace] || ''
53
+ @resource = opts[:resource]
54
+ @project = @resource&.project
55
+ @project_key = project&.infer_key
56
+ end
57
+
58
+ # This method should be implemented on the document class
59
+ # generally it will return a :symbol
60
+ # def default_document_type; end;
61
+
62
+ # The unique key on resources provides a way to prevent conflicts
63
+ # between resource names, resource types, local namespaces and projects.
64
+ def unique_key
65
+ return @unique_key if defined? @unique_key
66
+
67
+ @unique_key = begin
68
+ raise KDoc::Error, 'key is required when generating unique key' if key.nil? || key.empty?
69
+
70
+ [project_key, namespace, key, type]
71
+ .reject { |k| k.nil? || k == '' }
72
+ .map { |k| k.to_s.gsub('_', '-') }
73
+ .join('-')
74
+ end
75
+ end
76
+
77
+ # rubocop:disable Metrics/AbcSize
78
+ def debug
79
+ log.section_heading(self.class.name)
80
+
81
+ log.kv 'unique_key' , unique_key , 15
82
+ log.kv 'key' , key , 15
83
+ log.kv 'type' , type , 15
84
+ log.kv 'namespace' , namespace , 15
85
+ # log.kv 'resource' , resource , 15
86
+ # log.kv 'project' , project , 15
87
+ log.kv 'project_key' , project_key , 15
88
+ log.kv 'data' , data.nil? ? '' : data.to_s[0..100].gsub("\n", '\n'), 15
89
+ log.kv 'error' , error , 15
90
+ end
91
+ # rubocop:enable Metrics/AbcSize
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KManager
4
+ module Documents
5
+ class ModelDocument < KDoc::Model
6
+ include KLog::Logging
7
+ include KManager::Documents::DocumentTaggable
8
+
9
+ def initialize(**opts)
10
+ super(**opts)
11
+ initialize_document_tags(**opts)
12
+ end
13
+
14
+ def default_document_type
15
+ KDoc.opinion.default_model_type
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KManager
4
+ require 'handlebars/helpers/string_formatting/dasherize'
5
+
6
+ # A project represents all the DSL and Data resources that are available, it keeps a track of
7
+ # the in memory state of the resources, are they loaded into memory or not.
8
+ class Project
9
+ # Project name
10
+ attr_reader :name
11
+
12
+ # Project namespace, aka namespace root
13
+ attr_reader :namespace
14
+
15
+ # Configuration for this project
16
+ attr_reader :config
17
+
18
+ # List of resources attached to this project
19
+ attr_reader :resources
20
+
21
+ def initialize(name, config = nil, **opts)
22
+ raise KType::Error, 'Provide a project name' unless name.is_a?(String) || name.is_a?(Symbol)
23
+
24
+ @name = name
25
+ @config = config || KManager::Configuration::ProjectConfig.new
26
+ @resources = []
27
+
28
+ initialize_opts(opts)
29
+ end
30
+
31
+ def add_resource(resource)
32
+ # Need to check if this and resource.attach_project need to delegate to each other
33
+ # Need to check that resources can't be added twice
34
+ # Tests are required
35
+ @resources << resource
36
+ end
37
+
38
+ # Infer key is the project name stored in dash-case
39
+ def infer_key
40
+ Handlebars::Helpers::StringFormatting::Dasherize.new.parse(name.to_s.gsub('_', '-'))
41
+ end
42
+
43
+ private
44
+
45
+ def initialize_opts(opts)
46
+ # project name is often a good default for the namespace
47
+ @namespace = opts[:namespace] || name
48
+ end
49
+ end
50
+ end