{"id":16906524,"url":"https://github.com/rsms/tspkg","last_synced_at":"2025-03-22T10:31:14.270Z","repository":{"id":57381812,"uuid":"79830013","full_name":"rsms/tspkg","owner":"rsms","description":"Create small, fast and easily-distributable packages from TypeScript projects","archived":false,"fork":false,"pushed_at":"2017-12-26T19:49:53.000Z","size":243,"stargazers_count":34,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-15T21:17:06.572Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rsms.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-01-23T17:39:24.000Z","updated_at":"2023-08-09T16:28:42.000Z","dependencies_parsed_at":"2022-09-13T11:20:24.411Z","dependency_job_id":null,"html_url":"https://github.com/rsms/tspkg","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsms%2Ftspkg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsms%2Ftspkg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsms%2Ftspkg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsms%2Ftspkg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rsms","download_url":"https://codeload.github.com/rsms/tspkg/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244943732,"owners_count":20536290,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-13T18:43:00.786Z","updated_at":"2025-03-22T10:31:13.936Z","avatar_url":"https://github.com/rsms.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tspkg\n\nCreates small, fast and easily-distributable packages from TypeScript projects.\n\n- Produces a single JavaScript file along with a source map and optional TypeScript declaration file\n- Conventions over configuration — \"just works\" with existing TypeScript projects\n- [Advanced dead-code elimination and constant folding](#constant-substitution-cf-and-dce)\n- Import/export elimination\n- Eliding or elimination of package-internal modules\n- Product JS file can be loaded in any JS environment:\n  - CommonJS (Nodejs et al) through `exports` and with `require`\n  - AMD through `define`\n  - Any other environment through `this[\u003cpkg-name\u003e] = \u003cpkg-object\u003e`\n- Incremental compilation (similar to `tsc --watch`)\n- [Circular dependency detection](#acyclic-dependency-graph)\n\n[Have a look at the output from tspkg -O](https://gist.github.com/rsms/ffc0f7b8ef9eb814fe1bceab6127c24b) run on the [example project](example-project)\n\n## Constant substitution, CF and DCE\n\ninput.ts:\n\n```ts\nconst DEBUG = false\nconst assert = DEBUG ? equal : require('assert')\nfunction a(x :any) {\n  assert(x \u003e 0,1)\n  return 1 / x\n}\n```\n\noutput.js from `tspkg -O`: (simplified for readability)\n\n```js\nfunction a(x) {\n  return 1 / x;\n}\n```\n\noutput.js from `tspkg -g`: (simplified for readability)\n\n```js\nconst assert = require('assert')\nfunction a(x) {\n  assert(x \u003e 0,1)\n  return 1 / x;\n}\n```\n\nYou can provide replacement expressions for module-level constants. Say we have this:\n\n```js\nconst VERSION = 0\n```\n\nRunning `tspkg -DVERSION=5`, the output will look like this:\n\n```js\nconst VERSION = 5\n```\n\nThis can be used to control what code is included when the -O flag is provided:\n\n```js\nimport {parser as parser_4} from './parser-v4'\nimport {parser as parser_compat} from './parser'\nconst VERSION = 0\nconst parser = VERSION \u003e 3 ? parser_4 : parser_compat\n```\n\nRunning `tspkg -O -DVERSION=5`, the output will look like this:\n\n```js\nimport {parser as parser_4} from './parser-v4'\nconst VERSION = 5\nconst parser = parser_4\n```\n\nIf we instead run `tspkg -O -DVERSION=2`, the output will look like this:\n\n```js\nimport {parser as parser_compat} from './parser'\nconst VERSION = 2\nconst parser = parser_compat\n```\n\nNote: In reality, dead-code elimination will remove the `VERSION` const above, along with `const parser` unless we export it or use it in something that's exported.\n\nThe expression provided as the value for `-D` can be any JavaScript:\n\n```js\nexport const FOO = null\n```\n\nWe run `tspkg '-DFOO=function(){ return [1, 2, 3] }'` which produces results equivalent to:\n\n```js\nexport const FOO = function() {\n  return [1, 2, 3]\n}\n```\n\n## Acyclic dependency graph\n\ntspkg enforces [dependency graphs](https://en.wikipedia.org/wiki/Dependency_graph) to be [acyclic](https://en.wikipedia.org/wiki/Directed_acyclic_graph).\n[Circular dependencies](https://en.wikipedia.org/wiki/Circular_dependency#Problems_of_circular_dependencies) leads to error-prone and indeterministic programs, and makes code reuse harder.\n\nSay we have the following dependency graph for an imaginary project that receives\nsome messages over the network and autmatically replies to them, sometimes via email (SMTP):\n\n\u003cimg src=\"https://cdn.rawgit.com/rsms/tspkg/master/misc/example1-acyclic.svg\" width=\"256\"\u003e\n\nNow, say we're working on `fmtmsg` and we realize that by using functionality in `msg/parse` we can save ourselves some code-writing. Perhaps `msg/parse` provides a helpful function for folding HTML into plain text. Not knowing that `msg/parse` depends on `msg/classify` which in turn depends on `fmtmsg`, we import `msg/parse` and suddenly Weird Things™ starts happening, like sometimes when we run our program the module-constant \"foo\" is \"1\", but sometimes it's \"2\".\n\n\u003cimg src=\"https://cdn.rawgit.com/rsms/tspkg/master/misc/example1-cyclic.svg\" width=\"256\"\u003e\n\ntspkg will detect these situations and stop you from building Weird Packages™. Trying to build a package with the above configuration would make tspkg stop with an error:\n\n```txt\nerror TSPKG1: Circular dependency: msg/parse -\u003e msg/classify -\u003e fmtmsg -\u003e msg/parse\n```\n\nWe can fix this by moving the helpful function found in `msg/parse` to a separate module/file:\n\n\u003cimg src=\"https://cdn.rawgit.com/rsms/tspkg/master/misc/example1-acyclic2.svg\" width=\"256\"\u003e\n\n\n## CLI synopsis\n\n```txt\nUsage: ./tspkg [options] [\u003csrcpath\u003e]\noptions:\n  -h[elp]               Show description and detailed help for this program.\n  -o[output]=\u003coutfile\u003e  Filename prefix for output(s). E.g. 'a/b' =\u003e 'a/b.js'.\n                        If not provided, \"\u003csrcpath\u003e/\u003cpkgname\u003e\" is used when\n                        \u003csrcpath\u003e is a directory. Otherwise the file extension\n                        of \u003csrcpath\u003e is replaced with \".o\".\n  -p[kg]=\u003cpkgname\u003e      Name to be used for package when exported globally\n                        (i.e. when there's no package management.) If not\n                        provided, \u003cpkgname\u003e is inferred from \u003csrcpath\u003e.\n  -O                    Produce optimized output. See -help for details.\n  -g                    Produce debuggable output. See -help for details.\n  -i[ncr], -w[atch]     Incremental compilation (watches source for changes).\n  -compress=\u003cbool\u003e      Explicitly enable or disable compression of generated\n                        code. Defaults to \"true\" if -O is provided, otherwise\n                        defaults to \"false\".\n  -ts-disable           Do not attempt to interpret the package as a\n                        TypeScript project.\n  -ts-options=\u003cjson\u003e    Apply \u003cjson\u003e to TypeScript \"compilerOptions\" object on\n                        top of options from tsconfig file.\n  -map-root=\u003cdir\u003e       Source map \"sourceRoot\" value. Inferred from \u003csrcpath\u003e\n                        and \u003coutfile\u003e by default.\n  -no-maps              Do not read nor write any source maps.\n  -no-incr-cache        Disable caching for incremental builds.\n  -v[erbose]            Print details to stdout.\n  -debug                Print lots of details to stdout. Implies -v.\n  -dry                  Just print the configuration and exit.\n\n\n\u003csrcpath\u003e\n  Either a single javascript file or the path to a directory containing\n  package source. If omitted, the current working directory is used.\n\n\u003coutfile\u003e\n  A filename prefix that is joined by type suffix for each output file\n  produced. For a TypeScript project with declaration files, -o=a/b would\n  create the following files:\n    a/b.js       Code\n    a/b.js.map   Source map\n    a/b.d.ts     Type declarations\n\n-g\n  When provided:\n  • Compression is disabled by default (pass -compress=true to explicitly\n    enable).\n  • All instances of `const DEBUG = \u003cconstlit\u003e` are changed to replace\n    `\u003cconstlit\u003e` with `true`. This can be used to gate debugging code.\n\n-O\n  When provided:\n  • Enables optimizations (dead-code elimination, constant folding, etc.)\n  • Enables compression (pass -compress=false to explicitly disable.)\n  • Unless -g is provided, all instances of `const DEBUG = \u003cconstlit\u003e` are\n    changed to replace `\u003cconstlit\u003e` with `false`. This can be used to have\n    debugging code stripped from the generated code, since constant folding\n    together with dead-code elimination should remove code gated on \"DEBUG\".\n\n  When neither -g or -O is provided, the goal of tspkg is to generate output\n  as quickly as possible.\n\n  Example of DEBUG elimination; in.js:\n\n    const DEBUG = 0\n    const assert = DEBUG ? require('assert') : function(){}\n    export function bob(x) {\n      assert(x \u003e 0)\n      return 4 / x\n    }\n\n  tspkg -g in.js  # =\u003e out.js:\n\n    const DEBUG = 1\n    const assert = DEBUG ? require('assert') : function(){}\n    exports.bob = function bob(x) {\n      return 4 / x\n    }\n\n  tspkg -O in.js  # =\u003e out.js:\n\n    exports.bob=function(x){return 4/x};\n\n  Note: Not providing -g or -O would yield code that's functionally identical\n  to the in.js example above.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frsms%2Ftspkg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frsms%2Ftspkg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frsms%2Ftspkg/lists"}