smooth 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +7 -0
  3. data/Gemfile +1 -2
  4. data/README.md +150 -5
  5. data/Rakefile +16 -0
  6. data/app/assets/javascripts/smooth/index.js +5152 -0
  7. data/bin/smooth +9 -0
  8. data/{app/assets/javascripts/smooth → developer-tools}/.keep +0 -0
  9. data/developer-tools/bower.json +8 -0
  10. data/developer-tools/config.ru +3 -0
  11. data/developer-tools/dist/08d606864d3ad3f0b98660d391f5a1c2.gif +0 -0
  12. data/developer-tools/dist/2d66bcdc27cd89f71068e98a7a929712.gif +0 -0
  13. data/developer-tools/dist/3e9816417b11485d454f9b3662b06e7b.eot +0 -0
  14. data/developer-tools/dist/47de617fd1d745ad120ccb9e2924b98c.gif +0 -0
  15. data/developer-tools/dist/5ae23ad29b67289a1375d2043e289c52.eot +0 -0
  16. data/developer-tools/dist/60c2a8500e63bf211b7df9608f7613ea.svg +450 -0
  17. data/developer-tools/dist/645f50ba6c1e56f078fa018855d97eb0.gif +0 -0
  18. data/developer-tools/dist/71ab514d1cedda303417ad7a06472fea.ttf +0 -0
  19. data/developer-tools/dist/8cca2f02b0af2da365ff4d1755f29146.ttf +0 -0
  20. data/developer-tools/dist/939cf252f0eb4efbd2d170c974411c49.gif +0 -0
  21. data/developer-tools/dist/9af25aaeb6ca6d08d213b04841813eb5.gif +0 -0
  22. data/developer-tools/dist/b683029bafe0305ac2234038a03e1541.woff +0 -0
  23. data/developer-tools/dist/c9dec22105ad9330c811599b8b6464f8.woff +0 -0
  24. data/developer-tools/dist/ca279c55a51ab2641c4712a333633581.gif +0 -0
  25. data/developer-tools/dist/client.js +5152 -0
  26. data/developer-tools/dist/f5b27137d3f5e9b1d91b16b37386dd03.gif +0 -0
  27. data/developer-tools/dist/f99a231ed57ee113b50b1c3e9f9fcdc3.svg +399 -0
  28. data/developer-tools/dist/index.html +18 -0
  29. data/developer-tools/dist/inspector.js +38432 -0
  30. data/developer-tools/dist/jquery.min.js +9190 -0
  31. data/developer-tools/package.json +39 -0
  32. data/developer-tools/server.js +14 -0
  33. data/developer-tools/src/client.coffee +21 -0
  34. data/developer-tools/src/client/collection.coffee +14 -0
  35. data/developer-tools/src/client/model.coffee +11 -0
  36. data/developer-tools/src/client/resource.coffee +132 -0
  37. data/{app/controllers/.keep → developer-tools/src/client/runner.coffee} +0 -0
  38. data/developer-tools/src/dependencies.coffee +7 -0
  39. data/developer-tools/src/inspector.cjsx +49 -0
  40. data/developer-tools/src/inspector/models/interface_collection.coffee +31 -0
  41. data/developer-tools/src/inspector/pages/index.cjsx +31 -0
  42. data/developer-tools/src/inspector/pages/resources.cjsx +5 -0
  43. data/developer-tools/src/inspector/views/grid_sort.cjsx +23 -0
  44. data/developer-tools/src/inspector/views/icon_heading.cjsx +15 -0
  45. data/developer-tools/src/inspector/views/resource_card.cjsx +34 -0
  46. data/developer-tools/src/inspector/views/sidebar.cjsx +12 -0
  47. data/developer-tools/src/inspector/views/toolbar.cjsx +17 -0
  48. data/developer-tools/src/styles/index.scss +136 -0
  49. data/developer-tools/src/styles/views.scss +13 -0
  50. data/developer-tools/src/util.coffee +48 -0
  51. data/developer-tools/webpack.config.js +56 -0
  52. data/developer-tools/webpack.hot.config.js +65 -0
  53. data/lib/smooth.rb +209 -28
  54. data/lib/smooth/active_record/adapter.rb +24 -0
  55. data/lib/smooth/api.rb +272 -18
  56. data/lib/smooth/api/policy.rb +2 -2
  57. data/lib/smooth/api/tracking.rb +4 -4
  58. data/lib/smooth/application.rb +66 -0
  59. data/lib/smooth/cache.rb +1 -1
  60. data/lib/smooth/command.rb +267 -18
  61. data/lib/smooth/command/async_worker.rb +27 -0
  62. data/lib/smooth/command/instrumented.rb +6 -4
  63. data/lib/smooth/command/run_proxy.rb +21 -0
  64. data/lib/smooth/configuration.rb +63 -8
  65. data/lib/smooth/documentation.rb +3 -6
  66. data/lib/smooth/dsl.rb +1 -36
  67. data/lib/smooth/dsl_adapter.rb +34 -0
  68. data/lib/smooth/event.rb +8 -4
  69. data/lib/smooth/event/proxy.rb +9 -0
  70. data/lib/smooth/event/relay.rb +38 -0
  71. data/lib/smooth/example.rb +1 -1
  72. data/lib/smooth/ext/core.rb +16 -0
  73. data/lib/smooth/model_adapter.rb +31 -0
  74. data/lib/smooth/query.rb +143 -13
  75. data/lib/smooth/resource.rb +227 -52
  76. data/lib/smooth/resource/router.rb +217 -0
  77. data/lib/smooth/resource/templating.rb +62 -0
  78. data/lib/smooth/resource/tracking.rb +1 -1
  79. data/lib/smooth/response.rb +73 -0
  80. data/lib/smooth/serializer.rb +102 -11
  81. data/lib/smooth/user_adapter.rb +83 -0
  82. data/lib/smooth/util.rb +17 -0
  83. data/lib/smooth/version.rb +1 -1
  84. data/smooth.gemspec +6 -2
  85. data/spec/acceptance/books_routes_spec.rb +50 -0
  86. data/spec/acceptance/embedded_relationships_spec.rb +26 -0
  87. data/spec/dummy/app/apis/application_api.rb +8 -3
  88. data/spec/dummy/app/commands/create_book.rb +5 -0
  89. data/spec/dummy/app/models/book.rb +1 -0
  90. data/spec/dummy/app/models/library.rb +2 -0
  91. data/spec/dummy/app/models/user.rb +2 -0
  92. data/spec/dummy/app/queries/book_query.rb +13 -0
  93. data/spec/dummy/app/resources/{books.rb → books_definition.rb} +37 -12
  94. data/spec/dummy/db/migrate/20140824215902_create_users.rb +10 -0
  95. data/spec/dummy/db/migrate/20140826193259_create_libraries.rb +10 -0
  96. data/spec/dummy/db/schema.rb +8 -1
  97. data/spec/lib/smooth/api/async_spec.rb +21 -0
  98. data/spec/lib/smooth/api_spec.rb +8 -0
  99. data/spec/lib/smooth/command_spec.rb +87 -6
  100. data/spec/lib/smooth/configuration_spec.rb +4 -0
  101. data/spec/lib/smooth/event/relay_spec.rb +33 -0
  102. data/spec/lib/smooth/event_spec.rb +5 -8
  103. data/spec/lib/smooth/query_spec.rb +42 -0
  104. data/spec/lib/smooth/resource/router_spec.rb +14 -0
  105. data/spec/lib/smooth/resource_spec.rb +33 -1
  106. data/spec/lib/smooth/serializer_spec.rb +20 -0
  107. data/spec/lib/smooth/templating_spec.rb +23 -0
  108. data/spec/lib/smooth/util_spec.rb +22 -0
  109. data/spec/spec_helper.rb +1 -1
  110. metadata +151 -17
  111. data/app/helpers/.keep +0 -0
  112. data/app/mailers/.keep +0 -0
  113. data/app/models/.keep +0 -0
  114. data/app/views/.keep +0 -0
  115. data/spec/dummy/db/development.sqlite3 +0 -0
  116. data/spec/dummy/db/test.sqlite3 +0 -0
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "smooth-io",
3
+ "version": "0.0.1",
4
+ "description": "\"The JS Environment for the Architects App\"",
5
+ "main": "entry.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "author": "",
10
+ "license": "ISC",
11
+ "engine": {
12
+ "node": "0.10.x",
13
+ "npm": "1.3.x"
14
+ },
15
+ "dependencies": {
16
+ "webpack": "^1.4.0-beta4",
17
+ "webpack-dev-server": "latest",
18
+ "coffee-loader": "latest",
19
+ "cjsx-loader": "latest",
20
+ "sass-loader": "latest",
21
+ "style-loader": "latest",
22
+ "css-loader": "latest",
23
+ "file-loader": "latest",
24
+ "backbone": "latest",
25
+ "underscore": "latest",
26
+ "underscore.string": "latest",
27
+ "url-template": "latest",
28
+ "inflection": "latest",
29
+ "bower": "latest",
30
+ "react": "latest",
31
+ "backbone-react-component": "latest",
32
+ "react-treeview": "latest",
33
+ "react-draggable": "latest",
34
+ "react-router-component": "latest",
35
+ "react-hot-loader": "latest",
36
+ "react-tools": "latest"
37
+ }
38
+ }
39
+
@@ -0,0 +1,14 @@
1
+ var webpack = require("webpack"),
2
+ WebpackDevServer = require("webpack-dev-server"),
3
+ config = require("./webpack.hot.config");
4
+
5
+
6
+ var server = new WebpackDevServer(webpack(config), {
7
+ publicPath: config.output.publicPath,
8
+ hot: true,
9
+ stats: {
10
+ colors: true
11
+ }
12
+ });
13
+
14
+ server.listen(4000,'localhost');
@@ -0,0 +1,21 @@
1
+ _ = require("underscore")
2
+ $ = require("jquery")
3
+
4
+ Smooth = {
5
+ version: '0.0.2',
6
+ config: { },
7
+
8
+ Util: require("./util"),
9
+ Model: require("./client/model"),
10
+ Collection: require("./client/collection"),
11
+ Resource: require("./client/resource")
12
+ }
13
+
14
+ Smooth.resource = Smooth.Resource.define
15
+
16
+ Smooth.configure = (options)->
17
+ _.extend(Smooth.config, options)
18
+
19
+ module.exports = Smooth
20
+
21
+ window.Smooth = Smooth if typeof(window) isnt "undefined"
@@ -0,0 +1,14 @@
1
+ _ = require("underscore")
2
+ util = require("../util")
3
+ Backbone = require("backbone")
4
+
5
+ module.exports = Collection = Backbone.Collection.extend
6
+ initialize: (models=[], options={})->
7
+
8
+ if @bootstrap && window?.BootstrappedCollections?[@boostrap]
9
+ models = window.BootstrappedCollections[@bootstrap]
10
+
11
+ Backbone.Collection::initialize.apply(@, arguments)
12
+
13
+ inChunksOf: (size)->
14
+ util.chunk(@models, size)
@@ -0,0 +1,11 @@
1
+ _ = require("underscore")
2
+ util = require("../util")
3
+ Backbone = require("backbone")
4
+
5
+ module.exports = Model = Backbone.Model.extend
6
+ read: (attr)->
7
+ if _.isFunction(@[attr])
8
+ @[attr].call(@)
9
+ else
10
+ @get(attr) || @[attr]
11
+
@@ -0,0 +1,132 @@
1
+ _ = require("underscore")
2
+ util = require("../util")
3
+ Model = require("./model")
4
+ Collection = require("./collection")
5
+
6
+ definitions = {}
7
+
8
+ _resources = {}
9
+
10
+ module.exports = class Resource
11
+ constructor: (options={})->
12
+ _.extend(@, options)
13
+
14
+ getDefinition: ->
15
+ @definition
16
+
17
+ getModelClass: ->
18
+ return @definition.modelClass
19
+
20
+ newModel:(attributes={}, options={})->
21
+ new @getModelClass()(attributes, options)
22
+
23
+ fetch: (options)->
24
+ @getCollection(options).fetch(options)
25
+
26
+ find: (id)->
27
+ @getCollection().get(id)
28
+
29
+ getCollection: (options={})->
30
+ models = options.models
31
+ delete(options.models)
32
+
33
+ if options.private is true
34
+ return @newCollection(models, options)
35
+ else
36
+ @singleton ||= @newCollection(models, options)
37
+
38
+ newCollection:(models=[], options={})->
39
+ new @definition.collectionClass(models, options)
40
+
41
+ _.extend Resource,
42
+ define: (resourceName, options={}, fn=->)->
43
+ if _.isFunction(options)
44
+ fn = options
45
+ options = {}
46
+
47
+ resourceName = "#{util.string.underscored(resourceName)}".toLowerCase()
48
+
49
+ definition = definitions[resourceName] ||= new ResourceDefinition(resourceName, options)
50
+
51
+ fn?.call(definition, resourceName, options)
52
+
53
+ _resources[resourceName] = definition.build()
54
+
55
+ definition
56
+
57
+ reopen: (resourceDefinition)->
58
+ definitions[resourceDefinition]
59
+
60
+ registry: (resourceName, thisIsAGuess=false)->
61
+ # correct guess, first try. great champ.
62
+ if result = _resources[resourceName]
63
+ return result
64
+
65
+ # try an underscored version of whatever was passed.
66
+ if result = @registry(util.string.underscored(resourceName), isAGuess)
67
+ return result
68
+
69
+ # Try one guess, maybe they should lowercase and underscore it
70
+ unless thisIsAGuess
71
+ @registry("#{util.string.underscored(resourceName)}".toLowerCase(), true)
72
+
73
+ class ModelDslAdapter
74
+ constructor: (definition={})->
75
+ @definition = definition
76
+
77
+ url: (url)->
78
+ @definition.url = url
79
+
80
+ public: (extensions)->
81
+ # TODO
82
+ # Build the meta table
83
+ _.extend(@definition, extensions)
84
+
85
+ private: (extensions)->
86
+ # TODO
87
+ # Build the meta table
88
+ _.extend(@definition, extensions)
89
+
90
+ belongsTo: (relation, options={})->
91
+
92
+ hasMany: ->
93
+ # TODO
94
+ # Implement
95
+
96
+ class CollectionDslAdapter extends ModelDslAdapter
97
+ name: "CollectionDslAdapter"
98
+
99
+ class ResourceDefinition
100
+ constructor: (resourceName, options={})->
101
+ @resourceName = resourceName
102
+ @options = options
103
+
104
+ @_collection_interface = {
105
+ public: []
106
+ private: []
107
+ }
108
+
109
+ @_model_interface = {
110
+ public: [],
111
+ private: []
112
+ }
113
+
114
+ @_collection_definition = {}
115
+ @_model_definition = {}
116
+
117
+ @model = new ModelDslAdapter(@_model_definition)
118
+
119
+ @collection = new CollectionDslAdapter(@_collection_definition)
120
+
121
+ build: ->
122
+ @defineModelClass()
123
+ @defineCollectionClass()
124
+ new Resource(definition: @)
125
+
126
+ defineModelClass: ->
127
+ @modelClass ||= Model.extend(@model.definition || {})
128
+
129
+ defineCollectionClass: ->
130
+ definition = @collection.definition || {}
131
+ definition.model = @modelClass || @defineModelClass()
132
+ @collectionClass = Collection.extend(definition)
@@ -0,0 +1,7 @@
1
+ $ = require("jquery")
2
+ _ = require("underscore")
3
+ Backbone = require("backbone")
4
+ React = require("react")
5
+ Router = requir("react-router")
6
+
7
+ require "backbone-react-component"
@@ -0,0 +1,49 @@
1
+ require("semantic/build/packaged/javascript/semantic.js")
2
+ require("semantic/build/packaged/css/semantic.css")
3
+ require("./styles/index.scss")
4
+
5
+ React = require("react")
6
+ Backbone = require("backbone"); require("backbone-react-component")
7
+
8
+ Router = require('react-router-component')
9
+ Link = Router.Link
10
+
11
+ Locations = Router.Locations
12
+ Location = Router.Location
13
+
14
+ Sidebar = require("./inspector/views/sidebar")
15
+ IndexPage = require("./inspector/pages/index")
16
+ ResourcesIndexPage = require("./inspector/pages/resources")
17
+
18
+ InterfaceCollection = require("./inspector/models/interface_collection")
19
+
20
+
21
+ Application = React.createClass
22
+ onBeforeNavigation: ->
23
+ console.log("App on Before Navigation")
24
+
25
+ onNavigation: ->
26
+ console.log("App on Navigation")
27
+
28
+ getInterface: ->
29
+ return @_interface if @_interface
30
+ @_interface = new InterfaceCollection()
31
+ @_interface
32
+
33
+ render: ->
34
+ <div className="wrapper">
35
+ <Sidebar style="inverted thin vertical floating menu" />
36
+ <div className="ui page grid">
37
+ <div className="column">
38
+ <Locations onBeforeNavigation={@onBeforeNavigation} onNavigation={@onNavigation}>
39
+ <Location path="/smooth-developer-tools" handler={IndexPage} collection={@getInterface()}/>
40
+ <Location path="/smooth-developer-tools" handler={IndexPage} collection={@getInterface()}/>
41
+ <Location path="/smooth-developer-tools/resources" handler={ResourcesIndexPage} />
42
+ </Locations>
43
+ </div>
44
+ </div>
45
+ </div>
46
+
47
+ $ ->
48
+ prefix = if window.location.port == "4000" then "" else "/smooth-developer-tools"
49
+ React.renderComponent(Application(prefix: prefix), document.getElementById('application'))
@@ -0,0 +1,31 @@
1
+ _ = require "underscore"
2
+
3
+ InterfaceDocumentation = Backbone.Model.extend(url:->"/api/architects/interface/#{@resource_id}")
4
+
5
+ InterfaceCollection = Backbone.Collection.extend
6
+ model: InterfaceDocumentation
7
+
8
+ url: ->
9
+ # TODO
10
+ window.SmoothInterfaceEndpoint || "/api/architects/interface"
11
+
12
+ parse:(response)->
13
+ {api_meta} = response
14
+
15
+ @meta = api_meta
16
+
17
+ resourceObjects = @toResourceObjects(response)
18
+ console.log("Resources", resourceObjects)
19
+ resourceObjects
20
+
21
+ toResourceObjects:(response)->
22
+ {api_meta} = response
23
+ resource_names = api_meta?.resource_names || []
24
+
25
+ for resourceName in api_meta.resource_names
26
+ resource = response[resourceName] || {}
27
+
28
+ _.extend resource,
29
+ resourceName: resourceName
30
+
31
+ module.exports = InterfaceCollection
@@ -0,0 +1,31 @@
1
+ Link = require('react-router-component').Link
2
+ IconHeading = require("../views/icon_heading")
3
+ GridSort = require("../views/grid_sort")
4
+ ResourceCard = require("../views/resource_card")
5
+ Toolbar = require("../views/toolbar")
6
+
7
+ module.exports = IndexPage = React.createClass
8
+ componentWillMount: ->
9
+ @props.collection.fetch().then ()=> @forceUpdate()
10
+
11
+ getResourceNames: ->
12
+ names = @state?.interface?.api_meta?.resource_names || []
13
+ names
14
+
15
+ prepareResourceCard: (resource)->
16
+ <ResourceCard key={resource.cid} resource={resource} />
17
+
18
+ render: ->
19
+ <div className="page-container">
20
+ <IconHeading title="Smooth API Documentation" />
21
+
22
+ <div className="ui vertical segment">
23
+ <div className="ui right floated basic segment">
24
+ <Toolbar resourceGroups={@props.collection.pluck('resource_group')}/>
25
+ </div>
26
+ </div>
27
+
28
+ <div className="grid-sort-wrapper" style={clear:"both"}>
29
+ <GridSort prepare={@prepareResourceCard} items={@props.collection.models} perRow=3 />
30
+ </div>
31
+ </div>
@@ -0,0 +1,5 @@
1
+ IconHeading = require("../views/icon_heading")
2
+
3
+ module.exports = ResourcesIndexPage = React.createClass
4
+ render: ->
5
+ <IconHeading title="Resources" />
@@ -0,0 +1,23 @@
1
+ util = require("../../util.coffee")
2
+
3
+ module.exports = GridSort = React.createClass
4
+ propTypes:
5
+ prepare: React.PropTypes.func.isRequired
6
+ perRow: React.PropTypes.number.isRequired
7
+
8
+ prepareRow: (row, rowIndex)->
9
+ items = _(row).map(@props.prepare)
10
+
11
+ <div className="row" key={rowIndex}>
12
+ {items}
13
+ </div>
14
+
15
+ render: ->
16
+ groups = util.chunk(@props.items, @props.perRow)
17
+
18
+ rowIndex = 0
19
+ stackable = "stackable" if @props.stackable
20
+
21
+ <div className="ui #{ stackable } grid column #{util.wordsForNumber(@props.perRow)}">
22
+ {@prepareRow(row, rowIndex += 1) for row in groups}
23
+ </div>
@@ -0,0 +1,15 @@
1
+ module.exports = IconHeading = React.createClass
2
+ getDefaultProps: ->
3
+ icon: "cloud"
4
+ iconSize: "large"
5
+ title: ""
6
+ subheading: ""
7
+
8
+ render: ->
9
+ <div className="ui large header">
10
+ <i className="icon #{@props.icon} #{@props.iconSize}" />
11
+ <div className="content">
12
+ {@props.title}
13
+ <div className="sub header">{@props.subheading}</div>
14
+ </div>
15
+ </div>
@@ -0,0 +1,34 @@
1
+ module.exports = ResourceCard = React.createClass
2
+ prepareRouteItem: (description, pattern)->
3
+ <div className="ui item">
4
+ <div className="content">
5
+ <div className="header">{description}</div>
6
+ <div className="description">{pattern}</div>
7
+ </div>
8
+ </div>
9
+
10
+ prepareCommandItem: (item, key)->
11
+ key = "#{item.class}-#{key}"
12
+ console.log(key, item.class)
13
+ <span key={key} className="ui item">{item.class}</span>
14
+
15
+ render: ->
16
+ resource = @props.resource
17
+
18
+ routeItems = _(resource.get("routes")).map(@prepareRouteItem)
19
+ #commandItems = _(resource.get("commands")).map(@prepareCommandItem)
20
+ #serializerItems = _(resource.get("commands")).map(@prepareCommandItem)
21
+ #exampleItems = _(resource.get("commands")).map(@prepareCommandItem)
22
+ #queryItems = _(resource.get("commands")).map(@prepareCommandItem)
23
+
24
+ <div key={resource.cid} className="column resource-card">
25
+ <div className="ui segment raised">
26
+ <h2>{resource.get('resourceName')}</h2>
27
+ <p>{resource.get("group_description")}</p>
28
+ <div className="ui ribbon label">Routes</div>
29
+ <div className="ui route-table very relaxed divided list">
30
+ {routeItems}
31
+ </div>
32
+ </div>
33
+ </div>
34
+