punk 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }