@storm-software/projen
Version:
Tools for managing Projen configuration automation within a Nx workspace.
495 lines (493 loc) • 16.9 kB
JavaScript
import {
joinPaths
} from "../../chunk-LDQSXIL7.mjs";
import {
init_esm_shims
} from "../../chunk-PEAVGRTD.mjs";
// src/components/nx-workspace.ts
init_esm_shims();
import {
NX_DEFAULT_BUILD_OUTPUTS as BASE_NX_DEFAULT_BUILD_OUTPUTS,
NxWorkspace
} from "@aws/pdk/monorepo/components/nx-workspace";
import { ProjectUtils } from "@aws/pdk/monorepo/utils";
import { asUndefinedIfEmpty } from "@aws/pdk/monorepo/utils/common";
import { readFileSync } from "node:fs";
import { JsonFile } from "projen";
var NX_DEFAULT_BUILD_OUTPUTS = [
...BASE_NX_DEFAULT_BUILD_OUTPUTS,
"{workspaceRoot}/dist/{projectRoot}"
];
var StormNxWorkspace = class extends NxWorkspace {
/**
* Retrieves the singleton instance associated with project root.
*
* @param scope project instance.
*/
static of(scope) {
return scope.root.components.find(
(c) => ProjectUtils.isNamedInstanceOf(c, NxWorkspace)
);
}
/**
* Raw nx.json file to support overrides that aren't handled
* directly.
*
* **Attention:** any overrides applied here will not be visible
* in the properties and only included in final synthesized output,
* and likely to override native handling.
* @advanced
*/
nxJson;
/**
* Automatically infer NxProject targets based on project type.
* @experimental
*/
autoInferProjectTargets = true;
/**
* List of cacheable operations.
*/
cacheableOperations = [
"lint-sherif",
"lint-knip",
"lint-ls",
"lint",
"format-readme",
"format-toml",
"format-prettier",
"format",
"clean",
"build-base",
"build",
"test",
"e2e",
"docs",
"nx-release-publish"
];
/**
* Some presets use the extends property to hide some default options in a separate json file.
* The json file specified in the extends property is located in your node_modules folder.
* The Nx preset files are specified in the nx package.
*
* @default "@storm-software/workspace-tools/config/base.json"
*/
extends = "@storm-software/workspace-tools/config/base.json";
/**
* Plugins for extending the project graph
*/
nxPlugins = [
{
plugin: "@nx/eslint/plugin",
exclude: ["packages/**/__fixtures__/**/*"],
options: {
targetName: "lint",
useFlatConfig: true
}
},
"@storm-software/workspace-tools/plugins/typescript",
"@storm-software/workspace-tools/plugins/typescript/untyped",
"@storm-software/workspace-tools/plugins/typescript/tsup"
];
/**
* Default options for `nx affected`
*/
affected = {
defaultBase: "main"
};
/**
* Named inputs
* @see https://nx.dev/reference/nx-json#inputs-&-namedinputs
*/
namedInputs = {
// https://nx.dev/more-concepts/customizing-inputs#defaults
sharedGlobals: [
"{workspaceRoot}/.github/**/*",
"{workspaceRoot}/assets/**/*",
"{workspaceRoot}/tsconfig.*.json",
"{workspaceRoot}/.npm@(rc|ignore)",
"{workspaceRoot}/package.json",
"{workspaceRoot}/{pnpm-workspace,pnpm-lock,package-lock,yarn-lock}.@(yaml|yml)",
"{workspaceRoot}/bun.lockb",
"{workspaceRoot}/LICENSE",
"{workspaceRoot}/.git@(attributes|ignore)",
"{workspaceRoot}/{nx.json,.nxignore}",
"{workspaceRoot}/storm-workspace{,.*}.@(json|yaml|toml)",
"{workspaceRoot}/.storm-workspace/config{,.*}.@(json|yaml|toml)",
"{workspaceRoot}/storm-workspace.config.[jt]s",
"{workspaceRoot}/.storm-workspace/config{,.*}.[jt]s",
"{workspaceRoot}/.env{,.local}"
],
default: ["sharedGlobals", "{projectRoot}/**/*"],
production: [
"{projectRoot}/**/*",
"!{projectRoot}/{tools,scripts}/**/*",
"!{projectRoot}/node_modules/**/*",
"!{projectRoot}/{api-extractor,tsdoc,typedoc}.json",
"!{projectRoot}/.eslint-doc-generatorrc.@(js|json)",
"!{projectRoot}/.storybook/**/*",
"!{projectRoot}/tsconfig.storybook.json",
"!{projectRoot}/jest.config.ts",
"!{projectRoot}/tsconfig.spec.json",
"!{projectRoot}/{src/,}test-setup.[jt]s",
"!{projectRoot}/.eslintignore",
"!{projectRoot}/.eslintrc.@(json|cjs)",
"!{projectRoot}/eslint.config.@(js|cjs|mjs|ts|cts|mts|json)",
"!{projectRoot}/biome.@(toml|json)",
"!{projectRoot}/lefthook.@(yaml|yml)",
"!{projectRoot}/.markdownlint.json",
"!{projectRoot}/.markdownlint-cli2.cjs",
"!{projectRoot}/.prettier@(rc|ignore)",
"!{projectRoot}/docs/**/*",
"!{projectRoot}/**/*.stories.@(js|jsx|ts|tsx|mdx)",
"!{projectRoot}/{benches,e2e,tests,testing}/**/*",
"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)"
],
testing: [
"sharedGlobals",
"{workspaceRoot}/{jest.config,jest.preset,vitest.config,vitest.preset,vitest.workspace}.@(js|cjs|mjs|ts|cts|mts)",
"{workspaceRoot}/{benches,e2e,tests,testing}/**/*",
"{workspaceRoot}/coverage/**/*",
"{projectRoot}/{project.json,README.md,CHANGELOG.md}",
"{projectRoot}/.env{,.*}",
"{projectRoot}/{jest.config,vitest.config}.@(js|cjs|mjs|ts|cts|mts)",
"{projectRoot}/tsconfig.spec.json",
"{projectRoot}/{src/,}test-setup.[jt]s",
"{projectRoot}/{benches,e2e,tests,testing}/**/*",
"{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)"
],
linting: [
"sharedGlobals",
"{workspaceRoot}/.eslintignore",
"{workspaceRoot}/.eslintrc.@(js|cjs|mjs|ts|cts|mts|json)",
"{workspaceRoot}/eslint.config.@(js|cjs|mjs|ts|cts|mts)",
"{workspaceRoot}/biome.@(toml|json)",
"{workspaceRoot}/lefthook.@(yaml|yml|json)",
"{workspaceRoot}/.markdownlint.json",
"{workspaceRoot}/.markdownlint-cli2.@(js|cjs|mjs|ts|cts|mts)",
"{workspaceRoot}/.prettier@(rc|ignore)",
"{workspaceRoot}/prettier.config.@(js|cjs|mjs|ts|cts|mts)",
"{projectRoot}/{project.json,README.md,CHANGELOG.md}",
"{projectRoot}/.env{,.*}",
"{projectRoot}/.eslintignore",
"{projectRoot}/.eslintrc.@(js|cjs|mjs|ts|cts|mts|json)",
"{projectRoot}/eslint.config.@(js|cjs|mjs|ts|cts|mts)",
"{projectRoot}/biome.@(toml|json)",
"{projectRoot}/lefthook.@(yaml|yml|json)",
"{projectRoot}/.markdownlint.json",
"{projectRoot}/.markdownlint-cli2.@(js|cjs|mjs|ts|cts|mts)",
"{projectRoot}/.prettier@(rc|ignore)"
],
documentation: [
"sharedGlobals",
"{workspaceRoot}/{api-extractor,tsdoc,typedoc}.json",
"{workspaceRoot}/.eslint-doc-generatorrc.@(js|json)",
"{workspaceRoot}/contentlayer.config.ts",
"{workspaceRoot}/*.@(md|mdx)",
"{workspaceRoot}/docs/**/*",
"{workspaceRoot}/.storybook/**/*",
"{projectRoot}/{project.json,README.md,CHANGELOG.md}",
"{projectRoot}/.env{,.local}",
"{projectRoot}/{api-extractor,tsdoc,typedoc}.json",
"{projectRoot}/.eslint-doc-generatorrc.@(js|json)",
"{projectRoot}/contentlayer.config.ts",
"{projectRoot}/.storybook/**/*",
"{projectRoot}/tsconfig.storybook.json",
"{projectRoot}/docs/**/*",
"{projectRoot}/**/*.stories.@(js|jsx|ts|tsx|mdx)",
"!{projectRoot}/{benches,e2e,tests,testing}/**/*",
"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
"!{projectRoot}/tsconfig.spec.json"
],
rust: [
"sharedGlobals",
"{workspaceRoot}/Cargo.toml",
"{workspaceRoot}/Cargo.lock",
"{workspaceRoot}/.cargo/config.toml",
"{workspaceRoot}/rust-toolchain",
"{workspaceRoot}/rustfmt.toml",
"{workspaceRoot}/deny.toml",
"{projectRoot}/Cargo.toml",
"{projectRoot}/.cargo/config.toml",
"{projectRoot}/{project.json,CHANGELOG.md}",
"{projectRoot}/.env{,.local}",
"{projectRoot}/**/*.rs",
"{projectRoot}/**/*.@(proto|acid|acidic|prisma)",
"{projectRoot}/src/**/*.@(json|jsonc|yaml|yml|toml)",
"!{projectRoot}/README.md",
"!{projectRoot}/docs/**/*",
"!{projectRoot}/{benches,e2e,tests,testing}/**/*"
],
typescript: [
"sharedGlobals",
"!{projectRoot}/tsconfig.@(spec|storybook).json",
"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
"!{projectRoot}/**/*.stories.@(js|jsx|ts|tsx|mdx)",
"!{projectRoot}/node_modules/**/*",
"!{projectRoot}/{benches,e2e,tests,testing}/**/*",
"{projectRoot}/package.json",
"{projectRoot}/tsconfig.json",
"{projectRoot}/tsconfig.*.json",
"{projectRoot}/{project.json,README.md,CHANGELOG.md}",
"{projectRoot}/.env{,.*}",
"{projectRoot}/docs/**/*",
"{projectRoot}/**/*.stories.@(js|jsx|ts|tsx|mdx)",
"{projectRoot}/**/*.@(proto|acid|acidic|prisma)",
"{projectRoot}/src/**/*.@(cts|mts|ts|tsx|graphql|gql|js|cjs|mjs|jsx|json|jsonc|yaml|yml|toml|md|mdx)",
"{projectRoot}/{build,tsup,contentlayer}.*.[jt]s?(x)",
"{projectRoot}/{bin,tools,helpers,scripts}/**/*"
]
};
/**
* Dependencies between different target names across all projects
*
* @see https://nx.dev/reference/nx-json#target-defaults
*/
targetDefaults = {
"lint-ls": {
outputs: ["{projectRoot}/**/*"],
inputs: ["linting", "default", "^production"],
dependsOn: ["^lint-ls"],
executor: "nx:run-commands",
options: {
command: 'pnpm exec ls-lint --config="./node_modules/@storm-software/linting-tools/ls-lint/.ls-lint.yml" ',
color: true
}
},
"lint-sherif": {
outputs: ["{projectRoot}/package.json"],
inputs: ["{workspaceRoot}/package.json", "{projectRoot}/package.json"],
executor: "nx:run-commands",
options: {
command: "pnpm exec sherif -i react -i react-dom -i typescript"
}
},
"lint-knip": {
inputs: ["linting", "default", "^production"],
executor: "nx:run-commands",
options: {
command: "pnpm exec knip"
}
},
lint: {
outputs: ["{projectRoot}"],
inputs: ["linting", "default", "^production"],
dependsOn: ["lint-ls", "lint-sherif", "lint-knip", "lint-docs", "^lint"],
executor: "nx:run-commands",
options: {
command: 'echo Linted the project files in "{projectRoot}" '
}
},
"format-toml": {
inputs: ["linting", "{projectRoot}/**/*.toml"],
outputs: ["{projectRoot}/**/*.toml"],
dependsOn: ["^format-toml"],
executor: "nx:run-commands",
options: {
command: 'pnpm exec taplo format --colors="always" --config="./node_modules/@storm-software/linting-tools/taplo/config.toml" --cache-path="./tmp/taplo/{projectRoot}"',
color: true
}
},
"format-readme": {
inputs: [
"linting",
"documentation",
"{projectRoot}/{README.md,package.json,Cargo.toml,executors.json,generators.json}",
"default",
"^production"
],
outputs: ["{projectRoot}/README.md"],
dependsOn: ["^format-readme"],
executor: "nx:run-commands",
options: {
command: 'pnpm exec storm-git readme-gen --templates="./tools/readme-templates" --project="{projectName}"',
color: true
}
},
"format-prettier": {
inputs: ["linting", "default", "^production"],
dependsOn: ["^format-prettier"],
executor: "nx:run-commands",
options: {
command: 'pnpm exec prettier "{projectRoot}/**/*" --write --ignore-unknown --no-error-on-unmatched-pattern --config="./node_modules/@storm-software/prettier/config.json" --ignore-path="./node_modules/@storm-software/prettier/.prettierignore" --cache --cache-location="./tmp/prettier/{projectRoot}" ',
color: true
}
},
format: {
inputs: ["linting", "default", "^production"],
outputs: ["{projectRoot}"],
dependsOn: ["format-toml", "format-readme", "format-prettier", "^format"],
executor: "nx:run-commands",
options: {
command: 'echo Formatted the project files in "{projectRoot}" '
}
},
clean: {
inputs: ["default", "^production"],
outputs: NX_DEFAULT_BUILD_OUTPUTS,
dependsOn: ["^clean"],
executor: "nx:run-commands",
options: {
commands: [
"pnpm exec rimraf --glob {projectRoot}/dist",
"pnpm exec rimraf dist/{projectRoot}"
]
}
},
"build-untyped": {
dependsOn: ["^build"]
},
"build-base": {
dependsOn: ["build-untyped", "^build"]
},
"build-local": {
inputs: ["default", "^production"],
dependsOn: ["build-base", "build-untyped", "^build"]
},
build: {
inputs: ["default", "^production"],
outputs: NX_DEFAULT_BUILD_OUTPUTS,
dependsOn: ["build-base", "build-untyped", "^build"]
},
rebuild: {
inputs: ["default", "^production"],
executor: "nx:run-commands",
dependsOn: ["clean", "^build"],
options: {
command: "pnpm exec nx run {projectName}:build",
color: true,
cwd: "{workspaceRoot}"
}
},
docs: {
outputs: ["{options.outputPath}"],
inputs: ["linting", "documentation", "default", "^production"],
dependsOn: ["build", "format-readme", "lint-docs", "^docs"]
},
test: {
inputs: ["testing", "default", "^production"],
dependsOn: ["build", "^test"]
},
e2e: {
inputs: ["testing", "default", "^production"],
dependsOn: ["test", "^e2e"]
},
"nx-release-publish": {
inputs: ["default", "^production"],
dependsOn: ["build", "^nx-release-publish"]
}
};
/**
* Configuration for Nx releases
*/
release = {};
/**
* The number of parallel tasks to run.
*
* @defaultValue 5
*/
parallel = 5;
/**
* Should the daemon be used to run tasks?
*
* @defaultValue true
*/
useDaemonProcess = true;
/**
* Set this to false to disable adding inference plugins when generating new projects
*
* @defaultValue true
*/
useInferencePlugins = true;
/**
* The default base branch for new projects.
*
* @defaultValue "main"
*/
defaultBase = "main";
/**
* The CLI configuration for the workspace.
*/
cli;
constructor(project) {
super(project);
let StormWorkspaceConfig;
if (project.root.outdir) {
const StormWorkspaceConfigJson = readFileSync(
joinPaths(project.root.outdir, "storm-workspace.json"),
"utf8"
);
StormWorkspaceConfig = JSON.parse(StormWorkspaceConfigJson);
}
if (StormWorkspaceConfig?.namespace) {
this.npmScope = StormWorkspaceConfig?.namespace;
}
if (StormWorkspaceConfig?.branch) {
this.defaultBase = StormWorkspaceConfig?.branch;
this.affected = {
defaultBase: StormWorkspaceConfig?.branch
};
}
if (StormWorkspaceConfig?.packageManager) {
this.cli = {
packageManager: StormWorkspaceConfig?.packageManager
};
}
this.nxJson = new JsonFile(project, "nx.json", {
obj: {
extends: () => this.extends,
npmScope: () => this.npmScope,
affected: () => asUndefinedIfEmpty(this.affected),
workspaceLayout: () => asUndefinedIfEmpty(this.workspaceLayout),
plugins: () => asUndefinedIfEmpty(this.nxPlugins),
namedInputs: () => asUndefinedIfEmpty(this.namedInputs),
targetDefaults: () => asUndefinedIfEmpty(this.targetDefaults),
tasksRunnerOptions: () => asUndefinedIfEmpty(this.tasksRunnerOptions),
parallel: () => this.parallel,
useDaemonProcess: () => this.useDaemonProcess,
useInferencePlugins: () => this.useInferencePlugins,
release: () => asUndefinedIfEmpty(this.release)
}
});
}
/**
* Adds a release group to the workspace.
*
* @param name The name of the release group
* @param projects The projects in the release group
* @param projectsRelationship The relationship between the projects
* @param releaseTagPattern The release tag pattern
* @param groupPreVersionCommand The command to run before versioning
*/
addReleaseGroup(name, projects, projectsRelationship = "independent", releaseTagPattern = "{projectName}@{version}", groupPreVersionCommand = "pnpm build") {
this.release ??= {
groups: {},
changelog: {
entryWhenNoChanges: false,
renderOptions: {
authors: false,
commitReferences: true,
versionTitleDate: true
}
}
};
this.release.groups[name] = {
projects,
projectsRelationship,
releaseTagPattern,
version: {
groupPreVersionCommand,
currentVersionResolver: "git-tag",
specifierSource: "conventional-commits",
generator: "@storm-software/workspace-tools:release-version",
generatorOptions: {
currentVersionResolver: "git-tag",
specifierSource: "conventional-commits"
}
}
};
}
};
export {
NX_DEFAULT_BUILD_OUTPUTS,
StormNxWorkspace
};