punk 0.0.1

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 (74) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/Gemfile +121 -0
  4. data/Gemfile.lock +353 -0
  5. data/LICENSE +24 -0
  6. data/README.md +7 -0
  7. data/Rakefile +31 -0
  8. data/VERSION +1 -0
  9. data/bin/punk +18 -0
  10. data/lib/punk.rb +32 -0
  11. data/lib/punk/commands/auth.rb +57 -0
  12. data/lib/punk/commands/generate.rb +54 -0
  13. data/lib/punk/commands/http.rb +71 -0
  14. data/lib/punk/commands/list.rb +28 -0
  15. data/lib/punk/config/console/defaults.json +5 -0
  16. data/lib/punk/config/defaults.json +47 -0
  17. data/lib/punk/config/schema.json +55 -0
  18. data/lib/punk/config/script/defaults.json +5 -0
  19. data/lib/punk/config/server/development.json +9 -0
  20. data/lib/punk/config/spec/defaults.json +5 -0
  21. data/lib/punk/core/app.rb +233 -0
  22. data/lib/punk/core/boot.rb +9 -0
  23. data/lib/punk/core/cli.rb +13 -0
  24. data/lib/punk/core/commander.rb +82 -0
  25. data/lib/punk/core/commands.rb +26 -0
  26. data/lib/punk/core/env.rb +290 -0
  27. data/lib/punk/core/error.rb +10 -0
  28. data/lib/punk/core/exec.rb +38 -0
  29. data/lib/punk/core/interface.rb +76 -0
  30. data/lib/punk/core/load.rb +9 -0
  31. data/lib/punk/core/logger.rb +33 -0
  32. data/lib/punk/core/monkey.rb +7 -0
  33. data/lib/punk/core/monkey_unreloader.rb +18 -0
  34. data/lib/punk/core/pry.rb +39 -0
  35. data/lib/punk/core/settings.rb +38 -0
  36. data/lib/punk/core/version.rb +7 -0
  37. data/lib/punk/core/worker.rb +13 -0
  38. data/lib/punk/framework/action.rb +29 -0
  39. data/lib/punk/framework/all.rb +10 -0
  40. data/lib/punk/framework/command.rb +117 -0
  41. data/lib/punk/framework/model.rb +52 -0
  42. data/lib/punk/framework/plugins/all.rb +3 -0
  43. data/lib/punk/framework/plugins/validation.rb +55 -0
  44. data/lib/punk/framework/runnable.rb +31 -0
  45. data/lib/punk/framework/service.rb +67 -0
  46. data/lib/punk/framework/view.rb +26 -0
  47. data/lib/punk/framework/worker.rb +34 -0
  48. data/lib/punk/helpers/all.rb +8 -0
  49. data/lib/punk/helpers/loggable.rb +79 -0
  50. data/lib/punk/helpers/publishable.rb +9 -0
  51. data/lib/punk/helpers/renderable.rb +75 -0
  52. data/lib/punk/helpers/swagger.rb +20 -0
  53. data/lib/punk/helpers/validatable.rb +57 -0
  54. data/lib/punk/plugins/all.rb +4 -0
  55. data/lib/punk/plugins/cors.rb +19 -0
  56. data/lib/punk/plugins/ssl.rb +13 -0
  57. data/lib/punk/startup/cache.rb +11 -0
  58. data/lib/punk/startup/database.rb +57 -0
  59. data/lib/punk/startup/environment.rb +10 -0
  60. data/lib/punk/startup/logger.rb +20 -0
  61. data/lib/punk/startup/task.rb +10 -0
  62. data/lib/punk/templates/fail.jbuilder +4 -0
  63. data/lib/punk/templates/fail.rcsv +6 -0
  64. data/lib/punk/templates/fail.slim +9 -0
  65. data/lib/punk/templates/fail.xml.slim +6 -0
  66. data/lib/punk/templates/info.jbuilder +3 -0
  67. data/lib/punk/templates/info.rcsv +2 -0
  68. data/lib/punk/templates/info.slim +6 -0
  69. data/lib/punk/templates/info.xml.slim +3 -0
  70. data/lib/punk/views/all.rb +4 -0
  71. data/lib/punk/views/fail.rb +21 -0
  72. data/lib/punk/views/info.rb +20 -0
  73. data/punk.gemspec +246 -0
  74. metadata +747 -0
data/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to <https://unlicense.org>
@@ -0,0 +1,7 @@
1
+ # Punk!
2
+
3
+ Punk! is an omakase web framework for rapid prototyping.
4
+
5
+ ## Copyright
6
+
7
+ Copyright (c) 2021 Jason Hutchens. See LICENSE for further details.
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+ require 'juwelier'
14
+ Juwelier::Tasks.new do |gem|
15
+ # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
16
+ gem.name = "punk"
17
+ gem.homepage = "https://github.com/kranzky/punk"
18
+ gem.license = "UNLICENSE"
19
+ gem.summary = %Q{Punk! is an omakase web framework for rapid prototyping.}
20
+ gem.description = %Q{}
21
+ gem.email = "lloyd@kranzky.com"
22
+ gem.authors = ["Lloyd Kranzky"]
23
+ gem.required_ruby_version = ">= 2.1"
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Juwelier::RubygemsDotOrgTasks.new
27
+
28
+ require 'yard'
29
+ YARD::Rake::YardocTask.new
30
+
31
+ task :default => :clean
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ require 'rubygems'
6
+ require 'bundler/setup'
7
+ require 'commander/import'
8
+ require_relative '../lib/punk'
9
+
10
+ PUNK.init(task: 'script', config: { app: { name: 'Punk!' } }).config
11
+
12
+ program :name, PUNK.get.app.name
13
+ program :version, PUNK.version
14
+ program :description, 'An omakase web framework for rapid prototyping.'
15
+
16
+ PUNK.commands(:commander)
17
+
18
+ default_command :help
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bootsnap'
4
+
5
+ env = ENV.fetch('PUNK_ENV') { ENV.store('PUNK_ENV', 'development') }
6
+
7
+ if defined?(Bootsnap)
8
+ Bootsnap.setup(
9
+ cache_dir: 'tmp/cache',
10
+ development_mode: env == 'development',
11
+ load_path_cache: true,
12
+ autoload_paths_cache: true,
13
+ disable_trace: false,
14
+ compile_cache_iseq: true,
15
+ compile_cache_yaml: true
16
+ )
17
+ end
18
+
19
+ module PUNK
20
+ def self.init(task: 'server', path: './app', config: {})
21
+ require_relative 'punk/core/interface'
22
+ raise InternalServerError, 'Cannot call PUNK.init multiple times!' if state != :included
23
+ store.args = OpenStruct.new(
24
+ task: task,
25
+ path: path,
26
+ config: config
27
+ )
28
+ store.state = :initialised
29
+ Interface.bootstrap
30
+ self
31
+ end
32
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ PUNK::Command.create "login" do
4
+ description "Authenticate a user by email address or mobile number"
5
+
6
+ option shortcut: :c, name: :claim, type: String, description: "The user's email or phone"
7
+
8
+ def process
9
+ claim = opts[:claim]
10
+ SemanticLogger.flush
11
+ claim ||= ask("Email or Phone: ")
12
+ response =
13
+ PUNK.app.call(
14
+ "REQUEST_METHOD" => "POST",
15
+ "PATH_INFO" => "/sessions",
16
+ "CONTENT_TYPE" => "text/json",
17
+ "SCRIPT_NAME" => "",
18
+ "rack.input" => StringIO.new({ claim: claim }.to_json)
19
+ )
20
+ response = ActiveSupport::JSON.decode(response[-1].first).deep_symbolize_keys
21
+ return if response[:errors].present?
22
+ slug = response[:slug]
23
+ authenticated = false
24
+ while authenticated == false
25
+ SemanticLogger.flush
26
+ secret = ask("Secret: ") { |q| q.echo = '*' }
27
+ response =
28
+ PUNK.app.call(
29
+ "REQUEST_METHOD" => "PATCH",
30
+ "PATH_INFO" => "/sessions/#{slug}",
31
+ "CONTENT_TYPE" => "text/json",
32
+ "SCRIPT_NAME" => "",
33
+ "rack.input" => StringIO.new({ secret: secret }.to_json)
34
+ )
35
+ response = ActiveSupport::JSON.decode(response[-1].first).deep_symbolize_keys
36
+ break if response[:errors].present? && response[:errors].first != 'Secret is incorrect'
37
+ authenticated = response[:message].present?
38
+ end
39
+ response[:message]
40
+ end
41
+ end
42
+
43
+ PUNK::Command.create "logout" do
44
+ description "Delete the current user session"
45
+
46
+ def process
47
+ response =
48
+ PUNK.app.call(
49
+ "REQUEST_METHOD" => "DELETE",
50
+ "PATH_INFO" => "/sessions",
51
+ "SCRIPT_NAME" => "",
52
+ "rack.input" => StringIO.new
53
+ )
54
+ response = ActiveSupport::JSON.decode(response[-1].first).deep_symbolize_keys
55
+ response[:message]
56
+ end
57
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ PUNK::Command.create "generate" do
4
+ shortcut 'g'
5
+ description "Generate routes, actions, models, views, services or workers"
6
+
7
+ def process
8
+ case args.join(' ')
9
+ when 'route', 'action', 'model', 'view', 'service', 'worker', 'scaffold'
10
+ "TBD"
11
+ when '', 'help'
12
+ "? specify one of: routes, actions, models, views, services, scaffold"
13
+ else
14
+ "? unkown arguments: #{args.join(',')}"
15
+ end
16
+ end
17
+ end
18
+
19
+ __END__
20
+ {route}
21
+ # frozen_string_literal: true
22
+
23
+ PUNK.route('{pluralized_name}') do
24
+ authorize!
25
+
26
+ # route: GET|PATCH|DELETE /{pluralized_name}/:id
27
+ on :id do |{name}_id|
28
+ @{name} = {classified_name}[{name}_id.to_i]
29
+ get { present {classified_name}View, {name}: @{name} }
30
+ patch { perform Update{classified_name}, args.merge({name}: @{name}) }
31
+ delete { perform Destroy{classified_name}, {name}: @{name} }
32
+ end
33
+
34
+ # route: GET|POST /{pluralized_name}
35
+ get { perform List{pluralized_classified_name}
36
+ post { perform Create{classified_name}, args }
37
+ end
38
+ {action}
39
+ {list_action}
40
+ {create_action}
41
+ {update_action}
42
+ {destroy_action}
43
+ {model}
44
+ {view}
45
+ {list_view}
46
+ {json_template}
47
+ {json_list_template}
48
+ {csv_template}
49
+ {csv_list_template}
50
+ {html_template}
51
+ {html_list_template}
52
+ {xml_template}
53
+ {xml_list_template}
54
+ {service}
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ PUNK::Command.create "GET" do
4
+ description "Perform a HTTP GET request"
5
+
6
+ def process
7
+ path, query = args[0].split('?')
8
+ PUNK.app.call(
9
+ "REQUEST_METHOD" => "GET",
10
+ "PATH_INFO" => path,
11
+ "QUERY_STRING" => query,
12
+ "SCRIPT_NAME" => "",
13
+ "rack.input" => StringIO.new
14
+ )
15
+ end
16
+ end
17
+
18
+ PUNK::Command.create "PATCH" do
19
+ description "Perform a HTTP PATCH request"
20
+
21
+ def process
22
+ PUNK.app.call(
23
+ "REQUEST_METHOD" => "PATCH",
24
+ "PATH_INFO" => args[0],
25
+ "CONTENT_TYPE" => "text/json",
26
+ "SCRIPT_NAME" => "",
27
+ "rack.input" => StringIO.new(args[1..].join)
28
+ )
29
+ end
30
+ end
31
+
32
+ PUNK::Command.create "POST" do
33
+ description "Perform a HTTP POST request"
34
+
35
+ def process
36
+ PUNK.app.call(
37
+ "REQUEST_METHOD" => "POST",
38
+ "PATH_INFO" => args[0],
39
+ "CONTENT_TYPE" => "text/json",
40
+ "SCRIPT_NAME" => "",
41
+ "rack.input" => StringIO.new(args[1..].join)
42
+ )
43
+ end
44
+ end
45
+
46
+ PUNK::Command.create "PUT" do
47
+ description "Perform a HTTP PUT request"
48
+
49
+ def process
50
+ PUNK.app.call(
51
+ "REQUEST_METHOD" => "PUT",
52
+ "PATH_INFO" => args[0],
53
+ "CONTENT_TYPE" => "text/json",
54
+ "SCRIPT_NAME" => "",
55
+ "rack.input" => StringIO.new(args[1..].join)
56
+ )
57
+ end
58
+ end
59
+
60
+ PUNK::Command.create "DELETE" do
61
+ description "Perform a HTTP DELETE request"
62
+
63
+ def process
64
+ PUNK.app.call(
65
+ "REQUEST_METHOD" => "DELETE",
66
+ "PATH_INFO" => args[0],
67
+ "SCRIPT_NAME" => "",
68
+ "rack.input" => StringIO.new
69
+ )
70
+ end
71
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ PUNK::Command.create "list" do
4
+ shortcut 'l'
5
+ description "List routes, actions, models, views, services or workers"
6
+
7
+ def process
8
+ case args.join(' ')
9
+ when 'routes'
10
+ PUNK.app
11
+ PUNK::App.route_list
12
+ when 'actions'
13
+ ObjectSpace.each_object(PUNK::Action.singleton_class).map(&:name).reject { |name| name.nil? || name =~ /^PUNK/ }
14
+ when 'models'
15
+ ObjectSpace.each_object(PUNK::Model.singleton_class).map(&:name).reject { |name| name.nil? || name =~ /^PUNK/ }
16
+ when 'views'
17
+ ObjectSpace.each_object(PUNK::View.singleton_class).map(&:name).reject { |name| name.nil? || name =~ /^PUNK/ }
18
+ when 'services'
19
+ ObjectSpace.each_object(PUNK::Service.singleton_class).select { |klass| klass.superclass == PUNK::Service }.map(&:name).reject { |name| name.nil? || name =~ /^PUNK/ }
20
+ when 'workers'
21
+ ObjectSpace.each_object(PUNK::Worker.singleton_class).select { |klass| klass.superclass == PUNK::Worker }.map(&:name).reject { |name| name.nil? || name =~ /^PUNK/ }
22
+ when '', 'help'
23
+ "? specify one of: routes, actions, models, views, services, workers"
24
+ else
25
+ "? unkown arguments: #{args.join(',')}"
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,5 @@
1
+ {
2
+ "log": {
3
+ "level": "info"
4
+ }
5
+ }
@@ -0,0 +1,47 @@
1
+ {
2
+ "app": {
3
+ "name": "Unnamed Punk! App",
4
+ "reloadable": false
5
+ },
6
+ "log": {
7
+ "enabled": true,
8
+ "type": "stdout",
9
+ "level": "trace"
10
+ },
11
+ "cookie": {
12
+ "secret": "$COOKIE_SECRET",
13
+ "key": "punk.session"
14
+ },
15
+ "mailgun": {
16
+ "api_key": "$MAILGUN_API_KEY",
17
+ "domain": "$MAILGUN_DOMAIN",
18
+ "postbin": "$MAILGUN_POSTBIN",
19
+ "mock": false,
20
+ "whitelist": []
21
+ },
22
+ "plivo": {
23
+ "auth_id": "$PLIVO_AUTH_ID",
24
+ "auth_token": "$PLIVO_AUTH_TOKEN",
25
+ "number": "$PLIVO_NUMBER",
26
+ "mock": false,
27
+ "whitelist": []
28
+ },
29
+ "userstack": {
30
+ "api_key": "$USERSTACK_API_KEY",
31
+ "use_ssl": false
32
+ },
33
+ "db": {
34
+ "url": "$DATABASE_URL"
35
+ },
36
+ "cache": {
37
+ "servers": "$MEMCACHIER_SERVERS",
38
+ "options": {
39
+ "username": "$MEMCACHIER_USERNAME",
40
+ "password": "$MEMCACHIER_PASSWORD",
41
+ "failover": true,
42
+ "socket_timeout": 1.5,
43
+ "socket_failure_delay": 0.2,
44
+ "down_retry_delay": 60
45
+ }
46
+ }
47
+ }
@@ -0,0 +1,55 @@
1
+ {
2
+ "_env!": "Enum(test, development, staging, production)",
3
+ "_task!": "Enum(server, script, console, worker, spec)",
4
+ "_trace": "String",
5
+ "app": {
6
+ "name!": "String",
7
+ "description": "String",
8
+ "url": "URI",
9
+ "_path!": "Dir",
10
+ "reloadable!": "Flag",
11
+ "client": "URI"
12
+ },
13
+ "cookie": {
14
+ "secret!": "String",
15
+ "key": "String"
16
+ },
17
+ "mailgun": {
18
+ "api_key": "String",
19
+ "domain": "String",
20
+ "postbin": "String",
21
+ "mock": "Flag",
22
+ "whitelist": "Array"
23
+ },
24
+ "plivo": {
25
+ "auth_id": "String",
26
+ "auth_token": "String",
27
+ "number": "String",
28
+ "mock": "Flag",
29
+ "whitelist": "Array"
30
+ },
31
+ "userstack": {
32
+ "api_key": "String",
33
+ "use_ssl": "Flag"
34
+ },
35
+ "log": {
36
+ "enabled!": "Flag",
37
+ "type!": "Enum(stdout, stderr, file)",
38
+ "level!": "Enum(trace, debug, info, warn, error, critical)",
39
+ "path": "File(/*.log$/)"
40
+ },
41
+ "db": {
42
+ "url!": "URI"
43
+ },
44
+ "cache": {
45
+ "servers!": "String",
46
+ "options": {
47
+ "username": "String",
48
+ "password": "String",
49
+ "failover": "Flag",
50
+ "socket_timeout": "Float",
51
+ "socket_failure_delay": "Float",
52
+ "down_retry_delay": "Integer"
53
+ }
54
+ }
55
+ }