k_manager 0.0.13

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 (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