smooth 2.0.1 → 2.0.2

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