1 - Doc
Goal of this package is to install all the necessary configuration files of a package (eslint.config.js, prettier.config.js,...). If a configuration files needs changing, we only need to modify it in this package and all the packages that use the configs
packages will be updated automatically.
The configs
package must be installed as devDependency of the target package. In a monorepo, it must be installed as devDependency at the root.
Each target package must contain a project.config.js
file that exports an object whose keys are the names of the configuration files to create for that package and values the contents of these files.
In a monorepo, the project.config.js
file to create at the root will usually look loke this:
import * as Configs from "@parischap/configs";
export default Configs.configMonorepo;
In each subpackage, the project.config.js
file to create will usually look loke this:
import { merge } from "ts-deepmerge";
import * as Configs from "@parischap/configs";
export default merge(
Configs.configSubRepo({
environment: Environment.Type.Node,
bundled: true,
visibility: Visibility.Type.Private,
hasStaticFolder: false,
hasDocGen: false,
keywords: [],
}),
{
[constants.packageJsonFileName]: {
description: "Whatever it is",
dependencies: {
effect: constants.effectVersion,
"@effect/platform": constants.effectPlatformVersion,
"@effect/platform-node": constants.effectPlatformNodeVersion,
},
scripts: {
whatever: `whatever`,
},
},
},
);
The Configs.configSubRepo
function takes the following parameter:
- environment: specifies where the package will run:
Environment.Type.Node
for execution under node context, Environment.Type.Browser
for execution in a browser and Environment.Type.Library
for a library that may run both in node and a browser. - bundled: if set to true, all ts files under
esm/
(except those under the shared/
directory) become standalone executables in which are bundled all used files in the shared/
directory and all dependencies (but not the peerDependencies). Type files are created for each executable. If a bin directory is present under esm/, it will be built directly under dist and not under dist/esm. If bundled is set to false, all files under esm/
are simply transpiled in js, cjs and d.ts files. - visibility:
Visibility.Type.Public
if the package is to be published to the NPM registry, Visibility.Type.PublicByForce
if the package should be private but is published to NPM out of technical reasons and Visibility.Type.Private
is the package is not to be published. - hasStaticFolder: specifies if the package has a static folder which is to be copied unchanged under
dist/
(usually for websites) - Works only for bundled packages. - hasDocGen: specifies if doc must be generated and published to github for this package.
- keywords: a list of keywords for packages published to npm.
The configs
package uses itself to generate its configuration files. To that extent, the following procedure must be followed for that package only:
- run
node esm/shared/init/main.mjs
- run
pnpm build
For other packages, the procedure to follow is:
- run
pnpm update-config-files
at the target package root. Alternatively, in a monorepo, you can run pnpm update-all-config-files
at the root of the monorepo. - run
pnpm build
For pnpm update-config-files
to work, there needs to be a package.json
file at the root of the target package and, if in a monerepo, at the root of the monorepo. If this is not the case, you can simply create the following package.json
files:
1.1 - In a standalone package
{
"scripts": {
"update-config-files": "update-config-files",
},
"devDependencies": {
"@parischap/configs": "latest"
}
}
1.2 - In a monorepo
1.2.1 - At the root of the monorepo
{
"scripts": {
"update-config-files": "update-config-files",
"update-all-config-files": "pnpm -r -include-workspace-root=true --workspace-concurrency=1 update-config-files",
},
"devDependencies": {
"@parischap/configs": "latest",
},
}
1.2.2 - At the root of each subrepo
{
"scripts": {
"update-config-files": "update-config-files",
}
}
pnpm i
must be run first to install the configs
package.
When a package is built, you can push it to github. Upon creating a new release, two github workflows will automatically publish the package to npm if this is a public package (see github.workflows.publish.template.ts). For this to work, make sure in github:
- to have read and write permissions under workflow in Settings/Actions/General.
- to add the NPM_PUBLISH_TOKEN under Repository secrets in Settings/Secrets and variables/Actions
- to have Github Actions for Build And Deployment in Settings/Pages.
Notes:
- there is no reason to create releases for a privaye package. So normally the
publish.yml
action should not get launched. However, in case it does, the package will not get published because there is the private
key in package.json and the build-and-publish
script has been deactivated. publish.yml
can be started manually. In that case, it uses has release number the last issued release. It can be useful if the publish action has failed and no modification to the code is necessary. If a modification to the code is necessary, a new release will have to be issued.pages.yml
creates the documentation for the package. In all cases, it must be started manually.
2 - About tsconfig:
- if the include directive does not match any ts file, it is considered that there is no include directive. It then falls back to the default which is all files in all subdirectories. In particular, if it finds only .js files and even if allowJs and checkJs are activated, it will revert to the default.
- typescript looks for the nearest tsconfig. If the file is not covered by that tsconfig, it does not look any further. It considers this files is not covered by a tsconfig. It will not try to see if there is another tsconfig up the directory tree that covers this file.
- the eslint tsconfig.json does not need to include any library because eslint as its own library management. So it can be put at monorepo level.
3 - About npm:
NPM is free for public packages. I did not find a way to publish to npm a package that is private under github. As a minor security measure, we can publish the code minified and bundled version without the source code or maps. But users can always see the code on github. So this solution can be used for non sensitive stuff. A solution could be to have a private github repo with the source code and a public github repo with the compiled code...Maybe by using git submodules (see https://git-scm.com/book/en/v2/Git-Tools-Submodules)
NPM error messages are misleading. It can for instance indicate an authentification error when the issue is that the package is marked as private in package.json.
To use granular tokens to publish to npm, the package to publish must already exist! So the first time, use vscode, cd to the dist folder of the package to publish and hit npm publish --access=public
. If there is an authentification error, try hitting npm adduser
first. Once the repo is created on npm, go to its settings and choose 'Require two-factor authentication or an automation or granular access token' for publishing access.
4 - About package.json:
Dependencies imported at the top of a monorepo and bin executables defined there are available in all sub packages. Only devDependencies and bin executables should be added in that manner as each package must have the list of its real dependencies.