{"action":"created","comment":{"url":"https://api.github.com/repos/emberjs/rfcs/pulls/comments/93176038","pull_request_review_id":13697339,"id":93176038,"diff_hunk":"@@ -0,0 +1,1151 @@\n+- Start Date: 2016-11-05\n+- RFC PR: https://github.com/emberjs/rfcs/pull/176\n+- Ember Issue: (leave this empty)\n+\n+# Summary\n+\n+Make Ember feel less overwhelming to new users, and make Ember applications\n+start faster, by replacing the `Ember` global with a first-class system for\n+importing just the parts of the framework you need.\n+\n+# Motivation\n+\n+ECMAScript 2015 (also known as ES2015 or ES6) introduced a syntax for importing\n+and exporting values from modules. Ember aggressively adopted modules, and if\n+you've used Ember before, you're probably familiar with this syntax:\n+\n+```js\n+import Ember from \"ember\";\n+import Analytics from \"../mixins/analytics\";\n+\n+export default Ember.Component.extend(Analytics, {\n+  // ...\n+});\n+```\n+\n+One thing to notice is that the entire Ember framework is imported as a single\n+package. Rather than importing `Component` directly, for example, you import\n+`Ember` and subclass `Ember.Component`. (And this example still works even if\n+you forget the import, because we also create a global variable called\n+`Ember`.)\n+\n+Using Ember via a monolithic package or global object is not ideal for several\n+reasons:\n+\n+* It's overwhelming for learners. There's a giant list of classes and functions\n+  with no hints about how they're related. The API documentation reflects this.\n+* Experienced developers who don't want all of Ember's features feel like\n+  they're adding unnecessary and inescapable bloat to their application.\n+* The `Ember` object must be built at boot time, requiring that we ship the\n+  entire framework to the browser. This has two major costs:\n+  1. Increased download time, particularly noticeable on slower connections.\n+  2. Increased parsing/evaluation cost, which still must be paid even when\n+     assets are cached. On some browsers/devices, this can far exceed the cost of the\n+     download itself.\n+\n+Defining a public API for importing parts of Ember via JavaScript modules helps\n+us lay the groundwork for solving all of these problems.\n+\n+#### Reducing Load Time\n+\n+Modules help us eliminate unneeded code. The module syntax is _statically\n+analyzable_, meaning that a tool like Ember CLI can analyze an application's\n+source code and reliably determine which files, in both the framework and the\n+application, are actually needed. Anything that's not needed is omitted from the\n+final build.\n+\n+This allows us to provide the file size benefits of a \"small modules\" approach\n+to building web applications while retaining the productivity benefits of a\n+complete, opinionated framework.\n+\n+For example, if your application never used the `Ember.computed.union` computed\n+property helper, Ember could detect this and remove its code when you build your\n+application. This technique for slimming down the payload automatically is often\n+referred to as _tree shaking_ or _dead code elimination_.\n+\n+Building the module graph doesn't just mean we get a list of files used by the application—\n+we also know which files are used _route-by-route_.\n+\n+We can use this knowledge to optimize boot time even more, by prioritizing\n+sending only the JavaScript needed for the requested route, rather than the\n+entire application.\n+\n+For example, if the user requests the URL\n+`https://app.example.com/articles/123`, the server could first send the code for\n+`ArticlesRoute`, the `Article` model, the `articles` template, and any\n+components and framework code used in the route. Only after the route is\n+rendered would we start to send the remainder of the application and framework\n+code in the background.\n+\n+#### Guiding Learners\n+\n+We can group framework classes and utilities by functionality, making it clear\n+what things are related and how they should work together. People can feel\n+confident they are getting only what they need at that moment, not an entire\n+framework that they're not sure they're benefiting from.\n+\n+#### Modernizing Ember\n+\n+Lastly, developers are growing increasingly accustomed to using JavaScript\n+modules to import libaries. If we don't adapt to modules, Ember will feel clunky\n+and antiquated compared to modern alternatives.\n+\n+### Prior Art\n+\n+Initial efforts to define a module API for Ember began with the\n+[`ember-cli-shims`][shims] addon. This addon provides a set of \"shim\" modules\n+that re-export a value off the global `Ember`. While this setup doesn't offer\n+the benefits of true modules, it did allow us to rapidly experiment with a\n+module API without making changes to Ember core.\n+\n+[shims]: https://github.com/ember-cli/ember-cli-shims\n+\n+Common feedback from shim users was that, while they were a net improvement,\n+they introduced too much verbosity and were hard for beginners to remember.\n+\n+An oft-cited example of this verbosity is that implementing an object and using\n+`Ember.get` and `Ember.set` requires three different imports:\n+\n+```js\n+import EmberObject from \"ember-object\";\n+import get from \"ember-metal/get\";\n+import set from \"ember-metal/set\";\n+```\n+\n+In fact, one of the principles outlined in this RFC is designed to correct this\n+verbosity; namely, that [utility functions and the class they are related to\n+should share a module](#utility-functions-are-named-exports).\n+\n+For those who have already adopted modules via the `ember-cli-shims` package, we\n+will provide a migration tool to rewrite shim modules into the final module API.\n+The static nature of the import syntax makes this even easier and more reliable\n+than migrating globals-based apps. The upgrade process should take no more than\n+a few minutes (see [Migration](#migration)).\n+\n+This RFC also builds significantly on [@zeppelin's](https://github.com/zeppelin)\n+previous [ES6 modules RFC](https://github.com/emberjs/rfcs/pull/68), which drove\n+initial discussion, including the idea to use scoped packages.\n+\n+# Detailed Design\n+\n+## Terminology\n+\n+* **Package** - a bundle of JavaScript addressable by npm and other package\n+  managers, it may contain many modules (but has a default module, usually\n+  called `index.js`).\n+* **Scoped Package** - a namespaced package whose name starts with an `@`, like\n+  `import Thing from \"@scope/thing\"`.\n+* **Module** - a JavaScript file with at least one default export or named\n+  export.\n+* **Top-Level Module** - the module provided by importing a package directly,\n+  like `import Component from \"@ember/component\"`.\n+* **Nested Module** - a module provided at a path _inside_ a package, like\n+  `import { addObserver } from \"@ember/object/observers\"`.\n+\n+## Module Naming & Organization\n+\n+Because our goal is to eliminate the `Ember` global object, any public classes,\n+functions or properties that currently exist on the global need an equivalent\n+module that can be imported.\n+\n+Given how fundamental modules are to the development process, how we organize\n+and name them impacts new learners and seasoned veterans alike. Thus we must try\n+to find a balance between predictability for new and intermediate users, and\n+terseness for experienced developers with large apps.\n+\n+There is another goal at play: we would like to help dispel the misconception\n+that Ember is a monolithic framework. Ideally, module names help us tell a story\n+about Ember's layered features. Rather than inheriting the entire framework at\n+once, you can pull in just the pieces you need.\n+\n+For that reason, package names should assist the developer in understanding what\n+capabilities are added by bringing in that new package. We should pick\n+meaningful names, not let our public API be a by-product of how Ember's\n+internals are organized.\n+\n+A full table of proposed mappings from global to module is available in\n+[Addendum 1 - Table of Module Names and Exports by\n+Global](#addendum-1---table-of-module-names-and-exports-by-global) and [Addendum\n+2 - Table of Module Names and Exports by\n+Package](#addendum-2---table-of-module-names-and-exports-by-package). Because\n+there is some implicit functionality that you get when loading Ember that is not\n+encapsulated in a global property (for example, automatically adding prototype\n+extensions), there is also [Addendum 3 - Table of Modules with Side\n+Effects](#addendum-3---table-of-modules-with-side-effects).\n+\n+Before diving in to these tables, however, it may be helpful to understand some\n+of the thinking that guided this proposal. And keep in mind, this RFC specifies\n+a _baseline_ module API. Nothing here precludes adding additional models in the\n+future, as we discover missing pieces.\n+\n+### Use Scoped Packages\n+\n+Last year, [npm introduced support for scoped packages][scoped-packages]. Scopes\n+are similar to organizations on GitHub. They allow us to use any package name,\n+even if it's already in use on npm, by namespacing it inside a scope.\n+\n+[scoped-packages]: http://blog.npmjs.org/post/116936804365/solving-npms-hard-problem-naming-packages\n+\n+For example, the [`component`][component] package is already reserved by an\n+unmaintained tool; we couldn't use `component` as a package name even if we\n+wanted to.\n+\n+[component]: https://www.npmjs.com/package/component\n+\n+However, scopes allow us to create a package named `component` that lives under\n+the `@ember` scope: `import Component from \"@ember/component\"`.\n+\n+The advantages of using scoped packages, as this proposal does, are two-fold:\n+\n+1. \"Official\" packages are clearly differentiated from community packages.\n+2. There is no risk of naming conflicts with existing community packages.\n+\n+Note that actually publishing packages to npm may not be immediately necessary\n+to implement this RFC. We should still design around this constraint so that we\n+have the option available to us in the future. For more discussion, see the\n+[Distribution unresolved question](#distribution).\n+\n+### Prefer Common Terminology\n+\n+Module names should use terms people are more likely to be familiar with. For\n+example, instead of the ambiguous `platform`, polyfills should be in a module\n+called `polyfill`.\n+\n+Similarly, the vast majority of advanced Ember developers couldn't crisply\n+articulate the difference between `ember-metal` and `ember-runtime`. Instead, we\n+should prefer `ember-object`, to match how people actually talk about these\n+features: the Ember object model.\n+\n+### Organize by Mental Model\n+\n+One of the biggest barriers to learning is the fact that short-term memory is\n+limited. To understand a complex system like a modern web application, the\n+learner must hold in their head many different concepts—more concepts than most\n+people can reason about at once.\n+\n+[Chunking][chunking] is a strategy for dealing with this. It means that you\n+present concepts that are conceptually related together. When the learner needs\n+to reason about the overall system, in their mind they can replace a group of\n+related concepts with a single, overarching concept.\n+\n+[chunking]: https://en.wikipedia.org/wiki/Chunking_(psychology)\n+\n+For example, if you tell someone that in order to build an Ember app, they will\n+need to understand computed properties, actions (bubbling and closure),\n+components, containers, registries, routes, helpers (stateful and stateless),\n+dependent keys, controllers, route maps, observers, transitions, mixins,\n+computed property macros, injected properties, the run loop, and array\n+proxies—they will rightfully feel like Ember is an overwhelming, overcomplicated\n+framework. Most people (your RFC author included) simply cannot keep this many\n+discrete concepts in their head at once.\n+\n+The day-to-day reality of building an Ember app, of course, is not nearly so\n+complex. For those developers who stick through the learning curve, they end up\n+with a greatly simplified mental model.\n+\n+This proposal attempts to re-align module naming with that simplified mental\n+model, placing everything into packages based on the chunk of functionality they\n+provide:\n+\n+* `@ember/application` - Application-level concerns, like bootstrapping,\n+  initializers, and dependency injection.\n+* `@ember/component` - Classes and utilities related to UI components.\n+* `@ember/routing` - Classes used for multi-page routing.\n+* `@ember/service` - Classes and utilities for cross-cutting services.\n+* `@ember/controller` - Classes and utilities related to controllers.\n+* `@ember/object` - Classes and utilities related to Ember's object model,\n+  including `Ember.Object`, computed properties and observers.\n+* `@ember/runloop` - Methods for scheduling behavior on to the run loop.\n+\n+It includes a few other packages that, over time, your author hopes become\n+either unneeded or can be moved outside of core into standalone packages:\n+\n+* `@ember/array` - Array utilities and observation. Ideally these can be replaced\n+  with a combination of ES2015+ features and array diffing in Glimmer.\n+* `@ember/enumerable` - Replaced by iterables in ES2015.\n+* `@ember/string` - String formatting utilities (dasherize, camelize, etc.).\n+* `@ember/map` - Replaced by `Map` and `WeakMap` in ES2015.\n+* `@ember/polyfills` - Polyfills for `Object.keys`, `Object.assign` and `Object.create`.\n+* `@ember/utils` - Grab bag of utilities that could likely be replaced with\n+  something like lodash.\n+\n+And finally, some packages that may be used by internals, extensions, or addons\n+but are not used day-to-day by app developers:\n+\n+* `@ember/instrumentation` - Instrumentation hooks for measuring performance.\n+* `@ember/debug` - Utility functions for debugging, and hooks used by debugger tools like Ember Inspector.\n+\n+### Classes are Default Exports\n+\n+Classes that the user is supposed to import and subclass are always the default\n+export, never a named export. In the case where a package has more than one primary class,\n+those classes live in a nested module.\n+\n+This rule ensures there is no ambiguity about whether something is a named\n+export or a default export: classes are always default exports. In tandem with\n+the following rule ([Utility Functions are Named\n+Exports](#utility-functions-are-named-exports)), this also means that classes\n+and the functions that act on them are grouped into the same `import` line.\n+\n+#### Examples\n+\n+Primary class only:\n+\n+```js\n+import EmberObject from \"@ember/object\";\n+```\n+\n+Primary class plus secondary classes:\n+\n+```js\n+import Component from \"@ember/component\";\n+import Checkbox from \"@ember/component/checkbox\";\n+\n+import Map from \"@ember/map\";\n+import MapWithDefault from \"@ember/map/with-default\";\n+```\n+\n+Multiple primary classes:\n+\n+```js\n+import Router from \"@ember/routing/router\";\n+import Route from \"@ember/routing/route\";\n+```\n+\n+### Utility Functions are Named Exports\n+\n+Functions that are only useful with a particular class, or are used most frequently with\n+that class, are named exports from the package that exports the class.\n+\n+#### Examples\n+\n+```js\n+import Service, { inject } from \"@ember/service\";\n+import EmberObject, { get, set } from \"@ember/object\";\n+```\n+\n+In cases where there are many utility functions associated with a class, they can be further subdivided into\n+nested packages but remain named exports:\n+\n+```js\n+import EmberObject, { get, set } from \"@ember/object\";\n+import { addObserver } from \"@ember/object/observers\";\n+import { addListener } from \"@ember/object/events\";\n+```\n+\n+In the future, [decorators][decorators] would be included under this rule as\n+well. In fact, designing with an eye towards decorators was a large driver\n+behind this principle. For more discussion, see the [Everything is a Named\n+Export alternative](#everything-is-a-named-export).\n+\n+[decorators]: http://tc39.github.io/proposal-decorators/\n+\n+### One Level Deep\n+\n+To avoid deep directory hierarchies with mostly-empty directories, this proposal\n+limits nesting inside a top-level package to a single level. Deep nesting like\n+this can add additional time to navigating the hierarchy without adding much\n+benefit.\n+\n+Java packages often have this problem due to their URL-based namespacing; see\n+e.g. [this Java\n+library](https://github.com/elvishew/xLog/tree/fbfb60f9472e32723436b3d6bdd6c1878a5afb37/library/src)\n+where you end up with deeply nested directories, like\n+`xLog/library/src/test/java/com/elvishew/xlog/printer/AndroidPrinterTest.java`.\n+\n+This rule leads to including the type in the name of the module in some cases\n+where it might otherwise be grouped instead. For example, instead of\n+`@ember/routing/locations/none`, we prefer `@ember/routing/none-location` to\n+avoid the second level of nesting.\n+\n+### No Non-Module Namespaces\n+\n+The global version of Ember includes several functions that also act as a\n+namespace to group related functionality.\n+\n+For example, `Ember.run` can be used to run some code inside a run loop, while\n+`Ember.run.scheduleOnce` is used to schedule a function onto the run loop once.\n+\n+Similarly, `Ember.computed` can be used to indicate a method should be treated as\n+a computed property, but computed property macros also live on `Ember.computed`, like\n+`Ember.computed.alias`.\n+\n+When consumed via modules, these functions no longer act as a namespace. That's\n+because tacking these secondary functions on to the main function requires us to\n+eagerly evaluate them (not to mention the potential deoptimizations in\n+JavaScript VMs by adding properties to a function object).\n+\n+In practice, that means that this won't work:\n+\n+```js\n+// Won't work!\n+import { run } from \"@ember/runloop\";\n+run.scheduleOnce(function() {\n+  // ...\n+});\n+```\n+\n+Instead, you'd have to do this:\n+\n+```js\n+import { scheduleOnce } from \"@ember/runloop\";\n+scheduleOnce(function() {\n+  // ...\n+});\n+```\n+\n+The [migration tool](#migration), described below, is designed to detect these\n+cases and migrate them correctly.\n+\n+### Prototype Extensions and Other Code with Side Effects\n+\n+Some parts of Ember change global objects rather than exporting classes or\n+functions. For example, Ember (by default) installs additional methods on\n+`String.prototype`, like the `camelize()` method.\n+\n+Any code that has side effects lives in a module without any exports; importing\n+the module is enough to produce the desired side effects. For example, if I\n+wanted to make the string extensions available to the application, I could\n+write:\n+\n+```js\n+import \"@ember/extensions/string\"\n+```\n+\n+Generally speaking, modules that have side effects are harder to debug and can\n+cause compatibility issues, and should be avoided if possible.\n+\n+## Migration\n+\n+To assist in assessing this RFC in real-world applications, and to help upgrade\n+apps should this RFC be accepted and implemented, your author has provided an\n+automatic migration utility, or \"codemod\":\n+\n+[ember-modules-codemod][ember-modules-codemod]\n+\n+To run the codemod, `cd` into an existing Ember app and run the following commands.\n+\n+```sh\n+npm install ember-modules-codemod -g\n+ember-modules-codemod\n+```\n+\n+**Note**: The codemod currently requires Node 6 or later to run.\n+\n+This codemod uses [`jscodeshift`](https://github.com/facebook/jscodeshift) to\n+update an Ember application in-place to the module syntax proposed in this RFC.\n+It can update apps that use the global `Ember`, and will eventually also support\n+apps using [ember-cli-shims][shims].\n+\n+[shims]: https://github.com/ember-cli/ember-cli-shims\n+\n+**Make sure you save any changes in your app before running the codemod, because\n+it modifies files in place. Obviously, because this RFC is speculative, your app\n+will not function after applying this codemod. For now, the codemod is only\n+useful for assessing how this proposal looks in real-world applications.**\n+\n+For example, it will rewrite code that looks like this:\n+\n+```js\n+export default Ember.Component.extend({\n+  isAnimal: Ember.computed.or('isDog', 'isCat')\n+});\n+```\n+\n+Into this:\n+\n+```js\n+import Component from \"@ember/component\";\n+import { or } from \"@ember/object/computed\"\n+\n+export default Component.extend({\n+  isAnimal: or('isDog', 'isCat')\n+});\n+```\n+\n+For more information, see the [README][ember-modules-codemod].\n+\n+[ember-modules-codemod]: https://github.com/tomdale/ember-modules-codemod\n+\n+# How We Teach This\n+\n+This RFC makes changes to one of the most foundational (and historically stable)\n+concepts in Ember: how you access framework code. Because of that, it is hard to\n+overstate the impact these changes will have. We need to proceed carefully to\n+avoid confusion and churn.\n+\n+It is possible that the work required to update the documentation and other\n+learning materials will be significantly more than the work required to do the\n+actual implementation. That means we need to start getting ready _now_, so that\n+when the code changes are ready, it is not blocked by a big documentation\n+effort.\n+\n+That said, we do have the advantage of the new modules being \"just JavaScript.\"\n+We can lean heavily on the greater JavaScript community's learning materials,\n+and any teaching we do has the benefit of being transferable and not an\n+\"Ember-only\" skill.\n+\n+## Documentation Examples\n+\n+Examples in the Getting Started tutorial, guides and API docs will need to be\n+updated to the new module syntax.\n+\n+Probably the most efficient and least painful way to do this would be to write a\n+tool that can extract code snippets from Markdown files and run the\n+[migrator](#migration) on them, then replace the extracted code with the updated\n+version. For the API docs, this tool would need to be able to handle Markdown embedded\n+in JSDoc-style documentation.\n+\n+The benefit of this approach is that, once we have verified the script works\n+reliably, we can wait until the last possible moment to make the switch. If we\n+attempt to update everything by hand, the duration and tediousness of that\n+process will likely take out an effective \"lock\" on the documentation code base,\n+where people will put off making big changes because of the potential for merge\n+conflicts.\n+\n+## Generators\n+\n+Generators are used by new users to help them get a handle on the framework, and\n+by experienced users to avoid typing repetitive boilerplate. We need to ensure\n+that the generators that ship with Ember are updated to use modules as soon as\n+they are ready. The recent work by the Ember CLI team to ship generators with\n+the Ember package itself, rather than Ember CLI, should make this relatively\n+painless.\n+\n+## API Documentation\n+\n+Our API documentation has long been a source of frustration, because the laundry\n+list of (often rarely used or internal) classes makes Ember feel far more\n+overwhelming than it really is.\n+\n+The shift to modules gives us a good opportunity to rethink the presentation of\n+our API documentation. Instead of the imposing mono-list, we should group the\n+API documentation by package–which, conveniently in this proposal, means they\n+will also be grouped by area of functionality.\n+\n+We should investigate the broader ecosystem to see if there is a good tool that\n+generates package-oriented documentation for JavaScript projects. If not, we may\n+wish to adapt an existing tool to do so.\n+\n+## Explaining the Migration\n+\n+Once the guides and API documentation are updated, modules should be\n+straightforward for new learners—indeed, more and more new learners are starting\n+with JavaScript modules as the baseline.\n+\n+The most challenging aspect of teaching the new modules API, counterintuitively,\n+will likely be _existing_ users. In particular, for changes that touch nearly\n+every file, most teams working on large apps cannot pause work for a week to\n+implement the change.\n+\n+Our focus needs to be:\n+\n+* Communicating clearly that the existing global build will work for the\n+  foreseeable future.\n+* Making clear the file size benefits of moving to modules.\n+* Building robust tooling that allows even large apps to migrate in a day or\n+  two, not a week.\n+\n+It is important to frame the module transition as a carrot, not a stick. We\n+should avoid dire warnings or deprecation notices. Instead, we should provide\n+good reporting when doing Ember CLI builds. If an app is compiled in globals\n+mode, we can offer suggestions for how to reduce the file size, providing a\n+helpful pointer to the modules migration guide. This will make the transition\n+feel less like churn and more like an optimization opportunity that developers\n+can take advantage of when they have the time or resources.\n+\n+### Addons\n+\n+One pitfall is that a _single_ use of the `Ember` global means we have to\n+include the entire framework. That means that a developer could migrate their\n+entire app to modules, but a single old addon that uses the Ember globals will\n+negate the benefits.\n+\n+This requires a two-pronged strategy:\n+\n+* Tight integration into Ember CLI\n+  * Good reporting to make it obvious when a fallback to globals mode\n+  occurs, and which addons/files are causing it.\n+  * An opt-in mode to prohibit globals mode. Installing an incompatible addon\n+    would produce an error.\n+* Community outreach and pull requests to help authors update addons.\n+\n+# Drawbacks\n+\n+## Complexity\n+\n+There is something elegantly simple about a single `Ember` global that contains\n+everything. Introducing multiple packages means you don't just have to know what\n+you need—you also need to know where to import it from.\n+\n+JavaScript module syntax is also something not everyone will be familiar with,\n+given its newness. However, this is something we must deal with anyway because\n+module syntax is already in use within apps.\n+\n+## Module Churn\n+\n+The `ember-cli-shims` package is already included by default in new Ember apps,\n+and is in fairly common usage. Many developers are already familiar with its\n+API. This drawback can be at least partially mitigated by [the automated\n+migration process](#migration), which will be easily applied to existing shimmed\n+apps.\n+\n+## Scoped Packages Are an Unknown Quantity\n+\n+This proposal relies on scoped packages. Despite being released over a year ago,\n+scoped packages are not always well supported.\n+\n+For example, [scoped packages currently wreak havoc on Yarn][yarn]. Until very\n+recently, the [npmjs.com](https://npmjs.com) search did not include scoped\n+packages. Generally speaking, there will be a long-tail of tools in the\n+ecosystem that will choke on scoped packages.\n+\n+That said, Angular 2 is distributed under the `@angular` scope, and TypeScript\n+recently adopted the `@types` scope for publishing TypeScript typings to npm.\n+The popularity of both of these should drive compatibility. Despite this, we can\n+expect [similar compatibility issues][scoped-proxy-issue] for some time.\n+\n+[yarn]: https://github.com/yarnpkg/yarn/issues?utf8=✓&q=is%3Aissue%20is%3Aopen%20scoped%20packages\n+[scoped-proxy-issue]: https://github.com/angular/angular/issues/8422\n+\n+## Nested Modules\n+\n+To satisfy the [Classes are Default Exports](#classes-are-default-exports) rule,\n+this RFC proposes the use of nested modules. That is, a module name may contain\n+an additional path segment beyond the package name. For example,\n+`@ember/object/observers` is a nested module, while `@ember/object` is not.\n+\n+In the Node/CommonJS world, nested modules are unusual but not unheard of. For\n+example, Lodash offers a [functional programming\n+style](https://github.com/lodash/lodash/wiki/FP-Guide) accessed by calling\n+`require('lodash/fp')`.\n+\n+There are two drawbacks associated with nested modules:\n+\n+1. Because they are uncommon, developers may be confused by the syntax.\n+2. Because they allow you to \"reach in\" to the package for an\n+   arbitrary file, encouraging the end user to use nested modules may\n+   inadvertently _also_ encourage them to access private modules, thinking they are\n+   public.\n+\n+The first issue is surmountable with education, good reference documentation,\n+and good tools to help guide developers in the right direction. That this style\n+is uncommon in the Node ecosystem seems to be more a [function of\n+dogma](http://blog.izs.me/post/44149270867/why-no-directorieslib-in-node-the-less-snarky)\n+than any technical shortcoming of nested modules.\n+\n+To ensure that developers don't inadvertently access private modules, we have\n+two good options:\n+\n+1. Package modules in such a way that private modules _cannot_ be accessed.\n+2. Take a page from Ember Data and put all private modules in a `-private`\n+   directory, hopefully making it clear accessing this module is not playing by\n+   the rules.\n+\n+We could avoid using this uncommon style by hoisting nested modules up to their\n+own package. For example, `@ember/object/observers` could become\n+`@ember/observers` or `@ember/object-observers`. However, because I could not\n+find a strong technical reason against it, and because having more packages is\n+in tension with the explicit goal to [make Ember feel less\n+overwhelming](#organize-by-mental-model), I decided it was worth the small cost.\n+\n+# Alternatives\n+\n+### `ember-` prefix\n+\n+One alternative to the `@ember` scope is to use the `ember-` prefix. This avoids\n+the drawbacks around scoped packages described above. However, they would be\n+indistinguishable from the large number of community packages that begin with\n+`ember-`.\n+\n+### Everything is a Named Export\n+\n+This proposal argues that classes should be a module's default export, and any\n+utility functions should be a named export. That means you can never have more\n+than one class per module, and _that_ means, inherently, more `import`\n+statements than a system where multiple classes can live in one module.\n+\n+Additionally, in cases where there is not a clear \"primary\" class, this can feel\n+a little awkward:\n+\n+```js\n+import Route from \"@ember/routing/route\";\n+import Router from \"@ember/routing/router\";\n+```\n+\n+One commonly proposed alternative is to say that classes become named exports,\n+and default exports are not used at all. The above example would become:\n+\n+```js\n+import { Route, Router } from \"@ember/routing\";\n+```\n+\n+In this case, classes are distinguished by being capitalized, rather than by\n+being a default export.\n+\n+There is one major change coming to JavaScript and Ember that, your author\n+believes, deals a fatal blow to this approach: decorators.\n+\n+If you're unfamiliar with decorators, see [Addy Osmani's great\n+overview][decorators]. Decorators provide a mechanism for adding declarative\n+annotations to classes, methods, properties and functions.\n+\n+[decorators]: https://medium.com/google-developers/exploring-es7-decorators-76ecb65fb841#.y9umddvsl\n+\n+For example, Robert Jackson has an [experimental library for using decorators to\n+annotate computed properties in a class][ember-computed-decorators]. Something\n+like this will probably make its way into Ember in the future:\n+\n+```js\n+import EmberObject, { computed } from \"@ember/object\";\n+\n+export default class Cat extends EmberObject {\n+  @computed(\"hairLength\")\n+  isDomesticShortHair(hairLength) {\n+    return hairLength < 3;\n+  }\n+}\n+```\n+\n+[ember-computed-decorators]: https://github.com/rwjblue/ember-computed-decorators\n+\n+Most decorators are tightly coupled to a particular class because they configure\n+some aspect of behavior that is only relevant to that class. If every decorator\n+and every class share a namespace, it is hard to identify which go with each\n+other.\n+\n+```js\n+import { Router, Route, resource, model, location, inject, queryParam } from \"@ember/routing\";\n+```\n+\n+Can you tell me which of these decorators goes with which class?\n+\n+And this import is getting so long, you'd probably be tempted to break it up\n+into multiple lines _anyway_, so it's not clear that it's actually a win over\n+separate imports.\n+\n+Contrast this with the same thing expressed using the rules in\n+this RFC:\n+\n+```js\n+import Router, { resource, location } from \"@ember/routing/router\";\n+import Route, { model, inject, queryParam } from \"@ember/routing/route\";\n+```\n+\n+Here, the decorators are clearly tied to their class. And it's far nicer from a\n+refactoring perspective: if you delete a class from a file, you then delete a\n+single line from your imports.\n+\n+Contrast that with making fiddly edits to a long list of named exports unrelated\n+to each other.\n+\n+# Unresolved Questions\n+\n+### Intimate APIs\n+\n+How much do we want to provide module API for so-called \"intimate\n+APIs\"—technically private, but in widespread use?\n+\n+### Backwards Compatibility for Addons\n+\n+How do we provide an API for addons to use modules but fall back to globals mode\n+in older versions of Ember? We should ensure that, at minimum, addons can\n+continue to support LTS releases. At the same time, it's critical that adding an\n+addon doesn't opt your entire application back in to the entire framework.\n+\n+Because there is a lot of implementation-specific detail to get right here, and\n+because it doesn't otherwise block landing this module naming RFC, the final\n+design of API for addon authors should be broken out into a separate RFC.\n+\n+### Distribution\n+\n+In practice, how do we ship this code to end users of Ember CLI?\n+\n+When building client-side apps, it's very important to avoid duplicate\n+dependencies, which can quickly cause file size to balloon out of control.\n+\n+Unfortunately, npm@3's de-duping is so naïve that it's likely that users would\n+end up in dependency hell if we shipped the framework as separate npm packages.\n+There's no good way to ship dependencies in version lockstep and feel confident\n+that they will reliably be de-duped.\n+\n+Until Yarn usage is more widespread, and to eliminate significant complexity in\n+the first iteration, it probably makes sense for the first phase of\n+implementation to continue shipping a single npm package that Ember CLI apps can\n+depend on. This gives us atomic updates and makes sure you never have one piece\n+of the framework interacting with a different piece that is inadvertently three\n+versions old.\n+\n+What this means is that, rather than shipping `@ember/object` on npm, we'd ship\n+a single `ember-source` (or something) package that includes the entire\n+framework. At build time, the Ember build process would virtually map the\n+`@ember/object` package to the right file inside `ember-source`. In essence, all\n+of the benefits of smaller bundles without the boiling hellbroth of managing\n+dependencies.\n+\n+That said, because this RFC is designed with an eye towards eventually\n+publishing each package to npm individually, we will have that option available\n+to us in the future once we determine that we can do so without causing lots of\n+pain.\n+\n+# Addenda\n+\n+_(Ed. note: These tables are automatically generated from the scripts in the [codemod][codemod] repository.)_\n+\n+[codemod]: https://github.com/tomdale/ember-modules-codemod\n+\n+## Addendum 1 - Table of Module Names and Exports by Global\n+\n+| Before                                | After                                                                      |\n+| ---                                   | ---                                                                        |\n+| `Ember.$`                             | `import $ from \"jquery\"`                                                   |\n+| `Ember.A`                             | `import { A } from \"@ember/array\"`                                         |\n+| `Ember.Application`                   | `import Application from \"@ember/application\"`                             |\n+| `Ember.Array`                         | `import EmberArray from \"@ember/array\"`                                    |\n+| `Ember.ArrayProxy`                    | `import ArrayProxy from \"@ember/array/proxy\"`                              |\n+| `Ember.AutoLocation`                  | `import AutoLocation from \"@ember/routing/auto-location\"`                  |\n+| `Ember.Checkbox`                      | `import Checkbox from \"@ember/component/checkbox\"`                         |\n+| `Ember.Component`                     | `import Component from \"@ember/component\"`                                 |\n+| `Ember.ContainerDebugAdapter`         | `import ContainerDebugAdapter from \"@ember/debug/container-debug-adapter\"` |\n+| `Ember.Controller`                    | `import Controller from \"@ember/controller\"`                               |\n+| `Ember.DataAdapter`                   | `import DataAdapter from \"@ember/debug/data-adapter\"`                      |\n+| `Ember.DefaultResolver`               | `import GlobalsResolver from \"@ember/application/globals-resolver\"`        |\n+| `Ember.Enumerable`                    | `import Enumerable from \"@ember/enumerable\"`                               |\n+| `Ember.Evented`                       | `import Evented from \"@ember/object/evented\"`                              |\n+| `Ember.HashLocation`                  | `import HashLocation from \"@ember/routing/hash-location\"`                  |\n+| `Ember.Helper`                        | `import Helper from \"@ember/component/helper\"`                             |\n+| `Ember.Helper.helper`                 | `import { helper } from \"@ember/component/helper\"`                         |\n+| `Ember.HistoryLocation`               | `import HistoryLocation from \"@ember/routing/history-location\"`            |\n+| `Ember.Location`                      | `import Location from \"@ember/routing/location\"`                           |\n+| `Ember.Map`                           | `import EmberMap from \"@ember/map\"`                                        |\n+| `Ember.MapWithDefault`                | `import MapWithDefault from \"@ember/map/with-default\"`                     |\n+| `Ember.Mixin`                         | `import Mixin from \"@ember/object/mixin\"`                                  |\n+| `Ember.MutableArray`                  | `import MutableArray from \"@ember/array/mutable\"`                          |\n+| `Ember.NoneLocation`                  | `import NoneLocation from \"@ember/routing/none-location\"`                  |\n+| `Ember.Object`                        | `import EmberObject from \"@ember/object\"`                                  |\n+| `Ember.RSVP`                          | `import RSVP from \"rsvp\"`                                                  |\n+| `Ember.Resolver`                      | `import Resolver from \"@ember/application/resolver\"`                       |\n+| `Ember.Route`                         | `import Route from \"@ember/routing/route\"`                                 |\n+| `Ember.Router`                        | `import Router from \"@ember/routing/router\"`                               |\n+| `Ember.Service`                       | `import Service from \"@ember/service\"`                                     |\n+| `Ember.String.camelize`               | `import { camelize } from \"@ember/string\"`                                 |\n+| `Ember.String.capitalize`             | `import { capitalize } from \"@ember/string\"`                               |\n+| `Ember.String.classify`               | `import { classify } from \"@ember/string\"`                                 |\n+| `Ember.String.dasherize`              | `import { dasherize } from \"@ember/string\"`                                |\n+| `Ember.String.decamelize`             | `import { decamelize } from \"@ember/string\"`                               |\n+| `Ember.String.fmt`                    | `import { fmt } from \"@ember/string\"`                                      |\n+| `Ember.String.htmlSafe`               | `import { htmlSafe } from \"@ember/string\"`                                 |\n+| `Ember.String.loc`                    | `import { loc } from \"@ember/string\"`                                      |\n+| `Ember.String.underscore`             | `import { underscore } from \"@ember/string\"`                               |\n+| `Ember.String.w`                      | `import { w } from \"@ember/string\"`                                        |\n+| `Ember.TextArea`                      | `import TextArea from \"@ember/component/text-area\"`                        |\n+| `Ember.TextField`                     | `import TextField from \"@ember/component/text-field\"`                      |\n+| `Ember.addListener`                   | `import { addListener } from \"@ember/object/events\"`                       |\n+| `Ember.addObserver`                   | `import { addObserver } from \"@ember/object/observers\"`                    |\n+| `Ember.aliasMethod`                   | `import { aliasMethod } from \"@ember/object\"`                              |\n+| `Ember.assert`                        | `import { assert } from \"@ember/debug\"`                                    |\n+| `Ember.assign`                        | `import { assign } from \"@ember/polyfills\"`                                |\n+| `Ember.cacheFor`                      | `import { cacheFor } from \"@ember/object/internals\"`                       |","path":"text/0000-javascript-module-api.md","position":848,"original_position":848,"commit_id":"c021a91a562e21c75632802ac020ea0419d27588","original_commit_id":"c021a91a562e21c75632802ac020ea0419d27588","user":{"login":"kellyselden","id":602423,"avatar_url":"https://avatars.githubusercontent.com/u/602423?v=3","gravatar_id":"","url":"https://api.github.com/users/kellyselden","html_url":"https://github.com/kellyselden","followers_url":"https://api.github.com/users/kellyselden/followers","following_url":"https://api.github.com/users/kellyselden/following{/other_user}","gists_url":"https://api.github.com/users/kellyselden/gists{/gist_id}","starred_url":"https://api.github.com/users/kellyselden/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kellyselden/subscriptions","organizations_url":"https://api.github.com/users/kellyselden/orgs","repos_url":"https://api.github.com/users/kellyselden/repos","events_url":"https://api.github.com/users/kellyselden/events{/privacy}","received_events_url":"https://api.github.com/users/kellyselden/received_events","type":"User","site_admin":false},"body":"http://emberjs.com/api/classes/Ember.html#method_compare seems likely for this list. Can we include it?","created_at":"2016-12-20T05:57:23Z","updated_at":"2016-12-20T05:57:23Z","html_url":"https://github.com/emberjs/rfcs/pull/176#discussion_r93176038","pull_request_url":"https://api.github.com/repos/emberjs/rfcs/pulls/176","_links":{"self":{"href":"https://api.github.com/repos/emberjs/rfcs/pulls/comments/93176038"},"html":{"href":"https://github.com/emberjs/rfcs/pull/176#discussion_r93176038"},"pull_request":{"href":"https://api.github.com/repos/emberjs/rfcs/pulls/176"}}},"pull_request":{"url":"https://api.github.com/repos/emberjs/rfcs/pulls/176","id":92474150,"html_url":"https://github.com/emberjs/rfcs/pull/176","diff_url":"https://github.com/emberjs/rfcs/pull/176.diff","patch_url":"https://github.com/emberjs/rfcs/pull/176.patch","issue_url":"https://api.github.com/repos/emberjs/rfcs/issues/176","number":176,"state":"open","locked":false,"title":"RFC: JavaScript Modules API","user":{"login":"tomdale","id":90888,"avatar_url":"https://avatars.githubusercontent.com/u/90888?v=3","gravatar_id":"","url":"https://api.github.com/users/tomdale","html_url":"https://github.com/tomdale","followers_url":"https://api.github.com/users/tomdale/followers","following_url":"https://api.github.com/users/tomdale/following{/other_user}","gists_url":"https://api.github.com/users/tomdale/gists{/gist_id}","starred_url":"https://api.github.com/users/tomdale/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tomdale/subscriptions","organizations_url":"https://api.github.com/users/tomdale/orgs","repos_url":"https://api.github.com/users/tomdale/repos","events_url":"https://api.github.com/users/tomdale/events{/privacy}","received_events_url":"https://api.github.com/users/tomdale/received_events","type":"User","site_admin":false},"body":"### [Rendered RFC](https://github.com/tomdale/rfcs/blob/js-modules/text/0000-javascript-module-api.md)\r\n\r\n### Author Responses\r\n\r\n#### 12/13/2016\r\n\r\n* [Conditionally enabling prototype extensions](https://github.com/emberjs/rfcs/pull/176#discussion_r92295467)\r\n\r\n#### [11/16/2016](https://github.com/emberjs/rfcs/pull/176#issuecomment-261100221)\r\n\r\n* Distribution & Versioning\r\n* File Size\r\n* Scoped Packages\r\n* Templates\r\n* Computed Properties\r\n* Owner API\r\n* Testing\r\n* Formalization\r\n* Generators\r\n* Ember Data\r\n* Churn / Complexity\r\n\r\n### Changelog\r\n\r\n#### 12/13/2016\r\n\r\n- [Note that this RFC doesn't preclude future additions, at @rwjblue's request](https://github.com/emberjs/rfcs/pull/176/commits/ed84cb755962b21dbd97990bcea240cbc22f8014)\r\n- [Add more description on effectful/prototype extension modules](https://github.com/emberjs/rfcs/pull/176/commits/c021a91a562e21c75632802ac020ea0419d27588)\r\n\r\n#### 11/16/2016\r\n\r\n- [Add missing AutoLocation](https://github.com/emberjs/rfcs/pull/176/commits/13698de3344ed8498ec8349e58e9010cb1cdbb17)\r\n- [Move `getOwner` and `setOwner` to `@ember/application` from `@ember/object/internal`](https://github.com/emberjs/rfcs/pull/176/commits/dc4fc8706a16816391518a4cbb856f09a32bf6a5), per [@tchak's suggestion](https://github.com/emberjs/rfcs/pull/176#issuecomment-258678662)\r\n- [Add @zeppelin's previous module RFC, #68, to Prior Art section](https://github.com/emberjs/rfcs/pull/176/commits/c8283adfad47a308b10b42d1777b2d45aa9a7133)\r\n- [Note that we need to update generators to the How We Teach This section](https://github.com/emberjs/rfcs/pull/176/commits/cea5cc30b4d2d06d62db9f5ffe77889cc7b4fe2a), per [@HeroicEric's suggestion](https://github.com/emberjs/rfcs/pull/176#issuecomment-259201703)\r\n- [Add constraint around not deeply nesting modules](https://github.com/emberjs/rfcs/pull/176/commits/90cf471943c9a3d63de708ea9da1453a80bdd6d9), per [@nathanhammond's suggestion](https://github.com/emberjs/rfcs/pull/176#discussion_r87094024).\r\n- [Indicate intent to tackle migration strategy for addon authors in a separate RFC, now that we think we have a feasible approach](https://github.com/emberjs/rfcs/pull/176/commits/078c16ff8a23b64fd2d31722624765d636db9466), per [@nathanhammond's recommendation](https://github.com/emberjs/rfcs/pull/176#discussion_r87092134)\r\n- [Clarify that functions like `Ember.run` no longer act as namespaces](https://github.com/emberjs/rfcs/pull/176/commits/62d796da12347a7070a04cb4b932bd63aae14e7a), in response to [@nathanhammond's question](https://github.com/emberjs/rfcs/pull/176#discussion_r86680849)\r\n- [Remove discussion of multiple versions of Ember at the same](https://github.com/emberjs/rfcs/pull/176/commits/b2dd7d10b38d13e5612df3c0bdb922171af21c27) as it's outside of the scope of this RFC, based on [@nathanhammond's concerns](https://github.com/emberjs/rfcs/pull/176#discussion_r86680990)","created_at":"2016-11-06T01:55:03Z","updated_at":"2016-12-20T05:57:23Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5509e0d29cdf8a0edb5a5606ac9c40a89685f009","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/emberjs/rfcs/pulls/176/commits","review_comments_url":"https://api.github.com/repos/emberjs/rfcs/pulls/176/comments","review_comment_url":"https://api.github.com/repos/emberjs/rfcs/pulls/comments{/number}","comments_url":"https://api.github.com/repos/emberjs/rfcs/issues/176/comments","statuses_url":"https://api.github.com/repos/emberjs/rfcs/statuses/c021a91a562e21c75632802ac020ea0419d27588","head":{"label":"tomdale:js-modules","ref":"js-modules","sha":"c021a91a562e21c75632802ac020ea0419d27588","user":{"login":"tomdale","id":90888,"avatar_url":"https://avatars.githubusercontent.com/u/90888?v=3","gravatar_id":"","url":"https://api.github.com/users/tomdale","html_url":"https://github.com/tomdale","followers_url":"https://api.github.com/users/tomdale/followers","following_url":"https://api.github.com/users/tomdale/following{/other_user}","gists_url":"https://api.github.com/users/tomdale/gists{/gist_id}","starred_url":"https://api.github.com/users/tomdale/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tomdale/subscriptions","organizations_url":"https://api.github.com/users/tomdale/orgs","repos_url":"https://api.github.com/users/tomdale/repos","events_url":"https://api.github.com/users/tomdale/events{/privacy}","received_events_url":"https://api.github.com/users/tomdale/received_events","type":"User","site_admin":false},"repo":{"id":25714304,"name":"rfcs","full_name":"tomdale/rfcs","owner":{"login":"tomdale","id":90888,"avatar_url":"https://avatars.githubusercontent.com/u/90888?v=3","gravatar_id":"","url":"https://api.github.com/users/tomdale","html_url":"https://github.com/tomdale","followers_url":"https://api.github.com/users/tomdale/followers","following_url":"https://api.github.com/users/tomdale/following{/other_user}","gists_url":"https://api.github.com/users/tomdale/gists{/gist_id}","starred_url":"https://api.github.com/users/tomdale/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tomdale/subscriptions","organizations_url":"https://api.github.com/users/tomdale/orgs","repos_url":"https://api.github.com/users/tomdale/repos","events_url":"https://api.github.com/users/tomdale/events{/privacy}","received_events_url":"https://api.github.com/users/tomdale/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/tomdale/rfcs","description":"RFCs for changes to Ember","fork":true,"url":"https://api.github.com/repos/tomdale/rfcs","forks_url":"https://api.github.com/repos/tomdale/rfcs/forks","keys_url":"https://api.github.com/repos/tomdale/rfcs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tomdale/rfcs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tomdale/rfcs/teams","hooks_url":"https://api.github.com/repos/tomdale/rfcs/hooks","issue_events_url":"https://api.github.com/repos/tomdale/rfcs/issues/events{/number}","events_url":"https://api.github.com/repos/tomdale/rfcs/events","assignees_url":"https://api.github.com/repos/tomdale/rfcs/assignees{/user}","branches_url":"https://api.github.com/repos/tomdale/rfcs/branches{/branch}","tags_url":"https://api.github.com/repos/tomdale/rfcs/tags","blobs_url":"https://api.github.com/repos/tomdale/rfcs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tomdale/rfcs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tomdale/rfcs/git/refs{/sha}","trees_url":"https://api.github.com/repos/tomdale/rfcs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tomdale/rfcs/statuses/{sha}","languages_url":"https://api.github.com/repos/tomdale/rfcs/languages","stargazers_url":"https://api.github.com/repos/tomdale/rfcs/stargazers","contributors_url":"https://api.github.com/repos/tomdale/rfcs/contributors","subscribers_url":"https://api.github.com/repos/tomdale/rfcs/subscribers","subscription_url":"https://api.github.com/repos/tomdale/rfcs/subscription","commits_url":"https://api.github.com/repos/tomdale/rfcs/commits{/sha}","git_commits_url":"https://api.github.com/repos/tomdale/rfcs/git/commits{/sha}","comments_url":"https://api.github.com/repos/tomdale/rfcs/comments{/number}","issue_comment_url":"https://api.github.com/repos/tomdale/rfcs/issues/comments{/number}","contents_url":"https://api.github.com/repos/tomdale/rfcs/contents/{+path}","compare_url":"https://api.github.com/repos/tomdale/rfcs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tomdale/rfcs/merges","archive_url":"https://api.github.com/repos/tomdale/rfcs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tomdale/rfcs/downloads","issues_url":"https://api.github.com/repos/tomdale/rfcs/issues{/number}","pulls_url":"https://api.github.com/repos/tomdale/rfcs/pulls{/number}","milestones_url":"https://api.github.com/repos/tomdale/rfcs/milestones{/number}","notifications_url":"https://api.github.com/repos/tomdale/rfcs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tomdale/rfcs/labels{/name}","releases_url":"https://api.github.com/repos/tomdale/rfcs/releases{/id}","deployments_url":"https://api.github.com/repos/tomdale/rfcs/deployments","created_at":"2014-10-25T00:27:31Z","updated_at":"2016-11-25T23:07:18Z","pushed_at":"2016-12-13T23:17:52Z","git_url":"git://github.com/tomdale/rfcs.git","ssh_url":"git@github.com:tomdale/rfcs.git","clone_url":"https://github.com/tomdale/rfcs.git","svn_url":"https://github.com/tomdale/rfcs","homepage":null,"size":252,"stargazers_count":27,"watchers_count":27,"language":null,"has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":8,"mirror_url":null,"open_issues_count":0,"forks":8,"open_issues":0,"watchers":27,"default_branch":"master"}},"base":{"label":"emberjs:master","ref":"master","sha":"c1f3a6587ff8979f75c0fc48b5a9d4fa035fe791","user":{"login":"emberjs","id":1253363,"avatar_url":"https://avatars.githubusercontent.com/u/1253363?v=3","gravatar_id":"","url":"https://api.github.com/users/emberjs","html_url":"https://github.com/emberjs","followers_url":"https://api.github.com/users/emberjs/followers","following_url":"https://api.github.com/users/emberjs/following{/other_user}","gists_url":"https://api.github.com/users/emberjs/gists{/gist_id}","starred_url":"https://api.github.com/users/emberjs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emberjs/subscriptions","organizations_url":"https://api.github.com/users/emberjs/orgs","repos_url":"https://api.github.com/users/emberjs/repos","events_url":"https://api.github.com/users/emberjs/events{/privacy}","received_events_url":"https://api.github.com/users/emberjs/received_events","type":"Organization","site_admin":false},"repo":{"id":22664562,"name":"rfcs","full_name":"emberjs/rfcs","owner":{"login":"emberjs","id":1253363,"avatar_url":"https://avatars.githubusercontent.com/u/1253363?v=3","gravatar_id":"","url":"https://api.github.com/users/emberjs","html_url":"https://github.com/emberjs","followers_url":"https://api.github.com/users/emberjs/followers","following_url":"https://api.github.com/users/emberjs/following{/other_user}","gists_url":"https://api.github.com/users/emberjs/gists{/gist_id}","starred_url":"https://api.github.com/users/emberjs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emberjs/subscriptions","organizations_url":"https://api.github.com/users/emberjs/orgs","repos_url":"https://api.github.com/users/emberjs/repos","events_url":"https://api.github.com/users/emberjs/events{/privacy}","received_events_url":"https://api.github.com/users/emberjs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/emberjs/rfcs","description":"RFCs for changes to Ember","fork":false,"url":"https://api.github.com/repos/emberjs/rfcs","forks_url":"https://api.github.com/repos/emberjs/rfcs/forks","keys_url":"https://api.github.com/repos/emberjs/rfcs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/emberjs/rfcs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/emberjs/rfcs/teams","hooks_url":"https://api.github.com/repos/emberjs/rfcs/hooks","issue_events_url":"https://api.github.com/repos/emberjs/rfcs/issues/events{/number}","events_url":"https://api.github.com/repos/emberjs/rfcs/events","assignees_url":"https://api.github.com/repos/emberjs/rfcs/assignees{/user}","branches_url":"https://api.github.com/repos/emberjs/rfcs/branches{/branch}","tags_url":"https://api.github.com/repos/emberjs/rfcs/tags","blobs_url":"https://api.github.com/repos/emberjs/rfcs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/emberjs/rfcs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/emberjs/rfcs/git/refs{/sha}","trees_url":"https://api.github.com/repos/emberjs/rfcs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/emberjs/rfcs/statuses/{sha}","languages_url":"https://api.github.com/repos/emberjs/rfcs/languages","stargazers_url":"https://api.github.com/repos/emberjs/rfcs/stargazers","contributors_url":"https://api.github.com/repos/emberjs/rfcs/contributors","subscribers_url":"https://api.github.com/repos/emberjs/rfcs/subscribers","subscription_url":"https://api.github.com/repos/emberjs/rfcs/subscription","commits_url":"https://api.github.com/repos/emberjs/rfcs/commits{/sha}","git_commits_url":"https://api.github.com/repos/emberjs/rfcs/git/commits{/sha}","comments_url":"https://api.github.com/repos/emberjs/rfcs/comments{/number}","issue_comment_url":"https://api.github.com/repos/emberjs/rfcs/issues/comments{/number}","contents_url":"https://api.github.com/repos/emberjs/rfcs/contents/{+path}","compare_url":"https://api.github.com/repos/emberjs/rfcs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/emberjs/rfcs/merges","archive_url":"https://api.github.com/repos/emberjs/rfcs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/emberjs/rfcs/downloads","issues_url":"https://api.github.com/repos/emberjs/rfcs/issues{/number}","pulls_url":"https://api.github.com/repos/emberjs/rfcs/pulls{/number}","milestones_url":"https://api.github.com/repos/emberjs/rfcs/milestones{/number}","notifications_url":"https://api.github.com/repos/emberjs/rfcs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/emberjs/rfcs/labels{/name}","releases_url":"https://api.github.com/repos/emberjs/rfcs/releases{/id}","deployments_url":"https://api.github.com/repos/emberjs/rfcs/deployments","created_at":"2014-08-06T00:49:22Z","updated_at":"2016-12-20T05:32:23Z","pushed_at":"2016-12-20T05:00:49Z","git_url":"git://github.com/emberjs/rfcs.git","ssh_url":"git@github.com:emberjs/rfcs.git","clone_url":"https://github.com/emberjs/rfcs.git","svn_url":"https://github.com/emberjs/rfcs","homepage":null,"size":216,"stargazers_count":465,"watchers_count":465,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":149,"mirror_url":null,"open_issues_count":79,"forks":149,"open_issues":79,"watchers":465,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/emberjs/rfcs/pulls/176"},"html":{"href":"https://github.com/emberjs/rfcs/pull/176"},"issue":{"href":"https://api.github.com/repos/emberjs/rfcs/issues/176"},"comments":{"href":"https://api.github.com/repos/emberjs/rfcs/issues/176/comments"},"review_comments":{"href":"https://api.github.com/repos/emberjs/rfcs/pulls/176/comments"},"review_comment":{"href":"https://api.github.com/repos/emberjs/rfcs/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/emberjs/rfcs/pulls/176/commits"},"statuses":{"href":"https://api.github.com/repos/emberjs/rfcs/statuses/c021a91a562e21c75632802ac020ea0419d27588"}}}}
{"actor":{"display_login":"kellyselden"}}