{"action":"created","issue":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3469","labels_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3469/labels{/name}","comments_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3469/comments","events_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3469/events","html_url":"https://github.com/Microsoft/TypeScript/issues/3469","id":87031841,"number":3469,"title":"Support \"medium-sized\" projects","user":{"login":"jonathandturner","id":547158,"avatar_url":"https://avatars.githubusercontent.com/u/547158?v=3","gravatar_id":"","url":"https://api.github.com/users/jonathandturner","html_url":"https://github.com/jonathandturner","followers_url":"https://api.github.com/users/jonathandturner/followers","following_url":"https://api.github.com/users/jonathandturner/following{/other_user}","gists_url":"https://api.github.com/users/jonathandturner/gists{/gist_id}","starred_url":"https://api.github.com/users/jonathandturner/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonathandturner/subscriptions","organizations_url":"https://api.github.com/users/jonathandturner/orgs","repos_url":"https://api.github.com/users/jonathandturner/repos","events_url":"https://api.github.com/users/jonathandturner/events{/privacy}","received_events_url":"https://api.github.com/users/jonathandturner/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/Microsoft/TypeScript/labels/In%20Discussion","name":"In Discussion","color":"556b75"},{"url":"https://api.github.com/repos/Microsoft/TypeScript/labels/Suggestion","name":"Suggestion","color":"006b75"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":6,"created_at":"2015-06-10T16:41:57Z","updated_at":"2015-06-11T20:26:13Z","closed_at":null,"body":"Listening to @nycdotnet has me fired up to tackle this one.  Thanks, Steve.  (btw, you can check out his good interview here: http://www.dotnetrocks.com/default.aspx?showNum=1149)\r\n\r\nThe proposal here was first started in times prehistoric (even before #11), when dinosaurs walked the scorched earth.  While nothing in this proposal is novel, per se, I believe it's high time we tackled the issue.  Steve's own proposal is #3394. \r\n\r\n# The Problem\r\n\r\nCurrently, in TypeScript, it's rather easy to start and get going, and we're making it easier with each day (with the help of things like #2338 and the work on System.js).  This is wonderful.  But there is a bit of a hurdle as project size grows.  We currently have a mental model that goes something like this:\r\n\r\n* Small-sized projects: use tsconfig.json, keep most of your source in the current directory\r\n* Large-sized projects: use custom builds, put source where you need it\r\n\r\nFor small-sized projects, tsconfig.json gives you an easy-to-setup way of getting going with any of the editors in a cross platform way.  For large-scale projects, you will likely end up switching to build systems because of the varied requirements of large-scale projects, and the end result will be something that works for your scenarios but is difficult to tool because it's far too difficult to tool the variety of build systems and options.\r\n\r\nSteve, in his interview, points out that this isn't quite the right model of the world, and I tend to agree with him.  Instead, there are three sizes of project:\r\n\r\n* Small-sized projects: use tsconfig.json, keep most of your source in the current directory\r\n* Medium-sized projects: those with standard builds and shared components\r\n* Large-sized projects: use custom builds, put source where you need it\r\n\r\nAs you scale in size of project, Steve argues, you need to be able to scale through the medium step, or tool support falls off too quickly.\r\n\r\n# Proposal\r\n\r\nTo solve this, I propose we support \"medium-sized\" projects.  These projects have standard build steps that could be described in tsconfig.json today, with the exception that the project is built from multiple components.  The hypothesis here is that there are quite a number of projects at this level that could be well-served by this support.\r\n\r\n## Goals \r\n\r\nProvide an easy-to-use experience for developers creating \"medium-sized\" projects for both command-line compilation and when working with these projects in an IDE.\r\n\r\n## Non-goals \r\n\r\nThis proposal does *not* include optional compilation, or any steps outside of what the compiler handles today.  This proposal also does not cover bundling or packaging, which will be handled in a separate proposal.  In short, as mentioned in the name, this proposal covers only the 'medium-sized' projects and not the needs of those at large scales.  \r\n\r\n## Design\r\n\r\nTo support medium-sized projects, we focus on the use case of one tsconfig.json referencing another.\r\n\r\nExample [tsconfig.json](https://github.com/Microsoft/TypeScript/wiki/tsconfig.json) of today:\r\n```JavaScript\r\n{\r\n    \"compilerOptions\": {\r\n        \"module\": \"commonjs\",\r\n        \"noImplicitAny\": true,\r\n        \"sourceMap\": true\r\n    },\r\n    \"files\": [\r\n        \"core.ts\",\r\n        \"sys.ts\"\r\n    ]\r\n}\r\n```\r\n\r\nProposed tsconfig.json 'dependencies' section:\r\n\r\n```JavaScript\r\n{\r\n    \"compilerOptions\": {\r\n        \"module\": \"commonjs\",\r\n        \"noImplicitAny\": true,\r\n        \"sourceMap\": true\r\n    },\r\n    \"dependencies\": [\r\n        \"../common\", \r\n        \"../util\"\r\n    ],\r\n    \"files\": [\r\n        \"core.ts\",\r\n        \"sys.ts\"\r\n    ]\r\n}\r\n```\r\n\r\nDependencies point to either:\r\n* A directory, where a tsconfig.json can be found\r\n* A tsconfig.json directly\r\n\r\nDependencies are hierarchical.  To edit the full project, you need to open the correct directory that contains the root tsconfig.json.  This implies that dependencies can't be cyclic.  While it may be possible to handle cyclic dependencies in some cases, other cases, namely those with types that have circular dependencies, it may not be possible to do a full resolution.  \r\n\r\n# How it works\r\n\r\nDependencies are built first, in the order they are listed in the 'dependencies' section.  If a dependency fails to build, the compiler will exit with an error and not continue to build the rest of the project.\r\n\r\nAs each dependency completes, a '.d.ts' file representing the outputs is made available to the current build.  Once all dependencies complete, the current project is built.\r\n\r\nIf the user specifies a subdirectory as a dependency, and also implies its compilation by not providing a 'files' section, the dependency is compiled during dependency compilation and is also removed from the compilation of the current project.\r\n\r\nThe language service can see into each dependency.  Because each dependency will be driven off its own tsconfig.json, this may mean that multiple language service instances would need to be created.  The end result would be a coordinated language service that was capable of refactoring, code navigation, find all references, etc across dependencies.\r\n\r\n# Limitations\r\n\r\nAdding a directory as a dependency that has no tsconfig.json is considered an error.\r\n\r\nOutputs of dependencies are assumed to be self-contained and separate from the current project.  This implies that you can't concatenate the output .js of a dependency with the current project via tsconfig.json.  External tools, of course, can provide this functionality.\r\n\r\nAs mentioned earlier, circular dependencies are considered an error.  In the simple case:\r\n\r\nA - B\r\n   \\ C\r\n\r\nA is the 'current project' and depends on two dependencies: B and C.  If B and C do not themselves have dependencies, this case is trivial.  If C depends on B, B is made available to C.  This is not considered to be circular.  If, however, B depends on A, this is considered circular and would be an error.  \r\n\r\nIf, in the example, B depends on C and C is self-contained, this would not be considered a cycle.  In this case, the compilation order would be C, B, A, which follows the logic we have for ///ref.\r\n\r\n# Optional optimizations/improvements\r\n\r\nIf a dependency does not to be rebuilt, then its build step is skipped and the '.d.ts' representation from the previous build is reused.  This could be extended to handle if the compilation of a dependencies has built dependencies that will show up later in the 'dependencies' list of the current project (as happened in the example given in the Limitations section).\r\n\r\nRather than treating directories passed as dependencies that do not have a tsconfig.json as error cases, we could optionally apply default 'files' and the settings of the current project to that dependency."},"comment":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/comments/111267709","html_url":"https://github.com/Microsoft/TypeScript/issues/3469#issuecomment-111267709","issue_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3469","id":111267709,"user":{"login":"nycdotnet","id":3755379,"avatar_url":"https://avatars.githubusercontent.com/u/3755379?v=3","gravatar_id":"","url":"https://api.github.com/users/nycdotnet","html_url":"https://github.com/nycdotnet","followers_url":"https://api.github.com/users/nycdotnet/followers","following_url":"https://api.github.com/users/nycdotnet/following{/other_user}","gists_url":"https://api.github.com/users/nycdotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/nycdotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nycdotnet/subscriptions","organizations_url":"https://api.github.com/users/nycdotnet/orgs","repos_url":"https://api.github.com/users/nycdotnet/repos","events_url":"https://api.github.com/users/nycdotnet/events{/privacy}","received_events_url":"https://api.github.com/users/nycdotnet/received_events","type":"User","site_admin":false},"created_at":"2015-06-11T20:26:13Z","updated_at":"2015-06-11T20:26:13Z","body":"Thanks for your reply, Mohamed.  Let me restate to see if I understand:\r\n\r\n  * You think that the task of coordinating multi-project builds should remain the domain of dedicated build tools.\r\n  * You think that there may be something to this suggestion for the TypeScript language service.\r\n  * You think that running `tsc --project` on this `tsconfig.json` would be the same as running `tsc file1.ts ../project/out/project.d.ts`.  However, opening such a project in VS or another editor with the TypeScript language service would allow \"go to definition\" to bring the developer to the *actual TypeScript file* where the feature was defined (rather to the definition in `projectB.d.ts`)\r\n\r\nDo I have that right?\r\n\r\nIf so, I think this is very fair.  In my original proposal (https://github.com/Microsoft/TypeScript/issues/3394), I did say that my idea was incomplete because it didn't include the step of copying the emitted results from where they'd be output in the referenced library to where the referencing library would expect them at runtime.  I think you're saying \"why go halfway down a road for building when what is really needed is the language service support\".\r\n\r\nTo change the data a bit in your example, would you be willing to support something like this?\r\n\r\n```json\r\n\"files\" : [\r\n    \"file1.ts\",\r\n    {\r\n        \"path\": \"externalLibraries/projectB.d.ts\",\r\n         \"sourceProject\": \"../projectB/\"\r\n     }\r\n]\r\n```\r\n\r\nThe assumption is that the current project would ship with a definition for projectB that would be used by default, but if the actual source for projectB is available, the actual source would be used instead.\r\n\r\n"}}