{"id":18792144,"url":"https://github.com/khatastroffik/one-ts-for-all","last_synced_at":"2025-04-13T14:31:04.901Z","repository":{"id":40765520,"uuid":"270575494","full_name":"khatastroffik/one-ts-for-all","owner":"khatastroffik","description":"A PoC demonstrating a \"single source\" Typescript library project generating automatically multiple script artifacts out of the library (CJS, ESM, TS) and a sample CLI: ONE-FOR-ALL !","archived":false,"fork":false,"pushed_at":"2023-01-06T08:17:12.000Z","size":1506,"stargazers_count":2,"open_issues_count":12,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-10-27T01:08:26.929Z","etag":null,"topics":["application","bin","blueprint","cjs","cli","commonjs","commonjs-modules","ecmascript","esm","esm-libraries","jest","module","multiple-targets","nodejs","one4all","poc","ts","tsc","type-declarations","typescript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/khatastroffik.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-06-08T07:38:23.000Z","updated_at":"2023-06-12T10:34:19.000Z","dependencies_parsed_at":"2023-02-05T16:46:31.533Z","dependency_job_id":null,"html_url":"https://github.com/khatastroffik/one-ts-for-all","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/khatastroffik%2Fone-ts-for-all","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/khatastroffik%2Fone-ts-for-all/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/khatastroffik%2Fone-ts-for-all/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/khatastroffik%2Fone-ts-for-all/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/khatastroffik","download_url":"https://codeload.github.com/khatastroffik/one-ts-for-all/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223589343,"owners_count":17169956,"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":["application","bin","blueprint","cjs","cli","commonjs","commonjs-modules","ecmascript","esm","esm-libraries","jest","module","multiple-targets","nodejs","one4all","poc","ts","tsc","type-declarations","typescript"],"created_at":"2024-11-07T21:18:37.213Z","updated_at":"2024-11-07T21:18:37.778Z","avatar_url":"https://github.com/khatastroffik.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# One Typescript for all\n\nThis is a PoC demonstrating a \"*single source*\" Typescript library project generating automatically multiple versions of the script (CJS, ESM, TS) and a sample CLI: **ONE-FOR-ALL**\n\n\u003ch2\u003eTable-of-Content\u003c/h2\u003e\n\n\u003c!-- @import \"[TOC]\" {cmd=\"toc\" depthFrom=2 depthTo=6 orderedList=false} --\u003e\n\n\u003c!-- code_chunk_output --\u003e\n\n- [Overview](#overview)\n- [Objectives](#objectives)\n  - [SINGLE TYPESCRIPT INPUT \u0026rightarrow; MULTIPLE OUTPUT](#single-typescript-input-rightarrow-multiple-output)\n  - [RUN ESM LIBRARIES IN THE BROWSER](#run-esm-libraries-in-the-browser)\n- [Requirements](#requirements)\n- [Project Development versus Package Publication](#project-development-versus-package-publication)\n- [How to implement \"one-for-all\"?](#how-to-implement-one-for-all)\n  - [Sources](#sources)\n  - [Typescript compiler (TSC) configuration](#typescript-compiler-tsc-configuration)\n  - [*.gitignore* file](#gitignore-file)\n  - [npm scripts](#npm-scripts)\n  - [The `package.json` targets](#the-packagejson-targets)\n  - [Important !](#important)\n- [Project documentation](#project-documentation)\n\n\u003c!-- /code_chunk_output --\u003e\n\n## Overview\n\n![one-typescript-for-all Architecture](doc/one-ts-for-all.png)\n\n## Objectives\n\n### SINGLE TYPESCRIPT INPUT \u0026rightarrow; MULTIPLE OUTPUT\n\nThis is the main objective: **ONE-FOR-ALL**!\n\n- \u003cu\u003e**Implement**\u003c/u\u003e a library using **Typescript exclusively**.\n- \u003cu\u003e**Use**\u003c/u\u003e the library with any client which is able to use/run **CommonJS, ECMAScript or Typescript modules**.\n\n### RUN ESM LIBRARIES IN THE BROWSER\n\nA *browser app/client* may use the *ESM library* directly. In this case, a **modern browser** is required.\n**This use case is demonstrated in this PoC**.\n\nOlder browser would require to adapt the scripts before integration, using a supplemental \"transpiler\" to output compatible scripts - hence requiring a further implementation step. Such **older browsers aren't in the focus of this project**.\n\n## Requirements\n\n**Node.js** and **NPM** (or **yarn**) should be \"globally\" installed on your system to ease the installation of the packages and/or source files.\nPreferably:\n\n- node: \u003e=13.x\n- npm: \u003e=6.x\n\n**Typescript** may be globally present as well, thus is not required, since the PoC will use its own (local) version:\n\n- tsc: \u003e=3.9.5 (earlier version like 3.8.x should be ok - not tested, though)\n\n## Project Development versus Package Publication\n\nThe PoC is configured (`package.json` and `.gitignore`) to separate development and usage of the lib/app: \"GitHub\" versus \"NPM\".\n\n1. The bare **sources** (typescript only)  of the library and application are stored in the \u003cu\u003e**Github Repository**\u003c/u\u003e.\n  use this if you'd like to **develop**, adapt etc. the library/application\n\n1. The **transpiled** i.e. usable library artifact (ESM, CommonJS, Typescript and `*.d.ts` types declaration files ) is stored in the \u003cu\u003e**NPM repository**\u003c/u\u003e - though without the source files.  \n  use this if you'd like to **use** the library/application in your project.\n\nThis separation is intended:\n\n- to \u003cu\u003ereduce the size\u003c/u\u003e of the published package to the min possible and\n- to \u003cu\u003e**clearly separate the different concerns**\u003c/u\u003e.\n\n**Note**: the artifacts i.e the files could be minified and thus reduce the size of the package furthermore. This is not implemented here, though.\n\n## How to implement \"one-for-all\"?\n\nThis section summarize the techniques i.e. engineering procedures used to realize the \"one-for-all\" objective.\n\n### Sources\n\nThe sources files are all contained in the `src` folder. No exception.\n\n### Typescript compiler (TSC) configuration\n\nThe output (multiple modules i.e. CJS, ESM...) of **TSC** is driven by the different `tsconfig.*.json`files and by the `package.json` file:\n\n1. There's *intentionally NO default* `tsconfig.json` file in this project! Instead, builds are created on purpose i.e specifically through targeting a **specific tsconfig**.\n1. The `tsconfig.common.json` is declaring the configuration shared by all targets. Hence, it correspond to a traditional tsconfig.json, though rename on purpose (see above).\n1. The `tsconfig.bin.json` is targeting the generation/output of the **CLI application** in the `bin` folder.\n1. The `tsconfig.esm.json` is targeting the generation/output of the **ESM scripts** version in the `lib/esm/` folder.\n1. The `tsconfig.cjs.json` is targeting the generation/output of the **ESM scripts** version in the `lib/esm/` folder.\n1. The `tsconfig.types.json` is generating the types declaration `*.d.ts` files for the **Typescript scripts** version in the `lib/ts/` folder. This is required to provide those files in the npm package.\n\n### *.gitignore* file\n\nSince the source code repository should NOT contain the \"*output*\" of the compilation/distribution, the `.gitignore` file excludes the corresponding folders: `/lib` and `/bin`.\n\n### npm scripts\n\nIn order to generate the output i.e to produce the different artifacts (ESJ, ESM, CLI and TS) to be **published in a NPM repository** easily, the `package.json` defines some npm scripts.\nThose scripts can be executed using:\n\n```shell\n\u003e npm run \u003cname-of-the-script\u003e\n```\n\nThe most important npm scripts of the project are described below:\n\n```jsonc\n{\n  \"scripts\": {\n\n    // ===== EXECUTE CLI =============================\n\n    // RUN the CLI application using TS-NODE (no artifact is generated)\n    \"start\": \"ts-node --project tsconfig.common.json src/application.ts -d\",\n\n    // START the COMPILED CLI application (prior build is required)\n    \"node\": \"node bin/application.js\",\n\n    // ===== BUILD ARTIFACTS ========================\n\n    // BUILD the single artifacts\n    \"build:bin\": \"tsc -p tsconfig.bin.json\",\n    \"build:cjs\": \"tsc -p tsconfig.cjs.json\",\n    \"build:esm\": \"tsc -p tsconfig.esm.json\",\n    \"build:types\": \"tsc -p tsconfig.types.json\",\n\n    // BUILD ALL artifacts at once\n    \"build\": \"npm run build:types \u0026\u0026 npm run build:bin \u0026\u0026 npm run build:cjs \u0026\u0026 npm run build:esm\",\n\n    // ===== PACKAGE PUBLICATION======================\n\n    // PREPARE and GENERATE all artifacts for publishing usage\n    \"prod\": \"npm run cleanup \u0026\u0026 npm run build \u0026\u0026 npm run copyts \u0026\u0026 npm run test:prod\",\n\n    // check the content of the NPM package i.e. the list of artifacts that should be published\n    \"checkpkg\": \"pkgfiles\",\n\n    // Pre-publishing (this script will be executed by NPM automatically when publishing)\n    \"prepublishOnly\": \"npm run prod\",\n\n    // ===== DEVELOPMENT ONLY ========================\n\n    // generate the artifacts and link the project in the local npm repository\n    \"local:publish\": \"npm run prod \u0026\u0026 npm link\",\n    // undo the local npm repository link\n    \"local:unpublish\": \"npm unlink \u0026\u0026 npm run cleanup:nodemodules \u0026\u0026 npm install\",\n\n    // ===== HELPERS =================================\n\n    // delete the folders containing the published artifacts\n    \"cleanup\": \"rimraf ./lib ./bin ./coverage\",\n    // delete the node_modules folder (e.g. when un-linking the project to local npm repository)\n    \"cleanup:nodemodules\": \"npx rimraf ./node_modules\",\n    // copy the Typescript artifacts to be published in the npm package\n    \"copyts\": \"copyfiles -u 2 src/lib/**/* -e **/*.spec.ts lib/ts\"\n  }\n}\n```\n\nNote: Using this configuration allows to publish the library on NPM without hassle. Just call `\u003e npm publish`! The configured npm scripts will do the rest.\n\n### The `package.json` targets\n\nOnce the artifacts are produced and published, a client project intending to use the library package will operate a lookup in the package definition to **find and use an appropriate library artifact**:\n\nthis automatic lookup is using the following **fields** (if available) as defined in the `package.sjon` file:\n\n```jsonc\n{\n  // This define the DEFAULT artifact of the package. Here: the TYPESCRIPT version\n  \"main\": \"lib/ts/library.ts\",\n\n  // Tells the client project where the type declarations are located\n  \"types\": \"lib/ts/library.d.ts\",\n\n  // Locate the main ESM artifact for an ESM capable environment (e.g. node \u003e= v13.* if configured approprietly)\n  \"module\": \"lib/esm/library.js\",\n\n  // Locate the main ESM artifact for Browser environment...\n  \"browser\": \"lib/esm/library.js\",\n\n  // This location is NOT standard, thus included here for documentation purposes.\n  // The value could be used in place of the \"main\" defined above = to publish a CJS-BY-DEFAULT package\n  \"node\": \"lib/cjs/library.js\",\n\n  // Locate the CLI app artifact. Used when installing the package to register the CLI on the system (localy or globaly). The CLI executable is registered as \"ts4all\" here.\n  \"bin\": {\n    \"ts4all\": \"bin/application.js\"\n  },\n}\n```\n\n**Notes**: The PoC package is defining the \"Typescript artifact\" as the **default**. Instead, the \"CJS artifact\" could have been declared as default through the key-value `\"main\": \"lib/cjs/library.js\"`.\n\n### Important !\n\nThe `\"main\"`, `\"module\"` and `\"browser\"` keys specified in the library (i.e. in the `package.json` of the library) \u003cu\u003edo impact the binding of the library\u003c/u\u003e in any client project: the configuration in the library entails the suitable usage of the `import ... from ...;` and `... = require(...);` statements (including suitable paths) in the client projects!\n\nThus, it is recommended to *never change this specification after the library package has been published*. Otherwise, a \"**BREAKING CHANGE**\" should be commited and a major version released!\n(See [BREAKING CHANGES in commits][commitguideline])\n\n## Project documentation\n\n- [Sample Client Applications][samples]\n- [commit guideline][commitguideline]\n- [project development][development]\n\n[samples]: examples/README.md\n[commitguideline]: doc/commit-messages-guideline.md\n[development]: doc/development.md\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkhatastroffik%2Fone-ts-for-all","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkhatastroffik%2Fone-ts-for-all","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkhatastroffik%2Fone-ts-for-all/lists"}