Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/khatastroffik/one-ts-for-all
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 !
https://github.com/khatastroffik/one-ts-for-all
application bin blueprint cjs cli commonjs commonjs-modules ecmascript esm esm-libraries jest module multiple-targets nodejs one4all poc ts tsc type-declarations typescript
Last synced: 3 months ago
JSON representation
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 !
- Host: GitHub
- URL: https://github.com/khatastroffik/one-ts-for-all
- Owner: khatastroffik
- Created: 2020-06-08T07:38:23.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2023-01-06T08:17:12.000Z (about 2 years ago)
- Last Synced: 2024-10-27T01:08:26.929Z (3 months ago)
- 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
- Language: JavaScript
- Homepage:
- Size: 1.44 MB
- Stars: 2
- Watchers: 2
- Forks: 2
- Open Issues: 12
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
Awesome Lists containing this project
README
# One Typescript for all
This 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**
Table-of-Content
- [Overview](#overview)
- [Objectives](#objectives)
- [SINGLE TYPESCRIPT INPUT → MULTIPLE OUTPUT](#single-typescript-input-rightarrow-multiple-output)
- [RUN ESM LIBRARIES IN THE BROWSER](#run-esm-libraries-in-the-browser)
- [Requirements](#requirements)
- [Project Development versus Package Publication](#project-development-versus-package-publication)
- [How to implement "one-for-all"?](#how-to-implement-one-for-all)
- [Sources](#sources)
- [Typescript compiler (TSC) configuration](#typescript-compiler-tsc-configuration)
- [*.gitignore* file](#gitignore-file)
- [npm scripts](#npm-scripts)
- [The `package.json` targets](#the-packagejson-targets)
- [Important !](#important)
- [Project documentation](#project-documentation)## Overview
![one-typescript-for-all Architecture](doc/one-ts-for-all.png)
## Objectives
### SINGLE TYPESCRIPT INPUT → MULTIPLE OUTPUT
This is the main objective: **ONE-FOR-ALL**!
- **Implement** a library using **Typescript exclusively**.
- **Use** the library with any client which is able to use/run **CommonJS, ECMAScript or Typescript modules**.### RUN ESM LIBRARIES IN THE BROWSER
A *browser app/client* may use the *ESM library* directly. In this case, a **modern browser** is required.
**This use case is demonstrated in this PoC**.Older 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**.
## Requirements
**Node.js** and **NPM** (or **yarn**) should be "globally" installed on your system to ease the installation of the packages and/or source files.
Preferably:- node: >=13.x
- npm: >=6.x**Typescript** may be globally present as well, thus is not required, since the PoC will use its own (local) version:
- tsc: >=3.9.5 (earlier version like 3.8.x should be ok - not tested, though)
## Project Development versus Package Publication
The PoC is configured (`package.json` and `.gitignore`) to separate development and usage of the lib/app: "GitHub" versus "NPM".
1. The bare **sources** (typescript only) of the library and application are stored in the **Github Repository**.
use this if you'd like to **develop**, adapt etc. the library/application1. The **transpiled** i.e. usable library artifact (ESM, CommonJS, Typescript and `*.d.ts` types declaration files ) is stored in the **NPM repository** - though without the source files.
use this if you'd like to **use** the library/application in your project.This separation is intended:
- to reduce the size of the published package to the min possible and
- to **clearly separate the different concerns**.**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.
## How to implement "one-for-all"?
This section summarize the techniques i.e. engineering procedures used to realize the "one-for-all" objective.
### Sources
The sources files are all contained in the `src` folder. No exception.
### Typescript compiler (TSC) configuration
The output (multiple modules i.e. CJS, ESM...) of **TSC** is driven by the different `tsconfig.*.json`files and by the `package.json` file:
1. 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**.
1. 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).
1. The `tsconfig.bin.json` is targeting the generation/output of the **CLI application** in the `bin` folder.
1. The `tsconfig.esm.json` is targeting the generation/output of the **ESM scripts** version in the `lib/esm/` folder.
1. The `tsconfig.cjs.json` is targeting the generation/output of the **ESM scripts** version in the `lib/esm/` folder.
1. 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.### *.gitignore* file
Since the source code repository should NOT contain the "*output*" of the compilation/distribution, the `.gitignore` file excludes the corresponding folders: `/lib` and `/bin`.
### npm scripts
In 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.
Those scripts can be executed using:```shell
> npm run
```The most important npm scripts of the project are described below:
```jsonc
{
"scripts": {// ===== EXECUTE CLI =============================
// RUN the CLI application using TS-NODE (no artifact is generated)
"start": "ts-node --project tsconfig.common.json src/application.ts -d",// START the COMPILED CLI application (prior build is required)
"node": "node bin/application.js",// ===== BUILD ARTIFACTS ========================
// BUILD the single artifacts
"build:bin": "tsc -p tsconfig.bin.json",
"build:cjs": "tsc -p tsconfig.cjs.json",
"build:esm": "tsc -p tsconfig.esm.json",
"build:types": "tsc -p tsconfig.types.json",// BUILD ALL artifacts at once
"build": "npm run build:types && npm run build:bin && npm run build:cjs && npm run build:esm",// ===== PACKAGE PUBLICATION======================
// PREPARE and GENERATE all artifacts for publishing usage
"prod": "npm run cleanup && npm run build && npm run copyts && npm run test:prod",// check the content of the NPM package i.e. the list of artifacts that should be published
"checkpkg": "pkgfiles",// Pre-publishing (this script will be executed by NPM automatically when publishing)
"prepublishOnly": "npm run prod",// ===== DEVELOPMENT ONLY ========================
// generate the artifacts and link the project in the local npm repository
"local:publish": "npm run prod && npm link",
// undo the local npm repository link
"local:unpublish": "npm unlink && npm run cleanup:nodemodules && npm install",// ===== HELPERS =================================
// delete the folders containing the published artifacts
"cleanup": "rimraf ./lib ./bin ./coverage",
// delete the node_modules folder (e.g. when un-linking the project to local npm repository)
"cleanup:nodemodules": "npx rimraf ./node_modules",
// copy the Typescript artifacts to be published in the npm package
"copyts": "copyfiles -u 2 src/lib/**/* -e **/*.spec.ts lib/ts"
}
}
```Note: Using this configuration allows to publish the library on NPM without hassle. Just call `> npm publish`! The configured npm scripts will do the rest.
### The `package.json` targets
Once 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**:
this automatic lookup is using the following **fields** (if available) as defined in the `package.sjon` file:
```jsonc
{
// This define the DEFAULT artifact of the package. Here: the TYPESCRIPT version
"main": "lib/ts/library.ts",// Tells the client project where the type declarations are located
"types": "lib/ts/library.d.ts",// Locate the main ESM artifact for an ESM capable environment (e.g. node >= v13.* if configured approprietly)
"module": "lib/esm/library.js",// Locate the main ESM artifact for Browser environment...
"browser": "lib/esm/library.js",// This location is NOT standard, thus included here for documentation purposes.
// The value could be used in place of the "main" defined above = to publish a CJS-BY-DEFAULT package
"node": "lib/cjs/library.js",// 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.
"bin": {
"ts4all": "bin/application.js"
},
}
```**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"`.
### Important !
The `"main"`, `"module"` and `"browser"` keys specified in the library (i.e. in the `package.json` of the library) do impact the binding of the library 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!
Thus, 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!
(See [BREAKING CHANGES in commits][commitguideline])## Project documentation
- [Sample Client Applications][samples]
- [commit guideline][commitguideline]
- [project development][development][samples]: examples/README.md
[commitguideline]: doc/commit-messages-guideline.md
[development]: doc/development.md