├── .github ├── FUNDING.yml └── workflows │ ├── ci.yml │ └── pr.yml ├── .gitignore ├── .moon ├── tasks │ ├── node-library.yml │ └── node.yml ├── toolchain.yml └── workspace.yml ├── .prettierignore ├── .prettierrc.js ├── .prototools ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── .yarn └── releases │ └── yarn-4.7.0.cjs ├── .yarnrc.yml ├── LICENSE ├── README.md ├── babel.config.js ├── eslint.config.mjs ├── jest.config.js ├── lerna.json ├── package.json ├── packages ├── babel-preset │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── moon.yml │ ├── package.json │ ├── src │ │ └── index.ts │ ├── tsconfig.json │ └── tsconfig.lib.json ├── dev │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── moon.yml │ ├── package.json │ ├── src │ │ ├── bin │ │ │ └── lernaRelease.ts │ │ ├── constants.ts │ │ ├── helpers.ts │ │ └── index.ts │ ├── tsconfig.json │ └── tsconfig.lib.json ├── eslint-config │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── moon.yml │ ├── package.json │ ├── src │ │ ├── async.ts │ │ ├── base.ts │ │ ├── browser.ts │ │ ├── index.ts │ │ ├── jest.ts │ │ ├── module.ts │ │ ├── node.ts │ │ ├── react.ts │ │ ├── solid.ts │ │ ├── tests.ts │ │ ├── typescript.ts │ │ └── unicorn.ts │ ├── tsconfig.json │ └── tsconfig.lib.json ├── jest-preset │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── jest-preset.js │ ├── jest.config.js │ ├── moon.yml │ ├── package.json │ ├── src │ │ ├── fileMock.ts │ │ └── index.ts │ ├── tests │ │ └── jest.test.ts │ ├── tsconfig.json │ └── tsconfig.lib.json ├── prettier-config │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── moon.yml │ ├── package.json │ └── prettier.json ├── tsconfig │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── moon.yml │ ├── package.json │ ├── tsconfig.json │ ├── tsconfig.projects.json │ ├── tsconfig.react.json │ └── tsconfig.solid.json └── vscode-extension │ ├── .vscodeignore │ ├── CHANGELOG.md │ ├── DEV.md │ ├── LICENSE │ ├── README.md │ ├── assets │ ├── icons │ │ ├── file.svg │ │ ├── folder-open.svg │ │ └── folder.svg │ ├── langs │ │ ├── bash.svg │ │ ├── batch.svg │ │ ├── c.svg │ │ ├── cplusplus.svg │ │ ├── cpp.svg │ │ ├── crystal.svg │ │ ├── csharp.svg │ │ ├── css.svg │ │ ├── dart.svg │ │ ├── deno.svg │ │ ├── dotnet.svg │ │ ├── go.svg │ │ ├── haskell.svg │ │ ├── html.svg │ │ ├── java.svg │ │ ├── javascript.svg │ │ ├── julia.svg │ │ ├── kotlin.svg │ │ ├── lua.svg │ │ ├── node.svg │ │ ├── ocaml.svg │ │ ├── php.svg │ │ ├── python.svg │ │ ├── r.svg │ │ ├── ruby.svg │ │ ├── rust.svg │ │ ├── scala.svg │ │ ├── swift.svg │ │ ├── typescript.svg │ │ ├── unknown.svg │ │ └── zig.svg │ ├── moon-banner.png │ ├── moon-icon-theme.json │ ├── moon.svg │ └── webview.css │ ├── images │ ├── activity-icon.png │ ├── last-run-view.png │ ├── projects-view.png │ └── tags-view.png │ ├── moon.yml │ ├── package.json │ ├── src │ ├── commands.ts │ ├── extension.ts │ ├── graphVisualizerView.ts │ ├── lastRunView.ts │ ├── projectsView.ts │ └── workspace.ts │ └── tsconfig.json ├── tests └── setup.ts ├── tsconfig.json ├── tsconfig.options.json └── yarn.lock /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: moonrepo 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Pipeline 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | jobs: 8 | ci: 9 | name: CI 10 | runs-on: ubuntu-latest 11 | strategy: 12 | matrix: 13 | node-version: [20, 22] 14 | fail-fast: true 15 | env: 16 | YARN_IGNORE_NODE: 1 17 | steps: 18 | - uses: actions/checkout@v4 19 | with: 20 | fetch-depth: 0 21 | - uses: moonrepo/setup-toolchain@v0 22 | with: 23 | auto-install: true 24 | - run: yarn install --immutable 25 | - run: yarn setup 26 | - run: moon ci --log debug --color 27 | env: 28 | MOONBASE_SECRET_KEY: ${{ secrets.MOONBASE_SECRET_KEY }} 29 | MOONBASE_ACCESS_KEY: ${{ secrets.MOONBASE_ACCESS_KEY }} 30 | - uses: moonrepo/run-report-action@v1 31 | if: success() || failure() 32 | with: 33 | access-token: ${{ secrets.GITHUB_TOKEN }} 34 | matrix: ${{ toJSON(matrix) }} 35 | -------------------------------------------------------------------------------- /.github/workflows/pr.yml: -------------------------------------------------------------------------------- 1 | name: PR 2 | on: pull_request 3 | jobs: 4 | conventional: 5 | name: Conventional title 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v4 9 | - uses: actions/setup-node@v4 10 | - uses: beemojs/conventional-pr-action@v2 11 | env: 12 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs/ 3 | *.log 4 | 5 | # Cache 6 | .eslintcache 7 | .idea 8 | .npm 9 | .yarnclean 10 | 11 | # Directories 12 | coverage/ 13 | /build/ 14 | cjs/ 15 | dist/ 16 | dts/ 17 | esm/ 18 | lib/ 19 | mjs/ 20 | tmp/ 21 | umd/ 22 | node_modules/ 23 | 24 | # Custom 25 | *.min.js 26 | *.map 27 | *.tsbuildinfo 28 | *.vsix 29 | 30 | # Yarn 31 | .yarn/* 32 | !.yarn/patches 33 | !.yarn/releases 34 | !.yarn/plugins 35 | !.yarn/sdks 36 | !.yarn/versions 37 | .pnp.* 38 | 39 | # Moon 40 | .moon/cache 41 | -------------------------------------------------------------------------------- /.moon/tasks/node-library.yml: -------------------------------------------------------------------------------- 1 | $schema: 'https://moonrepo.dev/schemas/tasks.json' 2 | 3 | tasks: 4 | # https://moonrepo.dev/docs/guides/examples/packemon 5 | build: 6 | command: 'packemon' 7 | args: 8 | - 'build' 9 | - '--addEngines' 10 | - '--addExports' 11 | - '--declaration' 12 | inputs: 13 | - '@globs(sources)' 14 | - '@globs(typescript)' 15 | - 'package.json' 16 | outputs: 17 | - 'lib' 18 | env: 19 | NODE_ENV: 'production' 20 | -------------------------------------------------------------------------------- /.moon/tasks/node.yml: -------------------------------------------------------------------------------- 1 | $schema: 'https://moonrepo.dev/schemas/tasks.json' 2 | 3 | # Instead of fine tuning each project, always build dependencies and rely on the cache 4 | implicitDeps: 5 | - '^:build' 6 | 7 | implicitInputs: 8 | - 'package.json' 9 | 10 | fileGroups: 11 | configs: 12 | - '*.{js,cjs,mjs,json}' 13 | sources: 14 | - 'src/**/*' 15 | - 'types/**/*' 16 | tests: 17 | - 'tests/**/*.test.*' 18 | - '**/__tests__/**/*' 19 | assets: 20 | - 'assets/**/*' 21 | - 'images/**/*' 22 | - 'static/**/*' 23 | - '**/*.{scss,css}' 24 | - '**/*.mdx' 25 | typescript: 26 | - 'tsconfig.json' 27 | - 'tsconfig.*.json' 28 | - '/tsconfig.json' 29 | - '/tsconfig.*.json' 30 | 31 | tasks: 32 | # https://moonrepo.dev/docs/guides/examples/prettier 33 | format: 34 | command: 'prettier' 35 | args: 36 | - '--config' 37 | - '@in(1)' 38 | - '--ignore-path' 39 | - '@in(0)' 40 | - '--check' 41 | - '.' 42 | inputs: 43 | - '/.prettierignore' 44 | - '/.prettierrc.js' 45 | - '@globs(configs)' 46 | - '@globs(sources)' 47 | - '@globs(tests)' 48 | - '**/*.{md,mdx,yml,yaml,json}' 49 | 50 | format-write: 51 | command: 'prettier' 52 | args: 53 | - '--config' 54 | - '@in(1)' 55 | - '--ignore-path' 56 | - '@in(0)' 57 | - '--write' 58 | - '.' 59 | inputs: 60 | - '/.prettierignore' 61 | - '/.prettierrc.js' 62 | local: true 63 | 64 | # https://moonrepo.dev/docs/guides/examples/eslint 65 | lint: 66 | command: 'eslint' 67 | args: 68 | - '--fix' 69 | - '--report-unused-disable-directives' 70 | - '--no-error-on-unmatched-pattern' 71 | - '--exit-on-fatal-error' 72 | - '.' 73 | inputs: 74 | - '@globs(configs)' 75 | - '@globs(sources)' 76 | - '@globs(tests)' 77 | - '@globs(typescript)' 78 | - '/eslint.config.*' 79 | 80 | # https://moonrepo.dev/docs/guides/examples/jest 81 | test: 82 | command: 'jest --coverage --passWithNoTests' 83 | inputs: 84 | - '@globs(sources)' 85 | - '@globs(tests)' 86 | - '.babelrc.*' 87 | - 'babel.config.*' 88 | - 'jest.config.*' 89 | - '/babel.config.*' 90 | 91 | # https://moonrepo.dev/docs/guides/examples/typescript 92 | typecheck: 93 | command: 'tsc --build --pretty' 94 | inputs: 95 | - '@globs(sources)' 96 | - '@globs(tests)' 97 | - '@globs(typescript)' 98 | -------------------------------------------------------------------------------- /.moon/toolchain.yml: -------------------------------------------------------------------------------- 1 | $schema: 'https://moonrepo.dev/schemas/toolchain.json' 2 | 3 | # https://moonrepo.dev/docs/config/workspace#node 4 | node: 5 | version: '22.14.0' 6 | packageManager: 'yarn' 7 | yarn: 8 | version: '4.7.0' 9 | 10 | # Do not add an engines constraint as its abrasive for open source. 11 | addEnginesConstraint: false 12 | 13 | # Always dedupe lockfile to keep it healthy. 14 | dedupeOnLockfileChange: true 15 | 16 | # Use workspace ranges when syncing projects. 17 | dependencyVersionFormat: 'workspace-caret' 18 | syncProjectWorkspaceDependencies: true 19 | 20 | # Do not infer functionality from `package.json`, as we want to encourage 21 | # consumers to embrace moon. 22 | inferTasksFromScripts: false 23 | 24 | # https://moonrepo.dev/docs/config/workspace#typescript 25 | typescript: 26 | # Always create a missing config so we can catch misconfigured projects. 27 | createMissingConfig: true 28 | 29 | # Always route project reference declarations outside of the project. 30 | routeOutDirToCache: true 31 | 32 | # Always sync project references to keep it healthy. 33 | syncProjectReferences: true 34 | 35 | # Do not add path aliases, as this may be abrasive. Consumers can opt-in. 36 | syncProjectReferencesToPaths: false 37 | -------------------------------------------------------------------------------- /.moon/workspace.yml: -------------------------------------------------------------------------------- 1 | $schema: 'https://moonrepo.dev/schemas/workspace.json' 2 | 3 | projects: 4 | - 'packages/*' 5 | 6 | experiments: 7 | actionPipelineV2: true 8 | gitV2: true 9 | fasterGlobWalk: true 10 | 11 | # https://moonrepo.dev/docs/config/workspace#runner 12 | runner: 13 | # Cache these targets in the cloud 14 | archivableTargets: 15 | - ':format' 16 | - ':lint' 17 | - ':test' 18 | - ':typecheck' 19 | # Colors are nice... 20 | inheritColorsForPipedTasks: true 21 | # Always log the command so consumers understand what's happening. 22 | logRunningCommand: true 23 | 24 | # https://moonrepo.dev/docs/config/workspace#vcs 25 | vcs: 26 | manager: 'git' 27 | defaultBranch: 'master' 28 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | cjs/ 2 | coverage/ 3 | esm/ 4 | lib/ 5 | mjs/ 6 | node_modules/ 7 | CHANGELOG.md 8 | .yarn 9 | yarn.lock 10 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = 'prettier-config-moon'; 2 | -------------------------------------------------------------------------------- /.prototools: -------------------------------------------------------------------------------- 1 | moon = "1.36.0" 2 | node = "22.14.0" 3 | yarn = "4.7.0" 4 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Run Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "args": [ 13 | "--extensionDevelopmentPath=${workspaceFolder}/packages/vscode-extension" 14 | ], 15 | "outFiles": [ 16 | "${workspaceFolder}/packages/vscode-extension/lib/**/*.js" 17 | ], 18 | "preLaunchTask": "${defaultBuildTask}" 19 | } 20 | // { 21 | // "name": "Extension Tests", 22 | // "type": "extensionHost", 23 | // "request": "launch", 24 | // "args": [ 25 | // "--extensionDevelopmentPath=${workspaceFolder}/packages/vscode-extension", 26 | // "--extensionTestsPath=${workspaceFolder}/packages/vscode-extension/out/test/suite/index" 27 | // ], 28 | // "outFiles": [ 29 | // "${workspaceFolder}/packages/vscode-extension/out/**/*.js", 30 | // "${workspaceFolder}/packages/vscode-extension/dist/**/*.js" 31 | // ], 32 | // "preLaunchTask": "tasks: watch-tests" 33 | // } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "yaml.schemas": { 3 | "./.moon/cache/schemas/project.json": [ 4 | "**/moon.yml" 5 | ], 6 | "./.moon/cache/schemas/tasks.json": [ 7 | ".moon/tasks.yml", 8 | ".moon/tasks/**/*.yml" 9 | ], 10 | "./.moon/cache/schemas/template.json": [ 11 | "**/template.yml" 12 | ], 13 | "./.moon/cache/schemas/toolchain.json": [ 14 | ".moon/toolchain.yml" 15 | ], 16 | "./.moon/cache/schemas/workspace.json": [ 17 | ".moon/workspace.yml" 18 | ] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "watch", 9 | "isBackground": true, 10 | "presentation": { 11 | "reveal": "never", 12 | "group": "watchers" 13 | }, 14 | "group": { 15 | "kind": "build", 16 | "isDefault": true 17 | }, 18 | "options": { 19 | "cwd": "${workspaceRoot}/packages/vscode-extension" 20 | } 21 | } 22 | // { 23 | // "label": "tasks: watch-tests", 24 | // "dependsOn": [ 25 | // "npm: watch", 26 | // "npm: watch-tests" 27 | // ], 28 | // "problemMatcher": [], 29 | // "options": { 30 | // "cwd": "${workspaceRoot}/packages/vscode-extension" 31 | // } 32 | // } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | compressionLevel: mixed 2 | 3 | enableGlobalCache: true 4 | 5 | enableTelemetry: false 6 | 7 | logFilters: 8 | - code: YN0007 9 | level: discard 10 | - code: YN0008 11 | level: discard 12 | - code: YN0013 13 | level: discard 14 | 15 | nodeLinker: node-modules 16 | 17 | yarnPath: .yarn/releases/yarn-4.7.0.cjs 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 moonrepo LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DEPRECATED 2 | 3 | > These packages are deprecated and are loosely maintained. We suggest using the following tools 4 | > instead: [Biome](https://biomejs.dev/) (replaces ESLint + Prettier), [Vitest](https://vitest.dev/) 5 | > (replaces Jest), and [esbuild](https://esbuild.github.io/) (replaces Babel). 6 | 7 | # moon development 8 | 9 | ![build status](https://img.shields.io/github/workflow/status/moonrepo/dev/Pipeline) 10 | ![npm version](https://img.shields.io/npm/v/@moonrepo/dev) 11 | ![npm license](https://img.shields.io/npm/l/@moonrepo/dev) 12 | 13 | This repository is a collection of moon owned and maintained developer tools and shared 14 | configurations/presets for common JavaScript tooling -- primarily tools used by moonrepo and its 15 | authors. 16 | 17 | ## Editor extensions 18 | 19 | This repo houses the official moon VS Code extension, 20 | [moonrepo.moon-console](./packages/vscode-extension)! It is currently under heavy development, but 21 | is in a usable condition. 22 | 23 | ## Shared configurations 24 | 25 | The following packages are not tied to [moon](https://github.com/moonrepo/moon) directly, and can be 26 | used stand-alone within their respective JavaScript tools. 27 | 28 | They aim to provide a strict, modern, developer accessible, convention over configuration approach 29 | to JavaScript, TypeScript (first), and React/Solid projects! All of these configs have been designed 30 | for local and developer tooling based development! 31 | 32 | - [babel-preset-moon](./packages/babel-preset) - Babel preset that utilizes `env`, `typescript`, and 33 | `react` presets. 34 | - [eslint-config-moon](./packages/eslint-config) - ESLint config that extends `airbnb`, `unicorn`, 35 | `react`, and a handful of other plugins. 36 | - [jest-preset-moon](./packages/jest-preset) - Jest preset that utilizes the circus runner, and 37 | provides code coverage. 38 | - [prettier-config-moon](./packages/prettier-config) - Prettier config that aligns with 39 | accessibility and community standards. 40 | - [tsconfig-moon](./packages/tsconfig) - TypeScript configs for normal, react, and reference based 41 | projects. 42 | 43 | And last but not least, the [@moonrepo/dev](./packages/dev) package that provides helpers, constans, 44 | and more. This should rarely be used directly! 45 | 46 | ## FAQ 47 | 48 | ### Can I contribute changes? 49 | 50 | For the VS Code extension, yes! 51 | 52 | For the configs, they're basically personal preference and won't change drastically. You're welcome 53 | to use them as-is, but major changes are unlikely to land. Feel free to create an issue otherwise, 54 | so that we can discuss any intended change. 55 | 56 | ### Why tabs over spaces? 57 | 58 | The JavaScript ecosystem heavily prefers spaces over tabs. However, tabs are more accessible as they 59 | allow developers with vision impairments to control their indentation and improve its readability. 60 | Preferring accessibility compliance over a stylistic choice is always the better option. 61 | 62 | ### How are packages versioned? 63 | 64 | To start, this repo utilizes [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) 65 | for versioning and publishing. We achieve this by requiring a 66 | [specific prefix](https://github.com/beemojs/conventional-changelog-beemo#type) in pull request 67 | titles. With that being said, the versioning strategy is as follows: 68 | 69 | - Patch 70 | - Dependency upgrades. 71 | - Bug fixes. 72 | - Minor 73 | - Enabling or disabling settings or lint rules. 74 | - Adding new dependencies (like babel plugins). 75 | - Adding new features. 76 | - Major 77 | - Node.js minimum requirements / upgrades. 78 | - Major version upgrades for tools (e.g., eslint 7 -> 8). 79 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['moon'], 3 | }; 4 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig, globalIgnores } from 'eslint/config'; 2 | import moonConfig from 'eslint-config-moon'; 3 | import moonNodeConfig from 'eslint-config-moon/node'; 4 | 5 | const config = defineConfig([ 6 | globalIgnores([ 7 | '**/cjs/', 8 | '**/coverage/', 9 | '**/esm/', 10 | '**/lib/', 11 | '**/mjs/', 12 | '**/node_modules/', 13 | '**/*.d.ts', 14 | '**/*.json', 15 | 'packages/eslint-config/*.js', 16 | 'packages/jest-preset/*.js', 17 | ]), 18 | ...moonConfig, 19 | ...moonNodeConfig, 20 | { 21 | rules: { 22 | // Temporarily disabled 23 | 'unicorn/no-empty-file': 'off', 24 | 'unicorn/prefer-module': 'off', 25 | 'unicorn/prefer-node-protocol': 'off', 26 | }, 27 | }, 28 | { 29 | files: ['packages/eslint-config/**/*'], 30 | rules: { 'no-magic-numbers': 'off', 'sort-keys': 'off', 'import/no-default-export': 'off' }, 31 | }, 32 | { 33 | files: ['packages/vscode-extension/**/*'], 34 | rules: { 35 | 'max-classes-per-file': 'off', 36 | 'no-console': 'off', 37 | 'no-nested-ternary': 'off', 38 | 'no-param-reassign': 'off', 39 | // We want to use exhaustive checks 40 | 'default-case': 'off', 41 | // Random version conditionals 42 | 'no-magic-numbers': 'off', 43 | // The `vscode` import isn't real 44 | 'import/no-unresolved': 'off', 45 | // It doesnt like our `@moonrepo/types` package 46 | 'node/no-unpublished-import': 'off', 47 | }, 48 | }, 49 | ]); 50 | 51 | // console.log(config); 52 | 53 | export default config; 54 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'jest-preset-moon', 3 | }; 4 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/lerna/schemas/lerna-schema.json", 3 | "version": "independent", 4 | "npmClient": "yarn", 5 | "command": { 6 | "publish": { 7 | "ignoreChanges": [ 8 | "*.md", 9 | "*.mdx" 10 | ], 11 | "private": false 12 | }, 13 | "version": { 14 | "private": false 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "moon-dev", 4 | "version": "1.0.0", 5 | "scripts": { 6 | "moon": "$(yarn bin moon) --color", 7 | "release": "yarn moon run :build && lerna-release", 8 | "setup": "packemon build-workspace", 9 | "version": "yarn install && git add yarn.lock" 10 | }, 11 | "workspaces": [ 12 | "packages/*" 13 | ], 14 | "devDependencies": { 15 | "@babel/core": "^7.27.1", 16 | "@moonrepo/cli": "^1.36.0", 17 | "@moonrepo/dev": "workspace:*", 18 | "eslint": "^9.27.0", 19 | "jest": "^29.7.0", 20 | "jest-circus": "^29.7.0", 21 | "lerna": "^8.2.2", 22 | "packemon": "^4.1.1", 23 | "prettier": "^3.5.3", 24 | "typescript": "^5.8.3" 25 | }, 26 | "packageManager": "yarn@4.7.0" 27 | } 28 | -------------------------------------------------------------------------------- /packages/babel-preset/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | ### 3.1.2 - 2025-05-21 7 | 8 | #### 📦 Dependencies 9 | 10 | - **[babel]** Update to v7.27. ([70438dc](https://github.com/moonrepo/dev/commit/70438dc)) 11 | 12 | **Note:** Version bump only for package babel-preset-moon 13 | 14 | 15 | 16 | 17 | 18 | ## [3.1.1](https://github.com/moonrepo/dev/compare/babel-preset-moon@3.1.0...babel-preset-moon@3.1.1) (2025-03-31) 19 | 20 | **Note:** Version bump only for package babel-preset-moon 21 | 22 | 23 | 24 | 25 | 26 | ### 3.0.4 - 2024-11-27 27 | 28 | #### 📦 Dependencies 29 | 30 | - **[babel]** Update to v7.25. ([3e0eaf1](https://github.com/moonrepo/dev/commit/3e0eaf1)) 31 | - **[babel]** Update to v7.26. ([052d457](https://github.com/moonrepo/dev/commit/052d457)) 32 | 33 | **Note:** Version bump only for package babel-preset-moon 34 | 35 | ### 3.0.3 - 2024-07-15 36 | 37 | #### 📦 Dependencies 38 | 39 | - **[babel]** Update to v7.24 latest. ([41b9b47](https://github.com/moonrepo/dev/commit/41b9b47)) 40 | 41 | **Note:** Version bump only for package babel-preset-moon 42 | 43 | ## 3.0.2 (2024-05-27) 44 | 45 | - deps(babel): Update to v7.24 latest. ([0dcee1c](https://github.com/moonrepo/dev/commit/0dcee1c)) 46 | 47 | ### 3.0.1 - 2024-04-18 48 | 49 | #### 📦 Dependencies 50 | 51 | - **[babel]** Update to v7.24 latest. ([52f5e53](https://github.com/moonrepo/dev/commit/52f5e53)) 52 | 53 | **Note:** Version bump only for package babel-preset-moon 54 | 55 | # 3.0.0 - 2024-03-25 56 | 57 | #### 💥 Breaking 58 | 59 | - Drop Node v16 support. Require v18.12+. ([b6ca343](https://github.com/moonrepo/dev/commit/b6ca343)) 60 | 61 | #### 📦 Dependencies 62 | 63 | - **[babel]** Update to v7.24. ([4f12f8b](https://github.com/moonrepo/dev/commit/4f12f8b)) 64 | 65 | **Note:** Version bump only for package babel-preset-moon 66 | 67 | ### 2.0.15 - 2024-02-27 68 | 69 | #### 📦 Dependencies 70 | 71 | - **[babel-preset-solid]** Update to v1.8.15. ([955966a](https://github.com/moonrepo/dev/commit/955966a)) 72 | 73 | **Note:** Version bump only for package babel-preset-moon 74 | 75 | ### 2.0.14 - 2024-01-26 76 | 77 | #### 📦 Dependencies 78 | 79 | - **[babel]** Update to v7.23 latest. ([1dcdcaf](https://github.com/moonrepo/dev/commit/1dcdcaf)) 80 | 81 | **Note:** Version bump only for package babel-preset-moon 82 | 83 | ### 2.0.13 - 2023-12-31 84 | 85 | #### 📦 Dependencies 86 | 87 | - **[babel]** Update to v7.23 latest. ([1469fc9](https://github.com/moonrepo/dev/commit/1469fc9)) 88 | 89 | **Note:** Version bump only for package babel-preset-moon 90 | 91 | ### 2.0.12 - 2023-12-12 92 | 93 | #### 📦 Dependencies 94 | 95 | - **[babel]** Update to v7.23 latest. ([b00c171](https://github.com/moonrepo/dev/commit/b00c171)) 96 | 97 | **Note:** Version bump only for package babel-preset-moon 98 | 99 | ### 2.0.11 - 2023-11-20 100 | 101 | #### 📦 Dependencies 102 | 103 | - **[babel]** Update to v7.23 latest. ([f3e9126](https://github.com/moonrepo/dev/commit/f3e9126)) 104 | 105 | **Note:** Version bump only for package babel-preset-moon 106 | 107 | ### 2.0.10 - 2023-10-30 108 | 109 | #### 📦 Dependencies 110 | 111 | - **[babel]** Update to v7.23 latest. ([23870a7](https://github.com/moonrepo/dev/commit/23870a7)) 112 | 113 | **Note:** Version bump only for package babel-preset-moon 114 | 115 | ### 2.0.9 - 2023-09-25 116 | 117 | #### 📦 Dependencies 118 | 119 | - **[babel]** Update to v7.22 latest. ([44eae0f](https://github.com/moonrepo/dev/commit/44eae0f)) 120 | - **[babel]** Update to v7.23. ([1cf203f](https://github.com/moonrepo/dev/commit/1cf203f)) 121 | 122 | **Note:** Version bump only for package babel-preset-moon 123 | 124 | ### 2.0.8 - 2023-09-04 125 | 126 | #### 📦 Dependencies 127 | 128 | - **[babel]** Update to v7.22 latest. ([ede4a42](https://github.com/moonrepo/dev/commit/ede4a42)) 129 | 130 | **Note:** Version bump only for package babel-preset-moon 131 | 132 | ### 2.0.7 - 2023-08-19 133 | 134 | #### 📦 Dependencies 135 | 136 | - **[babel]** Update to v7.22 latest. ([1184a6c](https://github.com/moonrepo/dev/commit/1184a6c)) 137 | 138 | **Note:** Version bump only for package babel-preset-moon 139 | 140 | ### 2.0.6 - 2023-07-31 141 | 142 | #### 📦 Dependencies 143 | 144 | - **[babel]** Update to v7.22 latest. ([c7bf839](https://github.com/moonrepo/dev/commit/c7bf839)) 145 | - **[babel]** Update to v7.22 latest. ([a7535a2](https://github.com/moonrepo/dev/commit/a7535a2)) 146 | 147 | **Note:** Version bump only for package babel-preset-moon 148 | 149 | ### 2.0.5 - 2023-06-13 150 | 151 | #### 📦 Dependencies 152 | 153 | - **[babel]** Update to v7.22 latest. ([3ec4c93](https://github.com/moonrepo/dev/commit/3ec4c93)) 154 | 155 | **Note:** Version bump only for package babel-preset-moon 156 | 157 | ### 2.0.4 - 2023-05-30 158 | 159 | #### 📦 Dependencies 160 | 161 | - **[babel]** Update to v7.22. ([7b82093](https://github.com/moonrepo/dev/commit/7b82093)) 162 | - **[packemon]** Update to v3.1. ([85727f2](https://github.com/moonrepo/dev/commit/85727f2)) 163 | 164 | **Note:** Version bump only for package babel-preset-moon 165 | 166 | ### 2.0.3 - 2023-05-01 167 | 168 | #### 📦 Dependencies 169 | 170 | - **[babel]** Update to v7.21 latest. ([8bee073](https://github.com/moonrepo/dev/commit/8bee073)) 171 | 172 | **Note:** Version bump only for package babel-preset-moon 173 | 174 | ### 2.0.2 - 2023-04-24 175 | 176 | #### 📦 Dependencies 177 | 178 | - **[babel]** Update to v7.21 latest. ([e043357](https://github.com/moonrepo/dev/commit/e043357)) 179 | 180 | **Note:** Version bump only for package babel-preset-moon 181 | 182 | ### 2.0.1 - 2023-03-13 183 | 184 | #### 📦 Dependencies 185 | 186 | - **[babel]** Update to v7.21 latest. ([44338eb](https://github.com/moonrepo/dev/commit/44338eb)) 187 | 188 | **Note:** Version bump only for package babel-preset-moon 189 | 190 | # 2.0.0 - 2023-02-03 191 | 192 | #### 💥 Breaking 193 | 194 | - Drop Node v14 support. Require v16. ([0465f3c](https://github.com/moonrepo/dev/commit/0465f3c)) 195 | 196 | #### 📦 Dependencies 197 | 198 | - **[packemon]** Update to v3. ([79004d2](https://github.com/moonrepo/dev/commit/79004d2)) 199 | 200 | **Note:** Version bump only for package babel-preset-moon 201 | 202 | ### 1.1.4 - 2023-01-31 203 | 204 | #### 📦 Dependencies 205 | 206 | - **[babel]** Update to v7.20 latest. ([4d3f780](https://github.com/moonrepo/dev/commit/4d3f780)) 207 | - **[babel]** Update to v7.20 latest. ([b474be7](https://github.com/moonrepo/dev/commit/b474be7)) 208 | - **[moon]** Update to v0.23. ([f95b29f](https://github.com/moonrepo/dev/commit/f95b29f)) 209 | 210 | **Note:** Version bump only for package babel-preset-moon 211 | 212 | # Change Log 213 | 214 | All notable changes to this project will be documented in this file. See 215 | [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 216 | 217 | ### 1.1.3 - 2022-11-21 218 | 219 | #### 🛠 Internals 220 | 221 | - Improve TypeScript project references. (#20) 222 | ([b9dfb3e](https://github.com/moonrepo/dev/commit/b9dfb3e)), closes 223 | [#20](https://github.com/moonrepo/dev/issues/20) 224 | 225 | **Note:** Version bump only for package babel-preset-moon 226 | 227 | # Change Log 228 | 229 | All notable changes to this project will be documented in this file. See 230 | [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 231 | 232 | ### 1.1.2 - 2022-11-14 233 | 234 | #### 📦 Dependencies 235 | 236 | - **[babel]** Update to v7.20. ([bed56ec](https://github.com/moonrepo/dev/commit/bed56ec)) 237 | 238 | **Note:** Version bump only for package babel-preset-moon 239 | 240 | # Change Log 241 | 242 | All notable changes to this project will be documented in this file. See 243 | [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 244 | 245 | ### 1.1.1 - 2022-10-26 246 | 247 | #### 📦 Dependencies 248 | 249 | - **[babel-preset-solid]** Update to v1.6. 250 | ([2b37f8f](https://github.com/moonrepo/dev/commit/2b37f8f)) 251 | 252 | **Note:** Version bump only for package babel-preset-moon 253 | 254 | # Change Log 255 | 256 | All notable changes to this project will be documented in this file. See 257 | [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 258 | 259 | ## 1.1.0 - 2022-10-16 260 | 261 | #### 🚀 Updates 262 | 263 | - Implement initial VSCode extension infrastructure. (#10) 264 | ([37612f9](https://github.com/moonrepo/dev/commit/37612f9)), closes 265 | [#10](https://github.com/moonrepo/dev/issues/10) 266 | 267 | #### 📦 Dependencies 268 | 269 | - **[babel]** Update to v7.19.3. ([5ce220d](https://github.com/moonrepo/dev/commit/5ce220d)) 270 | 271 | **Note:** Version bump only for package babel-preset-moon 272 | 273 | ### 1.0.2 - 2022-09-22 274 | 275 | #### 📦 Dependencies 276 | 277 | - **[babel]** Update to v7.19.1. ([6e05c50](https://github.com/moonrepo/dev/commit/6e05c50)) 278 | 279 | **Note:** Version bump only for package babel-preset-moon 280 | 281 | ### 1.0.1 - 2022-09-08 282 | 283 | #### 📦 Dependencies 284 | 285 | - **[babel-preset-solid]** Update to v1.5. 286 | ([18c2f80](https://github.com/moonrepo/dev/commit/18c2f80)) 287 | - **[babel]** Update to v7.19. ([d02a76d](https://github.com/moonrepo/dev/commit/d02a76d)) 288 | 289 | **Note:** Version bump only for package babel-preset-moon 290 | 291 | # 1.0.0 - 2022-08-18 292 | 293 | #### 🎉 Release 294 | 295 | - Promote to major. ([c59b5a3](https://github.com/moonrepo/dev/commit/c59b5a3)) 296 | 297 | #### 📦 Dependencies 298 | 299 | - Set to major prerelease versions. ([75aef5b](https://github.com/moonrepo/dev/commit/75aef5b)) 300 | 301 | #### 📘 Docs 302 | 303 | - Reformat readmes. ([9fb70e4](https://github.com/moonrepo/dev/commit/9fb70e4)) 304 | 305 | **Note:** Version bump only for package babel-preset-moon 306 | 307 | # 0.1.0 - 2022-08-17 308 | 309 | #### 🎉 Release 310 | 311 | - Prepare for initial release. (#5) ([e1e00f1](https://github.com/moonrepo/dev/commit/e1e00f1)), 312 | closes [#5](https://github.com/moonrepo/dev/issues/5) 313 | 314 | #### 🚀 Updates 315 | 316 | - Add Solid.js support. (#6) ([e2a5bae](https://github.com/moonrepo/dev/commit/e2a5bae)), closes 317 | [#6](https://github.com/moonrepo/dev/issues/6) 318 | 319 | **Note:** Version bump only for package babel-preset-moon 320 | 321 | ### 0.0.1 - 2022-08-16 322 | 323 | #### 🐞 Fixes 324 | 325 | - Some final polish before beta release. (#2) 326 | ([ea37025](https://github.com/moonrepo/dev/commit/ea37025)), closes 327 | [#2](https://github.com/moonrepo/dev/issues/2) 328 | 329 | #### 📘 Docs 330 | 331 | - Update readmes and rework builds. (#1) 332 | ([408dcb6](https://github.com/moonrepo/dev/commit/408dcb6)), closes 333 | [#1](https://github.com/moonrepo/dev/issues/1) 334 | 335 | **Note:** Version bump only for package babel-preset-moon 336 | -------------------------------------------------------------------------------- /packages/babel-preset/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 moonrepo LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/babel-preset/README.md: -------------------------------------------------------------------------------- 1 | # babel-preset-moon 2 | 3 | ![build status](https://img.shields.io/github/workflow/status/moonrepo/dev/Pipeline) 4 | ![npm version](https://img.shields.io/npm/v/babel-preset-moon) 5 | ![npm license](https://img.shields.io/npm/l/babel-preset-moon) 6 | 7 | A modern Babel preset with built-in TypeScript support. Is designed for unit testing, linting, and 8 | local development only -- it _should not_ be used for web applications or package building (use 9 | [Packemon](https://packemon.dev) instead). 10 | 11 | ```bash 12 | yarn add --dev babel-preset-moon 13 | ``` 14 | 15 | ## Setup 16 | 17 | Add the preset to your root `babel.config.js`. 18 | 19 | ```js 20 | module.exports = { 21 | presets: ['moon'], 22 | }; 23 | ``` 24 | 25 | ## Features 26 | 27 | - Configures the `env` preset for the current Node.js version. 28 | - Enables the `typescript` preset by default. TypeScript everywhere! 29 | - Enables native `async`/`await` and avoids Regenerator. 30 | - Enables `export` default and namespace from syntax. 31 | - Supports the `react` preset and both JSX runtimes. 32 | - Supports the `solid` preset with SSR and hydration. 33 | - Converts `__DEV__`, `__PROD__`, and `__TEST__` to `process.env` checks. 34 | - Wraps `invariant()` in `process.env` conditionals. 35 | 36 | ## Options 37 | 38 | The following options can be passed to the preset. 39 | 40 | - `decorators` (`boolean`) - Enable TypeScript decorators. If true, will toggle Babel into loose 41 | mode. Defaults to `false`. 42 | - `loose` (`boolean`) - Turn on Babel loose mode for all plugins. Defaults to `false`. 43 | - `modules` (`boolean`) - Force transpilation to use ECMA script module syntax. Defaults to `false` 44 | (`auto` modules). 45 | - `react` (`boolean | classic | automatic`) - Enable the React plugin and the defined JSX runtime. 46 | Defaults to `false`. 47 | - `solid` (`boolean | ssr`) - Enable the Solid.js plugin. Hydration is always enabled. 48 | - `targets` (`Record | string[] | string`) - Override the target environment. 49 | Defaults to Node.js `current`. 50 | 51 | ```js 52 | module.exports = { 53 | presets: [['moon', { decorators: true, react: 'automatic' }]], 54 | }; 55 | ``` 56 | -------------------------------------------------------------------------------- /packages/babel-preset/moon.yml: -------------------------------------------------------------------------------- 1 | type: 'library' 2 | -------------------------------------------------------------------------------- /packages/babel-preset/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "babel-preset-moon", 3 | "version": "3.1.2", 4 | "description": "A modern Babel preset for tooling development.", 5 | "keywords": [ 6 | "babel-preset", 7 | "moon", 8 | "node", 9 | "env", 10 | "typescript", 11 | "react" 12 | ], 13 | "main": "./lib/index.js", 14 | "types": "./lib/index.d.ts", 15 | "files": [ 16 | "lib/**/*", 17 | "src/**/*" 18 | ], 19 | "repository": { 20 | "type": "git", 21 | "url": "git@github.com:moonrepo/dev.git", 22 | "directory": "packages/babel-preset" 23 | }, 24 | "author": "Miles Johnson", 25 | "license": "MIT", 26 | "publishConfig": { 27 | "access": "public" 28 | }, 29 | "engines": { 30 | "node": ">=18.12.0" 31 | }, 32 | "peerDependencies": { 33 | "@babel/core": ">=7.0.0" 34 | }, 35 | "dependencies": { 36 | "@babel/plugin-proposal-class-properties": "^7.18.6", 37 | "@babel/plugin-proposal-decorators": "^7.27.1", 38 | "@babel/plugin-proposal-export-default-from": "^7.27.1", 39 | "@babel/plugin-proposal-export-namespace-from": "^7.18.9", 40 | "@babel/plugin-proposal-private-methods": "^7.18.6", 41 | "@babel/preset-env": "^7.27.2", 42 | "@babel/preset-react": "^7.27.1", 43 | "@babel/preset-typescript": "^7.27.1", 44 | "babel-plugin-conditional-invariant": "^4.0.1", 45 | "babel-plugin-env-constants": "^4.0.1", 46 | "babel-preset-solid": "^1.9.6" 47 | }, 48 | "devDependencies": { 49 | "@babel/core": "^7.27.1" 50 | }, 51 | "funding": { 52 | "type": "ko-fi", 53 | "url": "https://ko-fi.com/milesjohnson" 54 | }, 55 | "packemon": { 56 | "format": "lib", 57 | "platform": "node" 58 | }, 59 | "exports": { 60 | "./package.json": "./package.json", 61 | "./*": { 62 | "types": "./lib/*.d.ts", 63 | "default": "./lib/*.js" 64 | }, 65 | ".": { 66 | "types": "./lib/index.d.ts", 67 | "default": "./lib/index.js" 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /packages/babel-preset/src/index.ts: -------------------------------------------------------------------------------- 1 | declare const __DEV__: boolean; 2 | 3 | export type PluginItem = string | [string, object]; 4 | 5 | export interface BabelPresetMoonOptions { 6 | decorators?: boolean; 7 | loose?: boolean; 8 | modules?: boolean; 9 | react?: boolean | 'automatic' | 'classic'; 10 | solid?: boolean | 'ssr'; 11 | targets?: Record | string[] | string; 12 | } 13 | 14 | export default function babelPresetMoon( 15 | api: unknown, 16 | { decorators, loose, modules, react, solid, targets }: BabelPresetMoonOptions = {}, 17 | ) { 18 | let looseMode = loose ?? false; 19 | 20 | const plugins: PluginItem[] = [ 21 | '@babel/plugin-proposal-export-default-from', 22 | '@babel/plugin-transform-export-namespace-from', 23 | 'babel-plugin-conditional-invariant', 24 | 'babel-plugin-env-constants', 25 | ]; 26 | 27 | // When using decorators, we must apply loose to explicit plugins 28 | // https://babeljs.io/docs/en/babel-plugin-proposal-decorators#legacy 29 | if (decorators) { 30 | looseMode = true; 31 | 32 | plugins.unshift( 33 | ['@babel/plugin-proposal-decorators', { legacy: true }], 34 | ['@babel/plugin-transform-class-properties', { loose: true }], 35 | ['@babel/plugin-transform-private-methods', { loose: true }], 36 | ); 37 | } 38 | 39 | const presets: PluginItem[] = [ 40 | [ 41 | '@babel/preset-env', 42 | { 43 | bugfixes: true, 44 | exclude: [ 45 | '@babel/plugin-transform-regenerator', 46 | '@babel/plugin-transform-async-to-generator', 47 | ], 48 | loose: looseMode, 49 | modules: modules ? false : 'auto', 50 | shippedProposals: true, 51 | // Only target node since this is for development 52 | // Revisit in Babel v8: https://babeljs.io/docs/en/options#no-targets 53 | targets: targets ?? { node: 'current' }, 54 | useBuiltIns: false, 55 | }, 56 | ], 57 | ['@babel/preset-typescript', { allowDeclareFields: true }], 58 | ]; 59 | 60 | if (react) { 61 | presets.push([ 62 | '@babel/preset-react', 63 | { 64 | development: __DEV__, 65 | runtime: react === 'automatic' ? 'automatic' : 'classic', 66 | }, 67 | ]); 68 | } 69 | 70 | if (solid) { 71 | presets.push([ 72 | 'babel-preset-solid', 73 | { generate: solid === 'ssr' ? 'ssr' : 'dom', hydratable: true }, 74 | ]); 75 | } 76 | 77 | return { 78 | plugins, 79 | presets, 80 | }; 81 | } 82 | -------------------------------------------------------------------------------- /packages/babel-preset/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.options.json", 3 | "compilerOptions": { 4 | "outDir": "../../.moon/cache/types/packages/babel-preset" 5 | }, 6 | "include": [ 7 | "src/**/*" 8 | ], 9 | "references": [ 10 | { 11 | "path": "./tsconfig.lib.json" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /packages/babel-preset/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.options.json", 3 | "compilerOptions": { 4 | "outDir": "lib", 5 | "rootDir": "src" 6 | }, 7 | "include": [ 8 | "src/**/*" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /packages/dev/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | ### 3.0.2 - 2024-06-09 7 | 8 | #### 🐞 Fixes 9 | 10 | - Fix conventional preset. ([6154a3d](https://github.com/moonrepo/dev/commit/6154a3d)) 11 | 12 | **Note:** Version bump only for package @moonrepo/dev 13 | 14 | ## 3.0.1 (2024-05-27) 15 | 16 | - deps(@typescript-eslint/\*): Update to v7.10. ([82e0a08](https://github.com/moonrepo/dev/commit/82e0a08)) 17 | - deps: Update dev and test dependencies. ([539c15e](https://github.com/moonrepo/dev/commit/539c15e)) 18 | 19 | # 3.0.0 - 2024-03-25 20 | 21 | #### 💥 Breaking 22 | 23 | - Drop Node v16 support. Require v18.12+. ([b6ca343](https://github.com/moonrepo/dev/commit/b6ca343)) 24 | 25 | **Note:** Version bump only for package @moonrepo/dev 26 | 27 | ### 2.0.1 - 2023-05-30 28 | 29 | #### 📦 Dependencies 30 | 31 | - **[packemon]** Update to v3.1. ([85727f2](https://github.com/moonrepo/dev/commit/85727f2)) 32 | 33 | **Note:** Version bump only for package @moonrepo/dev 34 | 35 | # 2.0.0 - 2023-02-03 36 | 37 | #### 💥 Breaking 38 | 39 | - Drop Node v14 support. Require v16. ([0465f3c](https://github.com/moonrepo/dev/commit/0465f3c)) 40 | 41 | #### 📦 Dependencies 42 | 43 | - **[packemon]** Update to v3. ([79004d2](https://github.com/moonrepo/dev/commit/79004d2)) 44 | 45 | **Note:** Version bump only for package @moonrepo/dev 46 | 47 | ### 1.3.1 - 2023-01-31 48 | 49 | #### 📦 Dependencies 50 | 51 | - **[moon]** Update to v0.23. ([f95b29f](https://github.com/moonrepo/dev/commit/f95b29f)) 52 | 53 | **Note:** Version bump only for package @moonrepo/dev 54 | 55 | # Change Log 56 | 57 | All notable changes to this project will be documented in this file. See 58 | [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 59 | 60 | ## 1.3.0 - 2022-11-21 61 | 62 | #### 🚀 Updates 63 | 64 | - Add helper for locating TS projects for ESLint. (#19) 65 | ([1013180](https://github.com/moonrepo/dev/commit/1013180)), closes 66 | [#19](https://github.com/moonrepo/dev/issues/19) 67 | 68 | #### 🛠 Internals 69 | 70 | - Improve TypeScript project references. (#20) 71 | ([b9dfb3e](https://github.com/moonrepo/dev/commit/b9dfb3e)), closes 72 | [#20](https://github.com/moonrepo/dev/issues/20) 73 | 74 | **Note:** Version bump only for package @moonrepo/dev 75 | 76 | # Change Log 77 | 78 | All notable changes to this project will be documented in this file. See 79 | [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 80 | 81 | ## 1.2.0 - 2022-10-26 82 | 83 | #### 🚀 Updates 84 | 85 | - Update rules to use `package.json` in cwd instead of root. (#17) 86 | ([1edc1c1](https://github.com/moonrepo/dev/commit/1edc1c1)), closes 87 | [#17](https://github.com/moonrepo/dev/issues/17) 88 | 89 | **Note:** Version bump only for package @moonrepo/dev 90 | 91 | # Change Log 92 | 93 | All notable changes to this project will be documented in this file. See 94 | [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 95 | 96 | ## 1.1.0 - 2022-10-16 97 | 98 | #### 🚀 Updates 99 | 100 | - Implement initial VSCode extension infrastructure. (#10) 101 | ([37612f9](https://github.com/moonrepo/dev/commit/37612f9)), closes 102 | [#10](https://github.com/moonrepo/dev/issues/10) 103 | 104 | **Note:** Version bump only for package @moonrepo/dev 105 | 106 | # 1.0.0 - 2022-08-18 107 | 108 | #### 🎉 Release 109 | 110 | - Promote to major. ([c59b5a3](https://github.com/moonrepo/dev/commit/c59b5a3)) 111 | 112 | #### 📦 Dependencies 113 | 114 | - Set to major prerelease versions. ([75aef5b](https://github.com/moonrepo/dev/commit/75aef5b)) 115 | 116 | **Note:** Version bump only for package @moonrepo/dev 117 | 118 | # 0.1.0 - 2022-08-17 119 | 120 | #### 🎉 Release 121 | 122 | - Prepare for initial release. (#5) ([e1e00f1](https://github.com/moonrepo/dev/commit/e1e00f1)), 123 | closes [#5](https://github.com/moonrepo/dev/issues/5) 124 | 125 | #### 🚀 Updates 126 | 127 | - Add a basic release script using lerna. (#4) 128 | ([e934001](https://github.com/moonrepo/dev/commit/e934001)), closes 129 | [#4](https://github.com/moonrepo/dev/issues/4) 130 | 131 | **Note:** Version bump only for package @moonrepo/dev 132 | 133 | ### 0.0.2 - 2022-08-16 134 | 135 | #### 🐞 Fixes 136 | 137 | - Add overrides for config files (`*.config.js`). (#3) 138 | ([f2f2070](https://github.com/moonrepo/dev/commit/f2f2070)), closes 139 | [#3](https://github.com/moonrepo/dev/issues/3) 140 | 141 | **Note:** Version bump only for package @moonrepo/dev 142 | 143 | ### 0.0.1 - 2022-08-16 144 | 145 | #### 🐞 Fixes 146 | 147 | - Some final polish before beta release. (#2) 148 | ([ea37025](https://github.com/moonrepo/dev/commit/ea37025)), closes 149 | [#2](https://github.com/moonrepo/dev/issues/2) 150 | 151 | #### 📘 Docs 152 | 153 | - Update readmes and rework builds. (#1) 154 | ([408dcb6](https://github.com/moonrepo/dev/commit/408dcb6)), closes 155 | [#1](https://github.com/moonrepo/dev/issues/1) 156 | 157 | **Note:** Version bump only for package @moonrepo/dev 158 | -------------------------------------------------------------------------------- /packages/dev/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 moonrepo LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/dev/README.md: -------------------------------------------------------------------------------- 1 | # @moonrepo/dev 2 | 3 | ![build status](https://img.shields.io/github/workflow/status/moonrepo/dev/Pipeline) 4 | ![npm version](https://img.shields.io/npm/v/@moonrepo/dev) 5 | ![npm license](https://img.shields.io/npm/l/@moonrepo/dev) 6 | 7 | Reusable constants and helpers for moon configurations. This shouldn't be used directly. 8 | -------------------------------------------------------------------------------- /packages/dev/moon.yml: -------------------------------------------------------------------------------- 1 | type: 'library' 2 | -------------------------------------------------------------------------------- /packages/dev/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@moonrepo/dev", 3 | "version": "3.1.0", 4 | "description": "Reusable constants and helpers for moon configurations.", 5 | "keywords": [ 6 | "moon", 7 | "constants" 8 | ], 9 | "main": "./lib/index.js", 10 | "types": "./lib/index.d.ts", 11 | "bin": { 12 | "lerna-release": "./lib/bin/lernaRelease.js" 13 | }, 14 | "files": [ 15 | "lib/**/*", 16 | "src/**/*" 17 | ], 18 | "repository": { 19 | "type": "git", 20 | "url": "git@github.com:moonrepo/dev.git", 21 | "directory": "packages/dev" 22 | }, 23 | "author": "Miles Johnson", 24 | "license": "MIT", 25 | "publishConfig": { 26 | "access": "public" 27 | }, 28 | "engines": { 29 | "node": ">=18.12.0" 30 | }, 31 | "funding": { 32 | "type": "ko-fi", 33 | "url": "https://ko-fi.com/milesjohnson" 34 | }, 35 | "packemon": { 36 | "format": "lib", 37 | "platform": "node" 38 | }, 39 | "exports": { 40 | "./package.json": "./package.json", 41 | "./*": { 42 | "types": "./lib/*.d.ts", 43 | "default": "./lib/*.js" 44 | }, 45 | ".": { 46 | "types": "./lib/index.d.ts", 47 | "default": "./lib/index.js" 48 | } 49 | }, 50 | "dependencies": { 51 | "conventional-changelog-beemo": "^4.1.1", 52 | "execa": "^5.1.1" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /packages/dev/src/bin/lernaRelease.ts: -------------------------------------------------------------------------------- 1 | import execa from 'execa'; 2 | 3 | if (process.env.GITHUB_TOKEN) { 4 | process.env.GH_TOKEN = process.env.GITHUB_TOKEN; 5 | } 6 | 7 | if (!process.env.GH_TOKEN) { 8 | throw new Error('Release requires a GH_TOKEN environment variable.'); 9 | } 10 | 11 | const changelogPreset = process.env.PRESET ?? 'beemo'; 12 | const graduatePrelease = process.argv.includes('--graduate'); 13 | const preid = graduatePrelease ? '' : process.env.PRERELEASE; 14 | 15 | function runLerna(args: string[]) { 16 | return execa.sync('lerna', args, { 17 | preferLocal: true, 18 | stdio: 'inherit', 19 | }); 20 | } 21 | 22 | // Version packages using conventional commits 23 | // https://github.com/lerna/lerna/tree/master/commands/version#readme 24 | const versionArgs = [ 25 | 'version', 26 | // Only run on master 27 | '--allow-branch', 28 | 'master', 29 | // Create a GitHub release 30 | '--create-release', 31 | 'github', 32 | // Push changes to git 33 | '--push', 34 | // Alter commit message to skip CI 35 | '--message', 36 | 'Release', 37 | // Use conventional commits 38 | '--conventional-commits', 39 | '--changelog-preset', 40 | changelogPreset, 41 | ]; 42 | 43 | if (graduatePrelease) { 44 | versionArgs.push('--conventional-graduate'); 45 | } else if (preid) { 46 | versionArgs.push('--conventional-prerelease', '--preid', preid); 47 | } 48 | 49 | runLerna(versionArgs); 50 | 51 | // Publish packages 52 | const publishArgs = ['publish', 'from-git']; 53 | 54 | if (preid) { 55 | publishArgs.push('--dist-tag', 'next', '--preid', preid); 56 | } 57 | 58 | runLerna(publishArgs); 59 | -------------------------------------------------------------------------------- /packages/dev/src/constants.ts: -------------------------------------------------------------------------------- 1 | export const WORKSPACE_ROOT = process.env.MOON_WORKSPACE_ROOT ?? process.cwd(); 2 | export const PROJECT_ROOT = process.env.MOON_PROJECT_ROOT ?? process.cwd(); 3 | 4 | // Support consistent sorting across the board 5 | // Its off since simple-import-sort doesnt support it! 6 | export const CASE_SENSITIVE = false; 7 | 8 | // Latest ECMA version and syntax to support 9 | export const ECMA_VERSION = 2022; 10 | 11 | // Files and folders to always ignore 12 | export const IGNORE_LIST = [ 13 | 'node_modules/', 14 | 'build/', 15 | 'cjs/', 16 | 'coverage/', 17 | 'dist/', 18 | 'dts/', 19 | 'esm/', 20 | 'lib/', 21 | 'mjs/', 22 | 'umd/', 23 | ]; 24 | 25 | // Supported file extensions 26 | export const EXTENSIONS = ['.ts', '.tsx', '.cts', '.mts', '.js', '.jsx', '.cjs', '.mjs']; 27 | export const EXTENSIONS_WITHOUT_DOT = EXTENSIONS.map((ext) => ext.slice(1)); 28 | export const EXTENSIONS_PATTERN = EXTENSIONS_WITHOUT_DOT.join(','); 29 | 30 | // Globs for finding source files, test files, and test utility files 31 | export const ALL_FILES_GLOB = `**/*.{${EXTENSIONS_PATTERN}}`; 32 | export const SOURCE_FILES_GLOB = `**/src/**/*.{${EXTENSIONS_PATTERN}}`; 33 | export const TEST_FILES_GLOB = `**/{tests,__tests__}/**/*.test.{${EXTENSIONS_PATTERN}}`; 34 | export const TEST_UTILS_GLOB = `**/{tests,__tests__}/**/*.{${EXTENSIONS_PATTERN}}`; 35 | 36 | // List of globs to find all test related files 37 | export const TESTS_LIST = [TEST_FILES_GLOB, TEST_UTILS_GLOB, `**/test.{${EXTENSIONS_PATTERN}}`]; 38 | 39 | // List of globs to find config related files 40 | export const CONFIGS_LIST = [ 41 | `**/.*.{${EXTENSIONS_PATTERN}}`, 42 | `**/*.config.{${EXTENSIONS_PATTERN}}`, 43 | ]; 44 | 45 | // Pattern of file extensions 46 | export const NON_JS_REGEX = String.raw`\.(css|sass|scss|less|gif|png|jpg|jpeg|svg|gql|graphql|yml|yaml)$`; 47 | export const ALL_JS_REGEX = `\\.(${EXTENSIONS_WITHOUT_DOT.join('|')})$`; 48 | 49 | // Pattern to find all custom TypeScript paths 50 | export const TS_PATH_PREFIX_REGEX = '^:[a-z]'; 51 | -------------------------------------------------------------------------------- /packages/dev/src/helpers.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import type { CompilerOptions, ProjectReference } from 'typescript'; 4 | import { PROJECT_ROOT, WORKSPACE_ROOT } from './constants'; 5 | 6 | export function parseJson(filePath: string): T { 7 | const content = fs 8 | .readFileSync(filePath, 'utf8') 9 | .split('\n') 10 | // Remove comments from JSON files 11 | .filter((line) => !/^\s*(#|\/)/.test(line)) 12 | .join('\n'); 13 | 14 | return JSON.parse(content) as T; 15 | } 16 | 17 | export function parseVersion(version: string): number { 18 | return Number.parseFloat(version.replaceAll(/[^\d.]+/g, '')); 19 | } 20 | 21 | // PACKAGE.JSON 22 | 23 | type PackageDeps = Record; 24 | 25 | interface PackageJson { 26 | name: string; 27 | version: string; 28 | engines?: { node?: string }; 29 | dependencies?: PackageDeps; 30 | devDependencies?: PackageDeps; 31 | peerDependencies?: PackageDeps; 32 | } 33 | 34 | const packageJsonCache: Record = {}; 35 | 36 | export function loadPackageJson(file: string): PackageJson | null { 37 | if (!packageJsonCache[file] && fs.existsSync(file)) { 38 | packageJsonCache[file] = parseJson(file); 39 | } 40 | 41 | return packageJsonCache[file] ?? null; 42 | } 43 | 44 | export function getRootPackageJson(): PackageJson { 45 | return loadPackageJson(path.join(WORKSPACE_ROOT, 'package.json'))!; 46 | } 47 | 48 | export function getProjectPackageJson(file?: string): PackageJson | null { 49 | return loadPackageJson(file ?? path.join(PROJECT_ROOT, 'package.json')); 50 | } 51 | 52 | export function getClosestPackageJson(startingDir: string): PackageJson { 53 | const packagePath = path.join(startingDir, 'package.json'); 54 | 55 | if (fs.existsSync(packagePath)) { 56 | return loadPackageJson(packagePath)!; 57 | } 58 | 59 | return getClosestPackageJson(path.dirname(startingDir)); 60 | } 61 | 62 | // NODE.JS 63 | 64 | let nodeVersion: number; 65 | 66 | export function getTargetNodeRuntime(): number { 67 | if (nodeVersion !== undefined) { 68 | return nodeVersion; 69 | } 70 | 71 | try { 72 | const pkg = getRootPackageJson(); 73 | const version = pkg.engines?.node; 74 | 75 | if (version) { 76 | nodeVersion = parseVersion(version); 77 | } 78 | 79 | const nvmrcPath = path.join(WORKSPACE_ROOT, '.nvmrc'); 80 | 81 | if (!nodeVersion && fs.existsSync(nvmrcPath)) { 82 | nodeVersion = parseVersion(fs.readFileSync(nvmrcPath, 'utf8')); 83 | } 84 | } catch { 85 | nodeVersion = 0; 86 | } 87 | 88 | return nodeVersion; 89 | } 90 | 91 | export function getParentNodeRuntime(): number { 92 | const pkg = getClosestPackageJson(process.cwd()); 93 | const version = pkg.engines?.node; 94 | 95 | if (version) { 96 | return parseVersion(version); 97 | } 98 | 99 | return getTargetNodeRuntime(); 100 | } 101 | 102 | // PACKAGES 103 | 104 | export function getPackageVersion(pkgName: string): number { 105 | const pkg = loadPackageJson(require.resolve(`${pkgName}/package.json`)); 106 | 107 | if (pkg) { 108 | return parseVersion(pkg.version); 109 | } 110 | 111 | const rootPackage = getRootPackageJson(); 112 | const version = 113 | rootPackage.dependencies?.[pkgName] ?? 114 | rootPackage.devDependencies?.[pkgName] ?? 115 | rootPackage.peerDependencies?.[pkgName]; 116 | 117 | if (version) { 118 | return parseVersion(version); 119 | } 120 | 121 | return 0; 122 | } 123 | 124 | // TSCONFIG.JSON 125 | 126 | interface TsConfigJson { 127 | compilerOptions?: CompilerOptions; 128 | references?: ProjectReference[]; 129 | } 130 | 131 | const tsconfigJsonCache: Record = {}; 132 | 133 | export function loadTsConfig(file: string): TsConfigJson | null { 134 | if (!tsconfigJsonCache[file] && fs.existsSync(file)) { 135 | tsconfigJsonCache[file] = parseJson(file); 136 | } 137 | 138 | return tsconfigJsonCache[file] ?? null; 139 | } 140 | 141 | export function getRootTsConfig(): TsConfigJson { 142 | return loadTsConfig(path.join(WORKSPACE_ROOT, 'tsconfig.json'))!; 143 | } 144 | 145 | export function getProjectTsConfig(file?: string): TsConfigJson | null { 146 | return loadTsConfig(file ?? path.join(PROJECT_ROOT, 'tsconfig.json')); 147 | } 148 | 149 | export function getClosestTsConfig(startingDir: string): TsConfigJson { 150 | const packagePath = path.join(startingDir, 'tsconfig.json'); 151 | 152 | if (fs.existsSync(packagePath)) { 153 | return loadTsConfig(packagePath)!; 154 | } 155 | 156 | return getClosestTsConfig(path.dirname(startingDir)); 157 | } 158 | 159 | export function getTsProjectForEslint(): string[] { 160 | let dir = process.cwd(); 161 | let tsConfigPath; 162 | 163 | while (dir) { 164 | // Some very large projects will run out of memory when using project references, 165 | // so we support a custom tsconfig for eslint to work around this issue. If found, 166 | // abort early and avoid injesting project references! 167 | const tsConfigEslintPath = path.join(dir, 'tsconfig.eslint.json'); 168 | 169 | if (fs.existsSync(tsConfigEslintPath)) { 170 | return [tsConfigEslintPath]; 171 | } 172 | 173 | // Otherwise, use the normal tsconfig if available 174 | tsConfigPath = path.join(dir, 'tsconfig.json'); 175 | 176 | if (fs.existsSync(tsConfigPath)) { 177 | break; 178 | } 179 | 180 | dir = path.dirname(dir); 181 | } 182 | 183 | // Nothing found? Weird, just assume a config exists in the root... 184 | if (!tsConfigPath) { 185 | tsConfigPath = path.join(WORKSPACE_ROOT, 'tsconfig.json'); 186 | dir = WORKSPACE_ROOT; 187 | } 188 | 189 | // Load the found tsconfig and include any project references 190 | const tsConfig = loadTsConfig(tsConfigPath); 191 | const project = [tsConfigPath]; 192 | 193 | if (tsConfig?.references && tsConfig.references.length > 0) { 194 | project.push( 195 | ...tsConfig.references.map((ref) => 196 | ref.path.endsWith('.json') 197 | ? path.join(dir, ref.path) 198 | : path.join(dir, ref.path, 'tsconfig.json'), 199 | ), 200 | ); 201 | } 202 | 203 | return project; 204 | } 205 | -------------------------------------------------------------------------------- /packages/dev/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './constants'; 2 | export * from './helpers'; 3 | -------------------------------------------------------------------------------- /packages/dev/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.options.json", 3 | "compilerOptions": { 4 | "outDir": "../../.moon/cache/types/packages/dev" 5 | }, 6 | "include": [ 7 | "src/**/*" 8 | ], 9 | "references": [ 10 | { 11 | "path": "./tsconfig.lib.json" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /packages/dev/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.options.json", 3 | "compilerOptions": { 4 | "outDir": "lib", 5 | "rootDir": "src" 6 | }, 7 | "include": [ 8 | "src/**/*" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /packages/eslint-config/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 moonrepo LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/eslint-config/README.md: -------------------------------------------------------------------------------- 1 | # eslint-config-moon 2 | 3 | ![build status](https://img.shields.io/github/workflow/status/moonrepo/dev/Pipeline) 4 | ![npm version](https://img.shields.io/npm/v/eslint-config-moon) 5 | ![npm license](https://img.shields.io/npm/l/eslint-config-moon) 6 | 7 | A modern and strict ESLint configuration with optional presets and first-class TypeScript support. 8 | Expands upon the amazing [Airbnb config](https://www.npmjs.com/package/eslint-config-airbnb-base) to 9 | provide the latest ECMAScript features, enforce popular patterns, and align with the wider 10 | community. 11 | 12 | ```bash 13 | yarn add --dev eslint eslint-config-moon 14 | ``` 15 | 16 | ## Setup 17 | 18 | Extend the `moon` config in your root `.eslintrc.js`. Additional [presets](#presets) are available 19 | for additional rules. 20 | 21 | ```js 22 | module.exports = { 23 | root: true, 24 | extends: ['moon'], 25 | }; 26 | ``` 27 | 28 | ### Presets 29 | 30 | The following additional configs can also be extended, but are not enabled by default. 31 | 32 | - `moon/browser` - Sets the environment to the browser/DOM and enables the 33 | [compat](https://www.npmjs.com/package/eslint-plugin-compat) plugin. Should _not_ be used with the 34 | `node` preset. 35 | - `moon/node` - Sets the environment to Node.js and enables the 36 | [node](https://www.npmjs.com/package/eslint-plugin-node) plugin. Should _not_ be used with the 37 | `browser` preset. 38 | - `moon/react` - Enables the [react](https://www.npmjs.com/package/eslint-plugin-react), 39 | [react-hooks](https://www.npmjs.com/package/eslint-plugin-react-hooks), 40 | [react-perf](https://www.npmjs.com/package/eslint-plugin-react-perf), and 41 | [jsx-a11y](https://www.npmjs.com/package/eslint-plugin-jsx-a11y) plugins. 42 | - Only applies to `*.tsx` files and also extends the `browser` preset. 43 | - Enables automatic JSX runtime if `react` version is 17+. 44 | - `moon/solid` - Enables the [solid](https://www.npmjs.com/package/eslint-plugin-solid) plugin. 45 | - Only applies to `*.tsx` files and also extends the `browser` preset. 46 | 47 | ## Features 48 | 49 | - Extends the [airbnb-base](https://www.npmjs.com/package/eslint-config-airbnb-base) config and 50 | enables additional rules. 51 | - Prefers named exports over default exports. 52 | - Enforces async/await/promise best practices with the 53 | [promise](https://www.npmjs.com/package/eslint-plugin-promise) plugin. 54 | - Sorts imports/exports in a logical way using the 55 | [simple-import-sort](https://www.npmjs.com/package/eslint-plugin-simple-import-sort) plugin. 56 | - Encourages readable tests with the [jest](https://www.npmjs.com/package/eslint-plugin-jest) 57 | plugin. Only applies to [test](#requirements) files. 58 | - Enables additional awesome rules from the 59 | [unicorn](https://www.npmjs.com/package/eslint-plugin-unicorn) plugin. 60 | - Automatically sets `parserOptions.project` based on the root `tsconfig.json`. 61 | - Avoids `any` type and unsafe operations. 62 | - Uses tabs over spaces for accessibility compliance. 63 | 64 | ## Requirements 65 | 66 | - Source files must be located in a `src` folder. 67 | - Tests files must end in `*.test.*` and be located within a `tests` or `__tests__` folder. 68 | - Relies on TypeScript for parsing files. 69 | - Root `package.json` contains a Node.js `engine` for the target runtime. 70 | -------------------------------------------------------------------------------- /packages/eslint-config/moon.yml: -------------------------------------------------------------------------------- 1 | type: 'library' 2 | 3 | dependsOn: 4 | - 'dev' 5 | -------------------------------------------------------------------------------- /packages/eslint-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-config-moon", 3 | "version": "4.0.2", 4 | "description": "A modern and strict ESLint configuration.", 5 | "keywords": [ 6 | "eslint-config", 7 | "airbnb", 8 | "moon", 9 | "react", 10 | "typescript" 11 | ], 12 | "main": "./lib/index.js", 13 | "types": "./lib/index.d.ts", 14 | "files": [ 15 | "*.js", 16 | "lib/**/*", 17 | "src/**/*" 18 | ], 19 | "repository": { 20 | "type": "git", 21 | "url": "git@github.com:moonrepo/dev.git", 22 | "directory": "packages/eslint-config" 23 | }, 24 | "author": "Miles Johnson", 25 | "license": "MIT", 26 | "publishConfig": { 27 | "access": "public" 28 | }, 29 | "engines": { 30 | "node": ">=18.12.0" 31 | }, 32 | "peerDependencies": { 33 | "eslint": "^9.0.0" 34 | }, 35 | "dependencies": { 36 | "@eslint/compat": "^1.2.9", 37 | "@moonrepo/dev": "^3.1.0", 38 | "@typescript-eslint/eslint-plugin": "^8.32.1", 39 | "@typescript-eslint/parser": "^8.32.1", 40 | "eslint-config-airbnb-base": "^15.0.0", 41 | "eslint-config-prettier": "^10.1.5", 42 | "eslint-plugin-compat": "^6.0.2", 43 | "eslint-plugin-import": "^2.31.0", 44 | "eslint-plugin-jest": "^28.11.0", 45 | "eslint-plugin-jsx-a11y": "^6.10.2", 46 | "eslint-plugin-n": "^17.18.0", 47 | "eslint-plugin-promise": "^7.2.1", 48 | "eslint-plugin-react": "^7.37.5", 49 | "eslint-plugin-react-hooks": "^5.2.0", 50 | "eslint-plugin-react-perf": "^3.3.3", 51 | "eslint-plugin-simple-import-sort": "^12.1.1", 52 | "eslint-plugin-solid": "^0.14.5", 53 | "eslint-plugin-unicorn": "^56.0.1", 54 | "globals": "^16.1.0" 55 | }, 56 | "devDependencies": { 57 | "eslint": "^9.27.0" 58 | }, 59 | "funding": { 60 | "type": "ko-fi", 61 | "url": "https://ko-fi.com/milesjohnson" 62 | }, 63 | "packemon": { 64 | "format": "lib", 65 | "platform": "node" 66 | }, 67 | "exports": { 68 | "./package.json": "./package.json", 69 | "./*": { 70 | "types": "./lib/*.d.ts", 71 | "default": "./lib/*.js" 72 | }, 73 | ".": { 74 | "types": "./lib/index.d.ts", 75 | "default": "./lib/index.js" 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /packages/eslint-config/src/async.ts: -------------------------------------------------------------------------------- 1 | import type eslint from 'eslint'; 2 | // @ts-expect-error Not typed 3 | import promisePlugin from 'eslint-plugin-promise'; 4 | 5 | const config: eslint.Linter.Config = { 6 | name: 'moon:async', 7 | // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment 8 | plugins: { promise: promisePlugin }, 9 | rules: { 10 | 'promise/param-names': 'error', 11 | 'promise/valid-params': 'error', 12 | 13 | // Avoid complicated or problematic patterns 14 | 'promise/no-promise-in-callback': 'error', 15 | 'promise/no-new-statics': 'error', 16 | 17 | // Ensure proper control flow 18 | 'promise/catch-or-return': 'error', 19 | 'promise/no-return-wrap': ['error', { allowReject: true }], 20 | 'promise/no-multiple-resolved': 'error', 21 | 'promise/no-nesting': 'error', 22 | 'promise/no-return-in-finally': 'error', 23 | 24 | // Returning isnt always necessary 25 | 'promise/always-return': 'off', 26 | 27 | // Prefer modern APIs 28 | 'promise/no-native': 'off', 29 | 'promise/avoid-new': 'off', 30 | 'promise/prefer-await-to-then': 'error', 31 | 'promise/prefer-await-to-callbacks': 'error', 32 | 33 | // Useful for patching old Node.js APIs 34 | 'promise/no-callback-in-promise': 'off', 35 | }, 36 | }; 37 | 38 | export default [config]; 39 | -------------------------------------------------------------------------------- /packages/eslint-config/src/base.ts: -------------------------------------------------------------------------------- 1 | import type eslint from 'eslint'; 2 | import { CASE_SENSITIVE } from '@moonrepo/dev'; 3 | 4 | // The following rules are either overriding Airbnb's defaults, 5 | // or they are enabling new rules that aren't in Airbnb yet. 6 | const config: eslint.Linter.Config = { 7 | name: 'moon:base', 8 | rules: { 9 | // Use tabs instead of spaces for accessibility 10 | indent: ['error', 'tab'], 11 | 'no-tabs': 'off', 12 | 13 | // Annoying as some class methods are nice to not be static 14 | 'class-methods-use-this': 'off', 15 | 16 | // Encourage breaking up code when applicable 17 | complexity: ['error', 12], 18 | 19 | // Allow either kind of comments (docblocks vs inline) 20 | 'multiline-comment-style': 'off', 21 | 22 | // Always prefer object destructuring, but array is optional 23 | 'prefer-destructuring': [ 24 | 'error', 25 | { 26 | object: true, 27 | array: false, 28 | }, 29 | ], 30 | 31 | // Always sort object members for better readability 32 | 'sort-keys': [ 33 | 'error', 34 | 'asc', 35 | { 36 | caseSensitive: CASE_SENSITIVE, 37 | natural: true, 38 | }, 39 | ], 40 | 41 | // Avoid bad or problematic syntax/patterns 42 | 'no-constant-binary-expression': 'error', 43 | 'no-constant-condition': 'error', 44 | 'no-constructor-return': 'error', 45 | 'no-div-regex': 'error', 46 | 'no-dupe-else-if': 'error', 47 | 'no-empty-static-block': 'error', 48 | 'no-import-assign': 'error', 49 | 'no-native-reassign': 'error', 50 | 'no-new-native-nonconstructor': 'error', 51 | // 'no-promise-executor-return': ['error', { allowVoid: true }], 52 | 'no-promise-executor-return': 'error', 53 | 'no-setter-return': 'error', 54 | 'no-unreachable-loop': 'error', 55 | 'no-unsafe-optional-chaining': ['error', { disallowArithmeticOperators: true }], 56 | 'no-unused-private-class-members': 'error', 57 | 'no-useless-call': 'error', 58 | 'require-atomic-updates': 'error', 59 | 60 | // Prefer compact syntax when applicable 61 | 'logical-assignment-operators': 'error', 62 | 'prefer-exponentiation-operator': 'error', 63 | 'prefer-regex-literals': ['error', { disallowRedundantWrapping: true }], 64 | 65 | // Prefer explicitness for readability 66 | 'no-implicit-coercion': 'error', 67 | 68 | // Encourage reusable constants with descriptive comments 69 | 'no-magic-numbers': [ 70 | 'error', 71 | { 72 | ignore: [-3, -2, -1, 0, 1, 2, 3], 73 | ignoreArrayIndexes: true, 74 | ignoreClassFieldInitialValues: true, 75 | enforceConst: true, 76 | }, 77 | ], 78 | 79 | // Sounds good in practice but is overkill 80 | 'require-unicode-regexp': 'off', 81 | 82 | // Doesnt scope correctly with `this` in arrow functions 83 | 'no-invalid-this': 'off', 84 | 85 | // Allow modern APIs 86 | 'no-restricted-syntax': 'off', 87 | 88 | // Not available on enough platforms yet 89 | 'prefer-object-has-own': 'error', 90 | }, 91 | }; 92 | 93 | export default [config]; 94 | -------------------------------------------------------------------------------- /packages/eslint-config/src/browser.ts: -------------------------------------------------------------------------------- 1 | import type eslint from 'eslint'; 2 | import compatPlugin from 'eslint-plugin-compat'; 3 | import globals from 'globals'; 4 | import { CONFIGS_LIST, TESTS_LIST } from '@moonrepo/dev'; 5 | 6 | const config: eslint.Linter.Config = { 7 | name: 'moon:browser', 8 | languageOptions: { 9 | globals: { 10 | ...globals.browser, 11 | }, 12 | }, 13 | plugins: { compat: compatPlugin }, 14 | rules: { 15 | // Warn about invalid API usage but do not fail the build 16 | 'compat/compat': 'warn', 17 | }, 18 | }; 19 | 20 | export default [ 21 | config, 22 | { 23 | files: [...CONFIGS_LIST, ...TESTS_LIST], 24 | rules: { 25 | // Disable within tests as its noisy 26 | 'compact/compat': 'off', 27 | }, 28 | }, 29 | ]; 30 | -------------------------------------------------------------------------------- /packages/eslint-config/src/index.ts: -------------------------------------------------------------------------------- 1 | import type eslint from 'eslint'; 2 | import prettierConfig from 'eslint-config-prettier'; 3 | import globals from 'globals'; 4 | import { ECMA_VERSION } from '@moonrepo/dev'; 5 | // @ts-expect-error Not typed 6 | // eslint-disable-next-line import/no-unresolved 7 | import * as tsParser from '@typescript-eslint/parser'; 8 | import asyncConfig from './async'; 9 | import baseConfig from './base'; 10 | import moduleConfig from './module'; 11 | import testsConfig from './tests'; 12 | import typescriptConfig from './typescript'; 13 | // import airbnbConfig from 'eslint-config-airbnb-base'; 14 | import unicornConfig from './unicorn'; 15 | // import { fixupConfigRules } from '@eslint/compat'; 16 | 17 | const config: eslint.Linter.Config = { 18 | name: 'moon:root', 19 | languageOptions: { 20 | globals: { 21 | ...globals.browser, 22 | ...globals.node, 23 | __DEV__: 'readonly', 24 | __PROD__: 'readonly', 25 | __TEST__: 'readonly', 26 | }, 27 | // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment 28 | parser: tsParser, 29 | parserOptions: { 30 | sourceType: 'module', 31 | ecmaVersion: ECMA_VERSION, 32 | }, 33 | }, 34 | linterOptions: { 35 | reportUnusedDisableDirectives: true, 36 | }, 37 | }; 38 | 39 | export default [ 40 | // ...fixupConfigRules(airbnbConfig), 41 | config, 42 | ...baseConfig, 43 | ...typescriptConfig, 44 | ...asyncConfig, 45 | ...moduleConfig, 46 | ...unicornConfig, 47 | ...testsConfig, 48 | prettierConfig, 49 | ]; 50 | -------------------------------------------------------------------------------- /packages/eslint-config/src/jest.ts: -------------------------------------------------------------------------------- 1 | import type eslint from 'eslint'; 2 | import jestPlugin from 'eslint-plugin-jest'; 3 | import { EXTENSIONS_PATTERN, TESTS_LIST } from '@moonrepo/dev'; 4 | 5 | const jestConfig: eslint.Linter.Config = { 6 | name: 'moon:jest', 7 | files: TESTS_LIST, 8 | plugins: { jest: jestPlugin }, 9 | rules: { 10 | // Prefer `it` over `test` 11 | 'jest/consistent-test-it': 'error', 12 | 'jest/require-top-level-describe': 'error', 13 | 'jest/valid-describe-callback': 'error', 14 | 'jest/valid-expect': 'error', 15 | 16 | // Ensure we are expecting/asserting correctly 17 | 'jest/expect-expect': 'error', 18 | 'jest/no-conditional-in-test': 'error', 19 | 'jest/no-if': 'off', // deprecated 20 | 'jest/no-standalone-expect': 'error', 21 | 'jest/prefer-expect-resolves': 'error', 22 | 23 | // Ensure our tests are deterministic 24 | 'jest/no-interpolation-in-snapshots': 'error', 25 | 'jest/no-large-snapshots': 'off', 26 | 27 | // Encourage readable titles and descriptions 28 | 'jest/no-identical-title': 'error', 29 | 'jest/prefer-lowercase-title': 'off', 30 | 'jest/valid-title': 'error', 31 | 32 | // Prefer explicit APIs for better readability 33 | 'jest/no-alias-methods': 'error', 34 | 'jest/no-deprecated-functions': 'error', 35 | 'jest/no-duplicate-hooks': 'error', 36 | 'jest/no-jasmine-globals': 'error', 37 | 'jest/no-restricted-matchers': 'off', 38 | 'jest/no-test-prefixes': 'error', 39 | 'jest/prefer-hooks-on-top': 'error', 40 | 'jest/prefer-to-be': 'error', 41 | 'jest/prefer-to-contain': 'error', 42 | 'jest/prefer-to-have-length': 'error', 43 | 'jest/prefer-todo': 'error', 44 | 'jest/require-to-throw-message': 'error', 45 | 46 | // Prefer wrapping instead of mutating test subjects 47 | 'jest/prefer-spy-on': 'error', 48 | 49 | // Prefer async/await/promises over callbacks (duh) 50 | 'jest/no-done-callback': 'error', 51 | 'jest/no-test-return-statement': 'error', 52 | 'jest/valid-expect-in-promise': 'off', 53 | 54 | // Avoid invalid or skipped tests from being on master 55 | 'jest/no-commented-out-tests': 'off', 56 | 'jest/no-disabled-tests': 'error', 57 | 'jest/no-focused-tests': 'error', 58 | 59 | // Use fixtures or helper files instead 60 | 'jest/no-export': 'error', 61 | 'jest/no-mocks-import': 'error', 62 | 63 | // Too abrasive and annoying 64 | 'jest/prefer-expect-assertions': 'off', 65 | 'jest/prefer-snapshot-hint': 'off', 66 | 'jest/prefer-strict-equal': 'off', 67 | 'jest/require-hook': 'off', 68 | 'jest/unbound-method': 'off', 69 | 70 | // Hooks are nice / is shared state an issue? Revisit? 71 | 'jest/no-hooks': 'off', 72 | 73 | // Sometimes we only want to check that its called... Revisit? 74 | 'jest/prefer-called-with': 'off', 75 | 76 | // This is nice for catching and testing errors... Revisit? 77 | 'jest/no-conditional-expect': 'off', 78 | }, 79 | }; 80 | 81 | const miscConfig: eslint.Linter.Config = { 82 | files: [ 83 | '**/{__mocks__,__fixtures__}/**/*', 84 | `**/{tests,__tests__}/**/{helpers,utils,setup}.{${EXTENSIONS_PATTERN}}`, 85 | ], 86 | rules: { 87 | // Allow exports from these files 88 | 'jest/no-export': 'off', 89 | 90 | // Allow composable / factoried unit tests 91 | 'jest/require-top-level-describe': 'off', 92 | }, 93 | }; 94 | 95 | // We only want to apply the Jest plugin and other testing rules 96 | // when inside of a test specific file. Not the entire codebase. 97 | export default [jestConfig, miscConfig]; 98 | -------------------------------------------------------------------------------- /packages/eslint-config/src/module.ts: -------------------------------------------------------------------------------- 1 | import { builtinModules } from 'module'; 2 | import type eslint from 'eslint'; 3 | // @ts-expect-error Not typed 4 | import * as importPlugin from 'eslint-plugin-import'; 5 | import simpleImportSortPlugin from 'eslint-plugin-simple-import-sort'; 6 | import { 7 | CONFIGS_LIST, 8 | EXTENSIONS, 9 | IGNORE_LIST, 10 | NON_JS_REGEX, 11 | TS_PATH_PREFIX_REGEX, 12 | } from '@moonrepo/dev'; 13 | 14 | const config: eslint.Linter.Config = { 15 | name: 'moon:module', 16 | plugins: { 17 | // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment 18 | import: importPlugin, 19 | 'simple-import-sort': simpleImportSortPlugin, 20 | }, 21 | settings: { 22 | 'import/extensions': EXTENSIONS, 23 | 'import/ignore': [...IGNORE_LIST, NON_JS_REGEX], 24 | 'import/resolver': { 25 | node: { 26 | extensions: [...EXTENSIONS, '.json'], 27 | }, 28 | }, 29 | 'import/parsers': { 30 | '@typescript-eslint/parser': EXTENSIONS.slice(0, 4), 31 | }, 32 | }, 33 | // Inherits default import rules from Airbnb config. Will only override differences. 34 | // https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb-base/rules/imports.js 35 | rules: { 36 | // Doesnt play nice with TypeScript 37 | // https://typescript-eslint.io/docs/linting/troubleshooting#eslint-plugin-import 38 | 'import/default': 'off', 39 | 'import/named': 'off', 40 | 'import/namespace': 'off', 41 | 'import/no-cycle': 'off', 42 | 'import/no-deprecated': 'off', 43 | 'import/no-named-as-default': 'off', 44 | 'import/no-named-as-default-member': 'off', 45 | 46 | // Too controversial / abrasive 47 | 'import/max-dependencies': 'off', 48 | 'import/no-namespace': 'off', 49 | 'import/no-relative-parent-imports': 'off', 50 | 51 | // Ensure import paths are succinct as possible 52 | 'import/no-relative-packages': 'error', 53 | 'import/no-useless-path-segments': [ 54 | 'error', 55 | { 56 | noUselessIndex: true, 57 | commonjs: false, 58 | }, 59 | ], 60 | 61 | // Always require an extension for non-JS/TS files 62 | 'import/extensions': [ 63 | 'error', 64 | 'ignorePackages', 65 | { 66 | cjs: 'always', 67 | cts: 'always', 68 | js: 'never', 69 | jsx: 'never', 70 | json: 'always', 71 | mjs: 'always', 72 | mts: 'always', 73 | ts: 'never', 74 | tsx: 'never', 75 | }, 76 | ], 77 | 78 | // Dont resolve custom TS paths, but do others 79 | 'import/no-unresolved': [ 80 | 'error', 81 | { 82 | commonjs: true, 83 | caseSensitiveStrict: true, 84 | ignore: [TS_PATH_PREFIX_REGEX], 85 | }, 86 | ], 87 | 88 | // Prefer modern ESM and MJS code 89 | 'import/no-amd': 'error', 90 | 'import/no-commonjs': [ 91 | 'error', 92 | { 93 | allowRequire: true, 94 | allowConditionalRequire: true, 95 | }, 96 | ], 97 | 'import/no-import-module-exports': 'error', 98 | 99 | // Prefer named exports (over default) as they provide a better experience 100 | 'import/no-anonymous-default-export': 'off', 101 | 'import/no-default-export': 'error', 102 | 'import/no-named-export': 'off', 103 | 'import/prefer-default-export': 'off', 104 | 105 | // Sort imports and exports deterministicly 106 | 'sort-imports': 'off', 107 | 'import/order': 'off', 108 | 'simple-import-sort/exports': 'error', 109 | 'simple-import-sort/imports': [ 110 | 'error', 111 | { 112 | groups: [ 113 | [ 114 | // Side-effects 115 | String.raw`^\u0000`, 116 | // Node built-ins 117 | `^node:`, 118 | `^(${builtinModules.join('|')})$`, 119 | // React/Solid NPM packages 120 | '^react', 121 | '^@react', 122 | '^solid', 123 | // NPM packages 124 | '^[a-z]', 125 | // Scoped NPM packages 126 | '^@[a-z]', 127 | // Aliased modules 128 | '^:[a-z]', 129 | // Parent files 130 | String.raw`^\.\./`, 131 | // Sibling files 132 | String.raw`^\./`, 133 | // Index file 134 | String.raw`^\.$`, 135 | // Everything else 136 | String.raw`\*`, 137 | ], 138 | ], 139 | }, 140 | ], 141 | }, 142 | }; 143 | 144 | export default [ 145 | config, 146 | // Allow default exports from package indexes 147 | { 148 | files: ['**/index.*'], 149 | rules: { 150 | 'import/no-default-export': 'off', 151 | }, 152 | }, 153 | // Config files have different semantics 154 | { 155 | files: CONFIGS_LIST, 156 | rules: { 157 | 'import/no-commonjs': 'off', 158 | }, 159 | }, 160 | ]; 161 | -------------------------------------------------------------------------------- /packages/eslint-config/src/node.ts: -------------------------------------------------------------------------------- 1 | import type eslint from 'eslint'; 2 | import compatPlugin from 'eslint-plugin-compat'; 3 | import nodePlugin from 'eslint-plugin-n'; 4 | import globals from 'globals'; 5 | 6 | const config: eslint.Linter.Config = { 7 | name: 'moon:node', 8 | languageOptions: { 9 | globals: { 10 | ...globals.node, 11 | }, 12 | }, 13 | plugins: { node: nodePlugin, compat: compatPlugin }, 14 | rules: { 15 | // Ensure proper error handling 16 | 'node/no-callback-literal': 'error', 17 | 18 | // Ensure NPM packages are valid and can be published to the target engine 19 | 'node/no-deprecated-api': 'error', 20 | 'node/no-unpublished-bin': 'error', 21 | 'node/no-unpublished-import': 'error', 22 | 'node/no-unsupported-features/es-builtins': 'error', 23 | 'node/no-unsupported-features/node-builtins': 'error', 24 | 'node/shebang': 'error', 25 | 26 | // Prefer exitCode instead of exit as it doesnt abort the script 27 | 'no-process-exit': 'error', 28 | 'node/process-exit-as-throw': 'error', 29 | 30 | // Prefer globals when available 31 | 'node/prefer-global/buffer': 'error', 32 | 'node/prefer-global/console': 'error', 33 | 'node/prefer-global/process': 'error', 34 | 'node/prefer-global/text-decoder': 'error', 35 | 'node/prefer-global/text-encoder': 'error', 36 | 'node/prefer-global/url': 'error', 37 | 'node/prefer-global/url-search-params': 'error', 38 | 39 | // Prefer promises APIs when they are available 40 | 'node/prefer-promises/dns': 'error', 41 | 'node/prefer-promises/fs': 'error', 42 | 43 | // We use TypeScript/ES modules instead 44 | 'node/exports-style': 'off', 45 | 'node/no-exports-assign': 'off', 46 | 'node/no-unsupported-features/es-syntax': 'off', 47 | 48 | // Handled by the import plugin 49 | 'node/file-extension-in-import': 'off', 50 | 'node/no-extraneous-import': 'off', 51 | 'node/no-extraneous-require': 'off', 52 | 'node/no-missing-import': 'off', 53 | 'node/no-missing-require': 'off', 54 | 'node/no-unpublished-require': 'off', 55 | 56 | // This is a common occurrence in node scripts 57 | 'global-require': 'off', 58 | 'import/no-dynamic-require': 'off', 59 | 60 | // May be enabled from the browser/react presets, so explicitly disable 61 | 'compat/compat': 'off', 62 | }, 63 | }; 64 | 65 | export default [config]; 66 | -------------------------------------------------------------------------------- /packages/eslint-config/src/react.ts: -------------------------------------------------------------------------------- 1 | import type eslint from 'eslint'; 2 | // @ts-expect-error Not typed 3 | import jsxA11yPlugin from 'eslint-plugin-jsx-a11y'; 4 | import reactPlugin from 'eslint-plugin-react'; 5 | import reactHooksPlugin from 'eslint-plugin-react-hooks'; 6 | // @ts-expect-error Not typed 7 | import reactPerfPlugin from 'eslint-plugin-react-perf'; 8 | import { CASE_SENSITIVE, getPackageVersion } from '@moonrepo/dev'; 9 | import browserConfig from './browser'; 10 | 11 | const reactVersion = getPackageVersion('react'); 12 | 13 | const reactConfig: eslint.Linter.Config = { 14 | name: 'moon:react', 15 | files: ['**/*.tsx'], 16 | languageOptions: { 17 | parserOptions: { 18 | ecmaFeatures: { 19 | jsx: true, 20 | }, 21 | }, 22 | }, 23 | plugins: { 24 | // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment 25 | 'jsx-a11y': jsxA11yPlugin, 26 | react: reactPlugin, 27 | 'react-hooks': reactHooksPlugin, 28 | // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment 29 | 'react-perf': reactPerfPlugin, 30 | }, 31 | settings: { 32 | react: { 33 | version: 'detect', 34 | }, 35 | linkComponents: ['Link', { name: 'Link', linkAttribute: 'to' }], 36 | }, 37 | rules: { 38 | // Conflicts with CSS-in-JS solutions 39 | 'sort-keys': 'off', 40 | 41 | // Disabled by Prettier: https://github.com/prettier/eslint-config-prettier/blob/main/index.js#L122 42 | // We need to do this since React is an override and these might be re-enabled. 43 | 'react/jsx-child-element-spacing': 'off', 44 | 'react/jsx-closing-bracket-location': 'off', 45 | 'react/jsx-closing-tag-location': 'off', 46 | 'react/jsx-curly-newline': 'off', 47 | 'react/jsx-curly-spacing': 'off', 48 | 'react/jsx-equals-spacing': 'off', 49 | 'react/jsx-first-prop-new-line': 'off', 50 | 'react/jsx-indent': 'off', 51 | 'react/jsx-indent-props': 'off', 52 | 'react/jsx-max-props-per-line': 'off', 53 | 'react/jsx-newline': 'off', 54 | 'react/jsx-one-expression-per-line': 'off', 55 | 'react/jsx-props-no-multi-spaces': 'off', 56 | 'react/jsx-tag-spacing': 'off', 57 | 'react/jsx-wrap-multilines': 'off', 58 | 59 | // Support the new JSX runtime when available 60 | 'react/react-in-jsx-scope': reactVersion >= 17 ? 'off' : 'error', 61 | 'react/jsx-uses-react': reactVersion >= 17 ? 'off' : 'error', 62 | 63 | // Align with the DOM instead, avoid "is" prefix 64 | 'react/boolean-prop-naming': 'off', 65 | 'react/jsx-boolean-value': ['error', 'never'], 66 | 67 | // Destructure to avoid references 68 | 'react/destructuring-assignment': 'error', 69 | 70 | // Display name is inferred from function declarations 71 | 'react/display-name': 'off', 72 | 73 | // Always use function declarations for components 74 | 'react/function-component-definition': [ 75 | 'error', 76 | { 77 | namedComponents: 'function-declaration', 78 | unnamedComponents: 'arrow-function', 79 | }, 80 | ], 81 | 'react/prefer-es6-class': 'off', 82 | 'react/prefer-stateless-function': 'error', 83 | 'react/jsx-pascal-case': ['error', { allowAllCaps: true, allowNamespace: true }], 84 | 85 | // Allow multiple components in a file 86 | 'react/no-multi-comp': 'off', 87 | 88 | // Always self-close when applicable 89 | 'react/self-closing-comp': [ 90 | 'error', 91 | { 92 | component: true, 93 | html: true, 94 | }, 95 | ], 96 | 'react/void-dom-elements-no-children': 'error', 97 | 98 | // Allow component level state 99 | 'react/no-set-state': 'off', 100 | 'react/no-unused-state': 'error', 101 | 102 | // Use alternatives instead of danger 103 | 'react/no-danger': 'error', 104 | 'react/no-danger-with-children': 'error', 105 | 106 | // Avoid deprecated APIs 107 | 'react/no-deprecated': 'error', 108 | 'react/no-find-dom-node': 'error', 109 | 'react/no-is-mounted': 'error', 110 | 'react/no-unsafe': ['error', { checkAliases: true }], 111 | 112 | // Dont restrict prop/element usage (is an app concern) 113 | 'react/forbid-component-props': 'off', 114 | 'react/forbid-dom-props': 'off', 115 | 'react/forbid-elements': 'off', 116 | 'react/no-adjacent-inline-elements': 'off', 117 | 118 | // Dont use prop types since were using TypeScript 119 | 'react/default-props-match-prop-types': 'off', 120 | 'react/forbid-foreign-prop-types': 'off', 121 | 'react/forbid-prop-types': 'off', 122 | 'react/no-unused-prop-types': 'off', 123 | 'react/prefer-exact-props': 'off', 124 | 'react/prefer-read-only-props': 'off', 125 | 'react/prop-types': 'off', 126 | 'react/require-default-props': 'off', 127 | 'react/sort-prop-types': 'off', 128 | 129 | // Avoid bad or problematic patterns 130 | 'react/jsx-uses-vars': 'error', 131 | 'react/no-access-state-in-setstate': 'error', 132 | 'react/no-array-index-key': 'error', 133 | 'react/no-arrow-function-lifecycle': 'error', 134 | 'react/no-children-prop': 'error', 135 | 'react/no-did-mount-set-state': 'error', 136 | 'react/no-did-update-set-state': 'error', 137 | 'react/no-direct-mutation-state': 'error', 138 | 'react/no-namespace': 'error', 139 | 'react/no-redundant-should-component-update': 'error', 140 | 'react/no-render-return-value': 'error', 141 | 'react/no-string-refs': 'error', 142 | 'react/no-this-in-sfc': 'error', 143 | 'react/no-typos': 'error', 144 | 'react/no-unescaped-entities': 'error', 145 | 'react/no-unknown-property': 'error', 146 | 'react/no-unstable-nested-components': 'error', 147 | 'react/no-unused-class-component-methods': 'error', 148 | 'react/no-will-update-set-state': 'error', 149 | 'react/require-optimization': 'off', 150 | 'react/style-prop-object': 'error', 151 | 152 | // Accessibility requirements 153 | 'react/button-has-type': 'error', 154 | 'react/no-invalid-html-attribute': 'error', 155 | 156 | // Security requirements 157 | 'react/jsx-no-script-url': 'error', 158 | 'react/jsx-no-target-blank': 'error', 159 | 160 | // Performance requirements 161 | 'react/jsx-no-constructed-context-values': 'error', 162 | 'react-perf/jsx-no-jsx-as-prop': 'off', 163 | 'react-perf/jsx-no-new-array-as-prop': 'error', 164 | 'react-perf/jsx-no-new-function-as-prop': 'error', 165 | 'react-perf/jsx-no-new-object-as-prop': 'error', 166 | 167 | // Ensure JSX is returned 168 | 'react/require-render-return': 'error', 169 | 170 | // Initialization should happen anywhere 171 | 'react/state-in-constructor': 'off', 172 | 173 | // Enforce consistent JSX spacing and syntax 174 | 'react/jsx-no-comment-textnodes': 'error', 175 | 'react/jsx-no-duplicate-props': 'error', 176 | 'react/jsx-no-undef': 'error', 177 | 'react/jsx-space-before-closing': 'off', 178 | 179 | // Avoid interpolation as much as possible 180 | 'react/jsx-curly-brace-presence': ['error', { props: 'never', children: 'never' }], 181 | 182 | // Allow either extension for JSX code, since some components may return null 183 | 'react/jsx-filename-extension': ['error', { allow: 'as-needed', extensions: ['.tsx'] }], 184 | 185 | // Always use shorthand fragments when applicable 186 | 'react/jsx-fragments': ['error', 'syntax'], 187 | 'react/jsx-no-useless-fragment': 'error', 188 | 189 | // Ensure keys are used correctly 190 | 'react/jsx-key': [ 191 | 'error', 192 | { 193 | checkFragmentShorthand: true, 194 | checkKeyMustBeforeSpread: true, 195 | }, 196 | ], 197 | 198 | // Allow any level of nesting 199 | 'react/jsx-max-depth': 'off', 200 | 201 | // Avoid inline function props 202 | 'react/jsx-no-bind': [ 203 | 'error', 204 | { 205 | ignoreDOMComponents: true, 206 | ignoreRefs: true, 207 | allowArrowFunctions: false, 208 | allowFunctions: false, 209 | allowBind: false, 210 | }, 211 | ], 212 | 213 | // Encourage the use of i18n libraries 214 | 'react/jsx-no-literals': [ 215 | 'error', 216 | { 217 | noStrings: true, 218 | ignoreProps: true, 219 | noAttributeStrings: false, 220 | }, 221 | ], 222 | 223 | // Allow spreading of props since it allows better composition, 224 | // and TypeScript will catch any issues regardless 225 | 'react/jsx-props-no-spreading': 'off', 226 | 227 | // Always sort props for better readability 228 | 'react/jsx-sort-default-props': 'off', // Handled by sort-keys 229 | 'react/jsx-sort-props': [ 230 | 'error', 231 | { 232 | callbacksLast: true, 233 | shorthandFirst: true, 234 | shorthandLast: false, 235 | ignoreCase: !CASE_SENSITIVE, 236 | noSortAlphabetically: false, 237 | reservedFirst: true, 238 | }, 239 | ], 240 | 241 | // Encourage on & handle event naming 242 | 'react/jsx-handler-names': [ 243 | 'error', 244 | { 245 | eventHandlerPrefix: 'handle', 246 | eventHandlerPropPrefix: 'on', 247 | }, 248 | ], 249 | 250 | // Sort component using React instead of TypeScript 251 | '@typescript-eslint/member-ordering': 'off', 252 | 'react/static-property-placement': 'error', 253 | 'react/sort-comp': [ 254 | 'error', 255 | { 256 | order: ['statics', 'properties', 'lifecycle', 'everything-else', 'handlers', 'renderers'], 257 | groups: { 258 | statics: ['propTypes', 'defaultProps'], 259 | properties: [ 260 | '/^(?!on).+$/', 261 | '/^(?!handle).+$/', 262 | '/^(?!render).+$/', 263 | '/^.+Ref$/', 264 | 'state', 265 | ], 266 | lifecycle: [ 267 | 'constructor', 268 | 'getDerivedStateFromProps', 269 | 'componentDidMount', 270 | 'shouldComponentUpdate', 271 | 'getSnapshotBeforeUpdate', 272 | 'componentDidUpdate', 273 | 'componentDidCatch', 274 | 'componentWillUnmount', 275 | ], 276 | handlers: ['/^on.+$/', '/^handle.+$/'], 277 | renderers: ['/^render.+$/', 'render'], 278 | }, 279 | }, 280 | ], 281 | }, 282 | }; 283 | 284 | const hooksConfig: eslint.Linter.Config = { 285 | files: ['**/*.ts', '**/*.tsx'], 286 | plugins: { 'react-hooks': reactHooksPlugin }, 287 | rules: { 288 | 'react-hooks/rules-of-hooks': 'error', 289 | 'react-hooks/exhaustive-deps': 'error', 290 | }, 291 | }; 292 | 293 | const testsConfig: eslint.Linter.Config = { 294 | files: ['**/*.test.tsx'], 295 | rules: { 296 | 'react/jsx-no-bind': 'off', 297 | 'react-perf/jsx-no-new-array-as-prop': 'off', 298 | 'react-perf/jsx-no-new-function-as-prop': 'off', 299 | 'react-perf/jsx-no-new-object-as-prop': 'off', 300 | }, 301 | }; 302 | 303 | // We only want to apply the React plugin and rules 304 | // to TSX files. Not the entire codebase. 305 | export default [ 306 | browserConfig, 307 | // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access 308 | jsxA11yPlugin.flatConfigs.recommended, 309 | reactConfig, 310 | hooksConfig, 311 | testsConfig, 312 | ]; 313 | -------------------------------------------------------------------------------- /packages/eslint-config/src/solid.ts: -------------------------------------------------------------------------------- 1 | import type eslint from 'eslint'; 2 | import solidPlugin from 'eslint-plugin-solid'; 3 | // import { type FixupPluginDefinition,fixupPluginRules } from '@eslint/compat'; 4 | import browserConfig from './browser'; 5 | 6 | const solidConfig: eslint.Linter.Config = { 7 | name: 'moon:solid', 8 | files: ['**/*.ts', '**/*.tsx'], 9 | languageOptions: { 10 | parserOptions: { 11 | ecmaFeatures: { 12 | jsx: true, 13 | }, 14 | }, 15 | }, 16 | }; 17 | 18 | export default [...browserConfig, solidPlugin.configs['flat/typescript'], solidConfig]; 19 | -------------------------------------------------------------------------------- /packages/eslint-config/src/tests.ts: -------------------------------------------------------------------------------- 1 | import type eslint from 'eslint'; 2 | import globals from 'globals'; 3 | import { EXTENSIONS_PATTERN, TESTS_LIST } from '@moonrepo/dev'; 4 | 5 | const testsConfig: eslint.Linter.Config = { 6 | name: 'moon:tests', 7 | files: TESTS_LIST, 8 | languageOptions: { 9 | globals: { 10 | ...globals.node, 11 | ...globals.jest, 12 | ...globals.vitest, 13 | }, 14 | }, 15 | rules: { 16 | // Disable these as it makes writing tests much easier 17 | 'max-classes-per-file': 'off', 18 | 'no-console': 'off', 19 | 'no-magic-numbers': 'off', 20 | 'sort-keys': 'off', 21 | 'promise/prefer-await-to-callbacks': 'off', 22 | '@typescript-eslint/no-empty-function': 'off', 23 | '@typescript-eslint/no-extraneous-class': 'off', 24 | '@typescript-eslint/no-useless-constructor': 'off', 25 | '@typescript-eslint/promise-function-async': 'off', 26 | 27 | // Some imports are dev dependencies 28 | 'import/no-extraneous-dependencies': 'off', 29 | 30 | // Allow `any` in tests for convenience 31 | '@typescript-eslint/no-explicit-any': 'off', 32 | '@typescript-eslint/no-unsafe-argument': 'off', 33 | '@typescript-eslint/no-unsafe-assignment': 'off', 34 | '@typescript-eslint/no-unsafe-call': 'off', 35 | '@typescript-eslint/no-unsafe-member-access': 'off', 36 | '@typescript-eslint/no-unsafe-return': 'off', 37 | 38 | // Allow relative import paths 39 | 'import/no-relative-packages': 'off', 40 | 'node/no-unpublished-import': 'off', 41 | }, 42 | }; 43 | 44 | const miscConfig: eslint.Linter.Config = { 45 | files: [ 46 | '**/{__mocks__,__fixtures__}/**/*', 47 | `**/{tests,__tests__}/**/{helpers,utils,setup}.{${EXTENSIONS_PATTERN}}`, 48 | ], 49 | rules: { 50 | 'import/no-commonjs': 'off', 51 | 52 | // Allow `any` in tests for convenience 53 | '@typescript-eslint/no-explicit-any': 'off', 54 | '@typescript-eslint/no-unsafe-argument': 'off', 55 | '@typescript-eslint/no-unsafe-assignment': 'off', 56 | '@typescript-eslint/no-unsafe-call': 'off', 57 | '@typescript-eslint/no-unsafe-member-access': 'off', 58 | '@typescript-eslint/no-unsafe-return': 'off', 59 | }, 60 | }; 61 | 62 | // We only want to apply the tests plugin and other testing rules 63 | // when inside of a test specific file. Not the entire codebase. 64 | export default [testsConfig, miscConfig]; 65 | -------------------------------------------------------------------------------- /packages/eslint-config/src/unicorn.ts: -------------------------------------------------------------------------------- 1 | import type eslint from 'eslint'; 2 | import unicornPlugin from 'eslint-plugin-unicorn'; 3 | import { CONFIGS_LIST } from '@moonrepo/dev'; 4 | 5 | const config: eslint.Linter.Config = { 6 | name: 'moon:unicorn', 7 | plugins: { unicorn: unicornPlugin }, 8 | rules: { 9 | // Disabled by Prettier: https://github.com/prettier/eslint-config-prettier/blob/main/index.js#L142 10 | // We need to do this as they may be re-enabled based on config extending order. 11 | 'unicorn/empty-brace-spaces': 'off', 12 | 'unicorn/no-nested-ternary': 'off', 13 | 'unicorn/number-literal-case': 'off', 14 | 15 | // Improve readability 16 | 'unicorn/better-regex': 'error', 17 | 'unicorn/escape-case': 'error', 18 | 'unicorn/no-console-spaces': 'error', 19 | 'unicorn/no-empty-file': 'error', 20 | 'unicorn/no-hex-escape': 'error', 21 | 'unicorn/no-negated-condition': 'error', 22 | 'unicorn/no-typeof-undefined': 'error', 23 | 'unicorn/no-unreadable-iife': 'error', 24 | 'unicorn/no-unsafe-regex': 'error', 25 | 'unicorn/no-zero-fractions': 'error', 26 | 'unicorn/prefer-math-min-max': 'error', 27 | 'unicorn/prefer-native-coercion-functions': 'error', 28 | 'unicorn/prefer-string-raw': 'error', 29 | 'unicorn/prefer-structured-clone': 'error', 30 | 'unicorn/prefer-switch': 'error', 31 | 'unicorn/string-content': 'error', 32 | 'unicorn/relative-url-style': ['error', 'always'], 33 | 'unicorn/text-encoding-identifier-case': 'error', 34 | 35 | // Better error handling and implementation 36 | 'unicorn/catch-error-name': 'error', 37 | 'unicorn/custom-error-definition': 'error', 38 | 'unicorn/error-message': 'error', 39 | 'unicorn/no-thenable': 'error', 40 | 'unicorn/no-useless-promise-resolve-reject': 'error', 41 | 'unicorn/prefer-type-error': 'error', 42 | 43 | // Too abrasive / too many false positives 44 | 'unicorn/consistent-destructuring': 'off', 45 | 'unicorn/consistent-function-scoping': 'off', 46 | 'unicorn/no-keyword-prefix': 'off', 47 | 'unicorn/no-unused-properties': 'off', 48 | 'unicorn/prefer-set-has': 'off', 49 | 'unicorn/prevent-abbreviations': 'off', 50 | 'unicorn/template-indent': 'off', 51 | 52 | // Ensure consistent and correct syntax 53 | 'unicorn/consistent-empty-array-spread': 'error', 54 | 'unicorn/new-for-builtins': 'error', 55 | 'unicorn/no-anonymous-default-export': 'error', 56 | 'unicorn/no-await-in-promise-methods': 'error', 57 | 'unicorn/no-instanceof-array': 'error', 58 | 'unicorn/no-invalid-remove-event-listener': 'error', 59 | 'unicorn/no-negation-in-equality-check': 'error', 60 | 'unicorn/no-new-array': 'error', 61 | 'unicorn/no-new-buffer': 'error', 62 | 'unicorn/no-single-promise-in-promise-methods': 'error', 63 | 'unicorn/no-this-assignment': 'error', 64 | 'unicorn/no-useless-spread': 'error', 65 | 'unicorn/no-useless-switch-case': 'error', 66 | 'unicorn/numeric-separators-style': 'error', 67 | 'unicorn/switch-case-braces': ['error', 'avoid'], 68 | 'unicorn/throw-new-error': 'error', 69 | 70 | // Ensure todo's are finished 71 | // 'unicorn/expiring-todo-comments': 'error', 72 | 73 | // Be explicit and avoid edge cases 74 | 'unicorn/explicit-length-check': 'error', 75 | 'unicorn/import-style': 'off', 76 | 'unicorn/no-abusive-eslint-disable': 'error', 77 | 'unicorn/no-array-method-this-argument': 'error', 78 | 'unicorn/no-unnecessary-await': 'error', 79 | 'unicorn/no-useless-fallback-in-spread': 'error', 80 | 'unicorn/no-useless-length-check': 'error', 81 | 'unicorn/no-useless-undefined': 'off', 82 | 'unicorn/prefer-negative-index': 'error', 83 | 'unicorn/prefer-prototype-methods': 'error', 84 | 'unicorn/require-array-join-separator': 'error', 85 | 'unicorn/require-number-to-fixed-digits-argument': 'error', 86 | 'unicorn/require-post-message-target-origin': 'error', 87 | 88 | // Doesnt cover the naming requirements I want 89 | 'unicorn/filename-case': 'off', 90 | 91 | // Use compact code when applicable 92 | 'unicorn/no-array-push-push': 'error', 93 | 'unicorn/no-lonely-if': 'error', 94 | 'unicorn/no-static-only-class': 'error', 95 | 'unicorn/prefer-optional-catch-binding': 'error', 96 | 'unicorn/prefer-ternary': 'error', 97 | 98 | // Allow any API 99 | 'unicorn/no-array-for-each': 'off', 100 | 'unicorn/no-array-reduce': 'off', 101 | 'unicorn/no-for-loop': 'off', 102 | 'unicorn/no-null': 'off', 103 | 'unicorn/prefer-regexp-test': 'off', 104 | 105 | // Prefer default parameter values 106 | 'unicorn/prefer-default-parameters': 'error', 107 | 108 | // Prefer object destructuring 109 | 'unicorn/no-object-as-default-parameter': 'error', 110 | 111 | // Avoid array destructuring 112 | 'unicorn/no-unreadable-array-destructuring': 'error', 113 | 114 | // Better handling of Node.js exit 115 | 'unicorn/no-process-exit': 'error', 116 | 117 | // Prefer modern APIs 118 | 'unicorn/no-document-cookie': 'error', 119 | 'unicorn/prefer-add-event-listener': 'error', 120 | 'unicorn/prefer-array-find': 'error', 121 | 'unicorn/prefer-array-flat': 'error', 122 | 'unicorn/prefer-array-flat-map': 'error', 123 | 'unicorn/prefer-array-index-of': 'error', 124 | 'unicorn/prefer-array-some': 'error', 125 | 'unicorn/prefer-code-point': 'error', 126 | 'unicorn/prefer-date-now': 'error', 127 | 'unicorn/prefer-dom-node-append': 'error', 128 | 'unicorn/prefer-dom-node-dataset': 'error', 129 | 'unicorn/prefer-dom-node-remove': 'error', 130 | 'unicorn/prefer-dom-node-text-content': 'error', 131 | 'unicorn/prefer-includes': 'error', 132 | 'unicorn/prefer-keyboard-event-key': 'error', 133 | 'unicorn/prefer-math-trunc': 'error', 134 | 'unicorn/prefer-modern-dom-apis': 'error', 135 | 'unicorn/prefer-modern-math-apis': 'error', 136 | 'unicorn/prefer-module': 'error', 137 | 'unicorn/prefer-node-protocol': 'error', 138 | 'unicorn/prefer-number-properties': 'error', 139 | 'unicorn/prefer-object-from-entries': 'error', 140 | 'unicorn/prefer-query-selector': 'error', 141 | 'unicorn/prefer-reflect-apply': 'error', 142 | 'unicorn/prefer-set-size': 'error', 143 | 'unicorn/prefer-spread': 'error', 144 | 'unicorn/prefer-string-slice': 'error', 145 | 'unicorn/prefer-string-starts-ends-with': 'error', 146 | 'unicorn/prefer-string-trim-start-end': 'error', 147 | 'unicorn/prefer-top-level-await': 'error', 148 | 149 | // Autofixing is abrasive 150 | 'unicorn/prefer-export-from': 'off', 151 | 152 | // Is caught/handled/conflicts by TypeScript instead 153 | 'unicorn/no-array-callback-reference': 'off', 154 | 'unicorn/prefer-json-parse-buffer': 'off', 155 | 156 | // Not available on enough platforms yet 157 | // TODO: Enable in the future! 158 | 'unicorn/prefer-at': 'error', 159 | 'unicorn/prefer-string-replace-all': 'error', 160 | }, 161 | }; 162 | 163 | const testConfig: eslint.Linter.Config = { 164 | files: CONFIGS_LIST, 165 | rules: { 166 | 'unicorn/prefer-module': 'off', 167 | }, 168 | }; 169 | 170 | export default [config, testConfig]; 171 | -------------------------------------------------------------------------------- /packages/eslint-config/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.options.json", 3 | "compilerOptions": { 4 | "outDir": "../../.moon/cache/types/packages/eslint-config" 5 | }, 6 | "include": [ 7 | "src/**/*" 8 | ], 9 | "references": [ 10 | { 11 | "path": "./tsconfig.lib.json" 12 | }, 13 | { 14 | "path": "../dev" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /packages/eslint-config/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.options.json", 3 | "compilerOptions": { 4 | "outDir": "lib", 5 | "rootDir": "src" 6 | }, 7 | "include": [ 8 | "src/**/*" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /packages/jest-preset/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | ### 3.0.2 - 2024-06-09 7 | 8 | **Note:** Version bump only for package jest-preset-moon 9 | 10 | ## 3.0.1 (2024-05-27) 11 | 12 | **Note:** Version bump only for package jest-preset-moon 13 | 14 | # 3.0.0 - 2024-03-25 15 | 16 | #### 💥 Breaking 17 | 18 | - Drop Node v16 support. Require v18.12+. ([b6ca343](https://github.com/moonrepo/dev/commit/b6ca343)) 19 | 20 | **Note:** Version bump only for package jest-preset-moon 21 | 22 | ### 2.0.8 - 2024-02-27 23 | 24 | #### 📦 Dependencies 25 | 26 | - **[eslint]** Update to v8.57. ([0d91c3d](https://github.com/moonrepo/dev/commit/0d91c3d)) 27 | - **[moon]** Update to v1.22. ([7b3a5c0](https://github.com/moonrepo/dev/commit/7b3a5c0)) 28 | 29 | **Note:** Version bump only for package jest-preset-moon 30 | 31 | ### 2.0.7 - 2023-12-31 32 | 33 | #### 📦 Dependencies 34 | 35 | - **[packemon]** Update to v3.2.3. ([fce59a1](https://github.com/moonrepo/dev/commit/fce59a1)) 36 | 37 | **Note:** Version bump only for package jest-preset-moon 38 | 39 | ### 2.0.6 - 2023-10-30 40 | 41 | #### 📦 Dependencies 42 | 43 | - **[eslint-plugin-jest]** Update to v27.6.0. ([73c2911](https://github.com/moonrepo/dev/commit/73c2911)) 44 | 45 | #### 🛠 Internals 46 | 47 | - Remove dependency. ([7066c93](https://github.com/moonrepo/dev/commit/7066c93)) 48 | 49 | **Note:** Version bump only for package jest-preset-moon 50 | 51 | ### 2.0.5 - 2023-09-25 52 | 53 | #### 📦 Dependencies 54 | 55 | - **[jest]** Update to v29.7. ([6a7c218](https://github.com/moonrepo/dev/commit/6a7c218)) 56 | 57 | **Note:** Version bump only for package jest-preset-moon 58 | 59 | ### 2.0.4 - 2023-09-04 60 | 61 | #### 📦 Dependencies 62 | 63 | - **[jest]** Update to v29.6.4. ([4a33052](https://github.com/moonrepo/dev/commit/4a33052)) 64 | 65 | **Note:** Version bump only for package jest-preset-moon 66 | 67 | ### 2.0.3 - 2023-07-31 68 | 69 | #### 📦 Dependencies 70 | 71 | - **[jest]** Update to v29.6. ([4432677](https://github.com/moonrepo/dev/commit/4432677)) 72 | - **[jest]** Update to v29.6.2. ([48c4fab](https://github.com/moonrepo/dev/commit/48c4fab)) 73 | 74 | **Note:** Version bump only for package jest-preset-moon 75 | 76 | ### 2.0.2 - 2023-05-30 77 | 78 | #### 📦 Dependencies 79 | 80 | - **[packemon]** Update to v3.1. ([85727f2](https://github.com/moonrepo/dev/commit/85727f2)) 81 | 82 | **Note:** Version bump only for package jest-preset-moon 83 | 84 | ### 2.0.1 - 2023-03-13 85 | 86 | #### 📦 Dependencies 87 | 88 | - **[jest]** Update to v29.5. ([de0c00c](https://github.com/moonrepo/dev/commit/de0c00c)) 89 | 90 | **Note:** Version bump only for package jest-preset-moon 91 | 92 | # 2.0.0 - 2023-02-03 93 | 94 | #### 💥 Breaking 95 | 96 | - Drop Node v14 support. Require v16. ([0465f3c](https://github.com/moonrepo/dev/commit/0465f3c)) 97 | 98 | #### 📦 Dependencies 99 | 100 | - **[packemon]** Update to v3. ([79004d2](https://github.com/moonrepo/dev/commit/79004d2)) 101 | 102 | **Note:** Version bump only for package jest-preset-moon 103 | 104 | ### 1.1.4 - 2023-01-31 105 | 106 | #### 📦 Dependencies 107 | 108 | - **[jest]** Update to v27.4. ([0f74a71](https://github.com/moonrepo/dev/commit/0f74a71)) 109 | 110 | **Note:** Version bump only for package jest-preset-moon 111 | 112 | # Change Log 113 | 114 | All notable changes to this project will be documented in this file. See 115 | [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 116 | 117 | ### 1.1.3 - 2022-11-21 118 | 119 | #### 🛠 Internals 120 | 121 | - Improve TypeScript project references. (#20) 122 | ([b9dfb3e](https://github.com/moonrepo/dev/commit/b9dfb3e)), closes 123 | [#20](https://github.com/moonrepo/dev/issues/20) 124 | 125 | **Note:** Version bump only for package jest-preset-moon 126 | 127 | # Change Log 128 | 129 | All notable changes to this project will be documented in this file. See 130 | [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 131 | 132 | ### 1.1.2 - 2022-11-14 133 | 134 | #### 📦 Dependencies 135 | 136 | - **[jest]** Update to v29.3. ([2811fd0](https://github.com/moonrepo/dev/commit/2811fd0)) 137 | 138 | **Note:** Version bump only for package jest-preset-moon 139 | 140 | # Change Log 141 | 142 | All notable changes to this project will be documented in this file. See 143 | [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 144 | 145 | ### 1.1.1 - 2022-10-26 146 | 147 | #### 📦 Dependencies 148 | 149 | - **[jest]** Update to v29.2.2. ([39a80a0](https://github.com/moonrepo/dev/commit/39a80a0)) 150 | 151 | **Note:** Version bump only for package jest-preset-moon 152 | 153 | # Change Log 154 | 155 | All notable changes to this project will be documented in this file. See 156 | [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 157 | 158 | ## 1.1.0 - 2022-10-16 159 | 160 | #### 🚀 Updates 161 | 162 | - Implement initial VSCode extension infrastructure. (#10) 163 | ([37612f9](https://github.com/moonrepo/dev/commit/37612f9)), closes 164 | [#10](https://github.com/moonrepo/dev/issues/10) 165 | 166 | #### 📦 Dependencies 167 | 168 | - **[jest]** Update to v29.2.0. ([bf84c34](https://github.com/moonrepo/dev/commit/bf84c34)) 169 | 170 | **Note:** Version bump only for package jest-preset-moon 171 | 172 | ### 1.0.2 - 2022-09-22 173 | 174 | #### 📦 Dependencies 175 | 176 | - **[jest]** Update to v29.0.3. ([9a7bbf2](https://github.com/moonrepo/dev/commit/9a7bbf2)) 177 | 178 | **Note:** Version bump only for package jest-preset-moon 179 | 180 | ### 1.0.1 - 2022-09-08 181 | 182 | #### 📦 Dependencies 183 | 184 | - **[jest]** Update to v29. ([21036c4](https://github.com/moonrepo/dev/commit/21036c4)) 185 | 186 | **Note:** Version bump only for package jest-preset-moon 187 | 188 | # 1.0.0 - 2022-08-18 189 | 190 | #### 🎉 Release 191 | 192 | - Promote to major. ([c59b5a3](https://github.com/moonrepo/dev/commit/c59b5a3)) 193 | 194 | #### 📦 Dependencies 195 | 196 | - Set to major prerelease versions. ([75aef5b](https://github.com/moonrepo/dev/commit/75aef5b)) 197 | 198 | #### 📘 Docs 199 | 200 | - Reformat readmes. ([9fb70e4](https://github.com/moonrepo/dev/commit/9fb70e4)) 201 | 202 | **Note:** Version bump only for package jest-preset-moon 203 | 204 | # 0.1.0 - 2022-08-17 205 | 206 | #### 🎉 Release 207 | 208 | - Prepare for initial release. (#5) ([e1e00f1](https://github.com/moonrepo/dev/commit/e1e00f1)), 209 | closes [#5](https://github.com/moonrepo/dev/issues/5) 210 | 211 | **Note:** Version bump only for package jest-preset-moon 212 | 213 | ### 0.0.2 - 2022-08-16 214 | 215 | #### 🐞 Fixes 216 | 217 | - Add overrides for config files (`*.config.js`). (#3) 218 | ([f2f2070](https://github.com/moonrepo/dev/commit/f2f2070)), closes 219 | [#3](https://github.com/moonrepo/dev/issues/3) 220 | 221 | #### 📦 Dependencies 222 | 223 | - Update all to latest. ([eb34fff](https://github.com/moonrepo/dev/commit/eb34fff)) 224 | 225 | **Note:** Version bump only for package jest-preset-moon 226 | 227 | ### 0.0.1 - 2022-08-16 228 | 229 | #### 🐞 Fixes 230 | 231 | - Some final polish before beta release. (#2) 232 | ([ea37025](https://github.com/moonrepo/dev/commit/ea37025)), closes 233 | [#2](https://github.com/moonrepo/dev/issues/2) 234 | 235 | #### 📘 Docs 236 | 237 | - Update readmes and rework builds. (#1) 238 | ([408dcb6](https://github.com/moonrepo/dev/commit/408dcb6)), closes 239 | [#1](https://github.com/moonrepo/dev/issues/1) 240 | 241 | **Note:** Version bump only for package jest-preset-moon 242 | -------------------------------------------------------------------------------- /packages/jest-preset/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 moonrepo LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/jest-preset/README.md: -------------------------------------------------------------------------------- 1 | # jest-preset-moon 2 | 3 | ![build status](https://img.shields.io/github/workflow/status/moonrepo/dev/Pipeline) 4 | ![npm version](https://img.shields.io/npm/v/jest-preset-moon) 5 | ![npm license](https://img.shields.io/npm/l/jest-preset-moon) 6 | 7 | A modern Jest preset that provides code coverage and performance out of the box. 8 | 9 | ```bash 10 | yarn add --dev jest-preset-moon 11 | ``` 12 | 13 | ## Setup 14 | 15 | Add the preset to your root `jest.config.js`. 16 | 17 | ```js 18 | module.exports = { 19 | preset: 'jest-preset-moon', 20 | }; 21 | ``` 22 | 23 | ## Features 24 | 25 | - Configured for Node.js environments by default. 26 | - Defines an empty file mock for non-JS/TS files (like CSS). 27 | - Requires 90% code coverage of all source files. 28 | - Improved performance through the Jest Circus runner. 29 | - Supports `__DEV__`, `__PROD__`, and `__TEST__` globals. 30 | 31 | ## Requirements 32 | 33 | - Source files must be located in a `src` folder. 34 | - Tests files must end in `*.test.*` and be located within a `tests` or `__tests__` folder. 35 | - Includes a setup file at `/tests/setup.ts` (if exists). 36 | - Relies on Babel, the TypeScript plugin, and the default `babel-jest` package. 37 | -------------------------------------------------------------------------------- /packages/jest-preset/jest-preset.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/no-commonjs 2 | module.exports = require('./lib'); 3 | -------------------------------------------------------------------------------- /packages/jest-preset/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'jest-preset-moon', 3 | }; 4 | -------------------------------------------------------------------------------- /packages/jest-preset/moon.yml: -------------------------------------------------------------------------------- 1 | type: 'library' 2 | 3 | dependsOn: 4 | - 'dev' 5 | 6 | tasks: 7 | test: 8 | args: 9 | - '--no-coverage' 10 | -------------------------------------------------------------------------------- /packages/jest-preset/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jest-preset-moon", 3 | "version": "3.1.0", 4 | "description": "A modern Jest preset for tooling development.", 5 | "keywords": [ 6 | "jest-preset", 7 | "moon" 8 | ], 9 | "main": "./lib/index.js", 10 | "types": "./lib/index.d.ts", 11 | "files": [ 12 | "jest-preset.js", 13 | "lib/**/*", 14 | "src/**/*" 15 | ], 16 | "repository": { 17 | "type": "git", 18 | "url": "git@github.com:moonrepo/dev.git", 19 | "directory": "packages/jest-preset" 20 | }, 21 | "author": "Miles Johnson", 22 | "license": "MIT", 23 | "publishConfig": { 24 | "access": "public" 25 | }, 26 | "engines": { 27 | "node": ">=18.12.0" 28 | }, 29 | "peerDependencies": { 30 | "jest": ">=26.0.0" 31 | }, 32 | "dependencies": { 33 | "@moonrepo/dev": "^3.1.0", 34 | "@types/jest": "^29.5.12", 35 | "jest-circus": "^29.7.0", 36 | "jest-environment-jsdom": "^29.7.0" 37 | }, 38 | "devDependencies": { 39 | "jest": "^29.7.0" 40 | }, 41 | "funding": { 42 | "type": "ko-fi", 43 | "url": "https://ko-fi.com/milesjohnson" 44 | }, 45 | "packemon": { 46 | "inputs": { 47 | "index": "src/index.ts", 48 | "fileMock": "src/fileMock.ts" 49 | }, 50 | "format": "lib", 51 | "platform": "node" 52 | }, 53 | "exports": { 54 | "./package.json": "./package.json", 55 | "./jest-preset": "./lib/index.js", 56 | "./*": { 57 | "types": "./lib/*.d.ts", 58 | "default": "./lib/*.js" 59 | }, 60 | ".": { 61 | "types": "./lib/index.d.ts", 62 | "default": "./lib/index.js" 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /packages/jest-preset/src/fileMock.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/no-default-export 2 | export default ''; 3 | -------------------------------------------------------------------------------- /packages/jest-preset/src/index.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { 4 | ALL_FILES_GLOB, 5 | ALL_JS_REGEX, 6 | EXTENSIONS_WITHOUT_DOT, 7 | IGNORE_LIST, 8 | NON_JS_REGEX, 9 | TEST_FILES_GLOB, 10 | WORKSPACE_ROOT, 11 | } from '@moonrepo/dev'; 12 | 13 | const setupFilesAfterEnv: string[] = []; 14 | const setupFilePath = path.join(WORKSPACE_ROOT, 'tests/setup.ts'); 15 | 16 | // Only include the file if it exists, otherwise Jest throws an error 17 | if (fs.existsSync(setupFilePath)) { 18 | setupFilesAfterEnv.push(setupFilePath); 19 | } 20 | 21 | const config = { 22 | collectCoverage: false, // Enabled by consumers 23 | collectCoverageFrom: [ALL_FILES_GLOB], 24 | coverageDirectory: './coverage', 25 | coveragePathIgnorePatterns: [...IGNORE_LIST], 26 | coverageReporters: ['lcov', 'text-summary'], 27 | coverageThreshold: { 28 | global: { 29 | branches: 80, 30 | functions: 90, 31 | lines: 90, 32 | statements: 90, 33 | }, 34 | }, 35 | globals: { 36 | __DEV__: true, 37 | __PROD__: true, 38 | __TEST__: true, 39 | }, 40 | moduleFileExtensions: [...EXTENSIONS_WITHOUT_DOT, 'json', 'node'], 41 | moduleNameMapper: { 42 | [NON_JS_REGEX]: require.resolve('./fileMock.js'), 43 | }, 44 | setupFilesAfterEnv, 45 | testEnvironment: 'node', 46 | testMatch: [TEST_FILES_GLOB], 47 | testRunner: 'jest-circus/runner', 48 | transform: { 49 | // Support all the new file extensions 50 | [ALL_JS_REGEX]: ['babel-jest', { rootMode: 'upward' }], 51 | }, 52 | }; 53 | 54 | export default config; 55 | -------------------------------------------------------------------------------- /packages/jest-preset/tests/jest.test.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | 3 | describe('jest', () => { 4 | it('passes', () => { 5 | expect(true).toBe(true); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /packages/jest-preset/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.options.json", 3 | "compilerOptions": { 4 | "outDir": "../../.moon/cache/types/packages/jest-preset" 5 | }, 6 | "include": [ 7 | "src/**/*", 8 | "tests/**/*", 9 | "jest.config.js", 10 | "jest-preset.js" 11 | ], 12 | "references": [ 13 | { 14 | "path": "./tsconfig.lib.json" 15 | }, 16 | { 17 | "path": "../dev" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/jest-preset/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.options.json", 3 | "compilerOptions": { 4 | "outDir": "lib", 5 | "rootDir": "src" 6 | }, 7 | "include": [ 8 | "src/**/*" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /packages/prettier-config/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | ### 1.1.2 - 2023-03-13 7 | 8 | #### 📦 Dependencies 9 | 10 | - **[moon]** Update to v0.25. (#31) ([e71e605](https://github.com/moonrepo/dev/commit/e71e605)), closes [#31](https://github.com/moonrepo/dev/issues/31) 11 | 12 | **Note:** Version bump only for package prettier-config-moon 13 | 14 | # Change Log 15 | 16 | All notable changes to this project will be documented in this file. See 17 | [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 18 | 19 | ### 1.1.1 - 2022-11-29 20 | 21 | #### 📦 Dependencies 22 | 23 | - **[moon]** Update to v0.20. ([3dbbbc0](https://github.com/moonrepo/dev/commit/3dbbbc0)) 24 | 25 | **Note:** Version bump only for package prettier-config-moon 26 | 27 | # Change Log 28 | 29 | All notable changes to this project will be documented in this file. See 30 | [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 31 | 32 | ## 1.1.0 - 2022-10-16 33 | 34 | #### 🚀 Updates 35 | 36 | - Implement initial VSCode extension infrastructure. (#10) 37 | ([37612f9](https://github.com/moonrepo/dev/commit/37612f9)), closes 38 | [#10](https://github.com/moonrepo/dev/issues/10) 39 | 40 | #### 🛠 Internals 41 | 42 | - Update prettier ignore rules. ([aee403e](https://github.com/moonrepo/dev/commit/aee403e)) 43 | 44 | **Note:** Version bump only for package prettier-config-moon 45 | 46 | ### 1.0.1 - 2022-09-08 47 | 48 | #### 📦 Dependencies 49 | 50 | - **[moon]** Update to v0.13. ([125d3d3](https://github.com/moonrepo/dev/commit/125d3d3)) 51 | 52 | **Note:** Version bump only for package prettier-config-moon 53 | 54 | # 1.0.0 - 2022-08-18 55 | 56 | #### 🎉 Release 57 | 58 | - Prepare for initial release. (#5) ([e1e00f1](https://github.com/moonrepo/dev/commit/e1e00f1)), 59 | closes [#5](https://github.com/moonrepo/dev/issues/5) 60 | - Promote to major. ([c59b5a3](https://github.com/moonrepo/dev/commit/c59b5a3)) 61 | 62 | #### 🚀 Updates 63 | 64 | - Add markdown files to the no-tabs list. 65 | ([02ee1fd](https://github.com/moonrepo/dev/commit/02ee1fd)) 66 | 67 | #### 📦 Dependencies 68 | 69 | - Set to major prerelease versions. ([75aef5b](https://github.com/moonrepo/dev/commit/75aef5b)) 70 | 71 | **Note:** Version bump only for package prettier-config-moon 72 | 73 | ### 0.0.1 - 2022-08-16 74 | 75 | #### 🐞 Fixes 76 | 77 | - Some final polish before beta release. (#2) 78 | ([ea37025](https://github.com/moonrepo/dev/commit/ea37025)), closes 79 | [#2](https://github.com/moonrepo/dev/issues/2) 80 | 81 | #### 📘 Docs 82 | 83 | - Update readmes and rework builds. (#1) 84 | ([408dcb6](https://github.com/moonrepo/dev/commit/408dcb6)), closes 85 | [#1](https://github.com/moonrepo/dev/issues/1) 86 | 87 | **Note:** Version bump only for package prettier-config-moon 88 | -------------------------------------------------------------------------------- /packages/prettier-config/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 moonrepo LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/prettier-config/README.md: -------------------------------------------------------------------------------- 1 | # prettier-config-moon 2 | 3 | ![build status](https://img.shields.io/github/workflow/status/moonrepo/dev/Pipeline) 4 | ![npm version](https://img.shields.io/npm/v/prettier-config-moon) 5 | ![npm license](https://img.shields.io/npm/l/prettier-config-moon) 6 | 7 | A modern and accessibility forward Prettier config that aligns with the community. 8 | 9 | ```bash 10 | yarn add --dev prettier-config-moon 11 | ``` 12 | 13 | ## Setup 14 | 15 | Extend the config from your root `prettier.config.js` or `.prettierrc.js`. 16 | 17 | ```js 18 | module.exports = 'prettier-config-moon'; 19 | ``` 20 | 21 | ## Features 22 | 23 | - Uses tabs over spaces for accessibility compliance. 24 | - Displays arrow parenthesis and trailing commas. 25 | - Includes semi colons and avoids ASI. 26 | - Prefers single quoted strongs and spaces for indentation. 27 | -------------------------------------------------------------------------------- /packages/prettier-config/moon.yml: -------------------------------------------------------------------------------- 1 | type: 'library' 2 | 3 | toolchain: 4 | typescript: false 5 | 6 | workspace: 7 | inheritedTasks: 8 | exclude: ['build', 'typecheck'] 9 | -------------------------------------------------------------------------------- /packages/prettier-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "prettier-config-moon", 3 | "version": "1.2.0", 4 | "description": "Strict Prettier config with a focus on accessibility.", 5 | "keywords": [ 6 | "prettier", 7 | "config", 8 | "moon" 9 | ], 10 | "main": "./prettier.json", 11 | "files": [ 12 | "prettier.json" 13 | ], 14 | "repository": { 15 | "type": "git", 16 | "url": "git@github.com:moonrepo/dev.git", 17 | "directory": "packages/prettier-config" 18 | }, 19 | "author": "Miles Johnson", 20 | "license": "MIT", 21 | "publishConfig": { 22 | "access": "public" 23 | }, 24 | "funding": { 25 | "type": "ko-fi", 26 | "url": "https://ko-fi.com/milesjohnson" 27 | }, 28 | "release": "1660800474149" 29 | } 30 | -------------------------------------------------------------------------------- /packages/prettier-config/prettier.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/prettierrc", 3 | "arrowParens": "always", 4 | "bracketSameLine": false, 5 | "bracketSpacing": true, 6 | "embeddedLanguageFormatting": "auto", 7 | "endOfLine": "lf", 8 | "printWidth": 100, 9 | "proseWrap": "always", 10 | "semi": true, 11 | "singleAttributePerLine": false, 12 | "singleQuote": true, 13 | "tabWidth": 2, 14 | "trailingComma": "all", 15 | "useTabs": true, 16 | "overrides": [ 17 | { 18 | "files": [ 19 | "*.json", 20 | "*.yml", 21 | "*.yaml", 22 | "*.md", 23 | "*.mdx" 24 | ], 25 | "options": { 26 | "useTabs": false 27 | } 28 | }, 29 | { 30 | "files": [ 31 | "*.json" 32 | ], 33 | "options": { 34 | "parser": "json-stringify" 35 | } 36 | } 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /packages/tsconfig/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | ## 1.3.0 - 2023-03-26 7 | 8 | #### 🚀 Updates 9 | 10 | - Enable `verbatimModuleSyntax` option. ([746d3f5](https://github.com/moonrepo/dev/commit/746d3f5)) 11 | 12 | **Note:** Version bump only for package tsconfig-moon 13 | 14 | ### 1.2.2 - 2023-03-13 15 | 16 | #### 📦 Dependencies 17 | 18 | - **[moon]** Update to v0.25. (#31) ([e71e605](https://github.com/moonrepo/dev/commit/e71e605)), closes [#31](https://github.com/moonrepo/dev/issues/31) 19 | 20 | **Note:** Version bump only for package tsconfig-moon 21 | 22 | # Change Log 23 | 24 | All notable changes to this project will be documented in this file. See 25 | [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 26 | 27 | ### 1.2.1 - 2022-11-29 28 | 29 | #### 📦 Dependencies 30 | 31 | - **[moon]** Update to v0.20. ([3dbbbc0](https://github.com/moonrepo/dev/commit/3dbbbc0)) 32 | 33 | **Note:** Version bump only for package tsconfig-moon 34 | 35 | # Change Log 36 | 37 | All notable changes to this project will be documented in this file. See 38 | [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 39 | 40 | ## 1.2.0 - 2022-11-21 41 | 42 | #### 🚀 Updates 43 | 44 | - Enable `incremental` compiler option. ([998d878](https://github.com/moonrepo/dev/commit/998d878)) 45 | 46 | **Note:** Version bump only for package tsconfig-moon 47 | 48 | # Change Log 49 | 50 | All notable changes to this project will be documented in this file. See 51 | [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 52 | 53 | ## 1.1.0 - 2022-10-16 54 | 55 | #### 🚀 Updates 56 | 57 | - Implement initial VSCode extension infrastructure. (#10) 58 | ([37612f9](https://github.com/moonrepo/dev/commit/37612f9)), closes 59 | [#10](https://github.com/moonrepo/dev/issues/10) 60 | 61 | #### 🛠 Internals 62 | 63 | - Update prettier ignore rules. ([aee403e](https://github.com/moonrepo/dev/commit/aee403e)) 64 | 65 | **Note:** Version bump only for package tsconfig-moon 66 | 67 | ### 1.0.1 - 2022-09-08 68 | 69 | #### 📦 Dependencies 70 | 71 | - **[moon]** Update to v0.13. ([125d3d3](https://github.com/moonrepo/dev/commit/125d3d3)) 72 | 73 | **Note:** Version bump only for package tsconfig-moon 74 | 75 | # 1.0.0 - 2022-08-18 76 | 77 | #### 🎉 Release 78 | 79 | - Promote to major. ([c59b5a3](https://github.com/moonrepo/dev/commit/c59b5a3)) 80 | 81 | #### 📦 Dependencies 82 | 83 | - Set to major prerelease versions. ([75aef5b](https://github.com/moonrepo/dev/commit/75aef5b)) 84 | 85 | #### 📘 Docs 86 | 87 | - Reformat readmes. ([9fb70e4](https://github.com/moonrepo/dev/commit/9fb70e4)) 88 | 89 | **Note:** Version bump only for package tsconfig-moon 90 | 91 | # 0.1.0 - 2022-08-17 92 | 93 | #### 🎉 Release 94 | 95 | - Prepare for initial release. (#5) ([e1e00f1](https://github.com/moonrepo/dev/commit/e1e00f1)), 96 | closes [#5](https://github.com/moonrepo/dev/issues/5) 97 | 98 | #### 🚀 Updates 99 | 100 | - Add Solid.js support. (#6) ([e2a5bae](https://github.com/moonrepo/dev/commit/e2a5bae)), closes 101 | [#6](https://github.com/moonrepo/dev/issues/6) 102 | 103 | **Note:** Version bump only for package tsconfig-moon 104 | 105 | ### 0.0.1 - 2022-08-16 106 | 107 | #### 🐞 Fixes 108 | 109 | - Some final polish before beta release. (#2) 110 | ([ea37025](https://github.com/moonrepo/dev/commit/ea37025)), closes 111 | [#2](https://github.com/moonrepo/dev/issues/2) 112 | 113 | #### 📘 Docs 114 | 115 | - Update readmes and rework builds. (#1) 116 | ([408dcb6](https://github.com/moonrepo/dev/commit/408dcb6)), closes 117 | [#1](https://github.com/moonrepo/dev/issues/1) 118 | 119 | **Note:** Version bump only for package tsconfig-moon 120 | -------------------------------------------------------------------------------- /packages/tsconfig/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 moonrepo LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/tsconfig/README.md: -------------------------------------------------------------------------------- 1 | # tsconfig-moon 2 | 3 | ![build status](https://img.shields.io/github/workflow/status/moonrepo/dev/Pipeline) 4 | ![npm version](https://img.shields.io/npm/v/tsconfig-moon) 5 | ![npm license](https://img.shields.io/npm/l/tsconfig-moon) 6 | 7 | Pre-packaged, strict, and modern TypeScript `tsconfig.json`s. Each config assumes that TypeScript 8 | will _only_ be used as a type checker and _not_ a compiler. 9 | 10 | ```bash 11 | yarn add --dev tsconfig-moon 12 | ``` 13 | 14 | ## Setup 15 | 16 | Extend the config from your root `tsconfig.json`. 17 | 18 | ```json 19 | { 20 | "extends": "tsconfig-moon/tsconfig.json", 21 | "include": ["src/**/*"] 22 | } 23 | ``` 24 | 25 | > Configs only define `compilerOptions` and not `include`, `exclude`, `references`, etc. 26 | 27 | ## Features 28 | 29 | - First-class support for ECMAScript modules and their syntax. 30 | - Supports synthetic default exports. 31 | - Enables ES interoperability and isolation. 32 | - Enables the `esnext` lib. 33 | - Targets `es2022` (since we only type check). 34 | - Supports project references through the `tsconfig.projects.json` config. 35 | - Enables declaration emitting. 36 | - Enables incremental compilation. 37 | - Supports React through the `tsconfig.react.json` config. 38 | - Enables the `dom` lib. 39 | - Sets JSX transform to `react`. 40 | - Supports Solid.js through the `tsconfig.solid.json` config. 41 | - Strict and performant by default (of course). 42 | - Does _not_ check JavaScript files. 43 | -------------------------------------------------------------------------------- /packages/tsconfig/moon.yml: -------------------------------------------------------------------------------- 1 | type: 'library' 2 | 3 | toolchain: 4 | typescript: false 5 | 6 | workspace: 7 | inheritedTasks: 8 | exclude: ['build', 'typecheck'] 9 | -------------------------------------------------------------------------------- /packages/tsconfig/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tsconfig-moon", 3 | "version": "1.4.0", 4 | "description": "Strict tsconfig.json's for modern projects.", 5 | "keywords": [ 6 | "typescript", 7 | "tsconfig", 8 | "moon", 9 | "react", 10 | "solid", 11 | "project refs" 12 | ], 13 | "files": [ 14 | "tsconfig.json", 15 | "tsconfig.react.json", 16 | "tsconfig.solid.json", 17 | "tsconfig.projects.json" 18 | ], 19 | "repository": { 20 | "type": "git", 21 | "url": "git@github.com:moonrepo/dev.git", 22 | "directory": "packages/tsconfig" 23 | }, 24 | "author": "Miles Johnson", 25 | "license": "MIT", 26 | "publishConfig": { 27 | "access": "public" 28 | }, 29 | "funding": { 30 | "type": "ko-fi", 31 | "url": "https://ko-fi.com/milesjohnson" 32 | }, 33 | "release": "1660800474149" 34 | } 35 | -------------------------------------------------------------------------------- /packages/tsconfig/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "compilerOptions": { 4 | "allowJs": false, 5 | "allowSyntheticDefaultImports": true, 6 | "declaration": false, 7 | "esModuleInterop": true, 8 | "experimentalDecorators": false, 9 | "forceConsistentCasingInFileNames": true, 10 | "isolatedModules": true, 11 | "lib": [ 12 | "esnext" 13 | ], 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "noEmitOnError": true, 17 | "noFallthroughCasesInSwitch": true, 18 | "noImplicitOverride": true, 19 | "noImplicitReturns": true, 20 | "noUnusedLocals": true, 21 | "pretty": true, 22 | "removeComments": false, 23 | "resolveJsonModule": false, 24 | "skipLibCheck": true, 25 | "sourceMap": false, 26 | "strict": true, 27 | "target": "es2022", 28 | "verbatimModuleSyntax": true 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/tsconfig/tsconfig.projects.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "composite": true, 6 | "declaration": true, 7 | "declarationMap": true, 8 | "emitDeclarationOnly": true, 9 | "incremental": true, 10 | "noEmitOnError": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/tsconfig/tsconfig.react.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "lib": [ 6 | "dom" 7 | ], 8 | "jsx": "react" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/tsconfig/tsconfig.solid.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "lib": [ 6 | "dom" 7 | ], 8 | "jsx": "preserve", 9 | "jsxImportSource": "solid-js" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/vscode-extension/.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | coverage/ 4 | images/ 5 | node_modules/ 6 | src/ 7 | .gitignore 8 | tsconfig.json 9 | .eslintrc.js 10 | **/*.map 11 | **/*.ts 12 | -------------------------------------------------------------------------------- /packages/vscode-extension/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.14.0 2 | 3 | - Added support for the task graph. Requires moon v1.30. 4 | - Added support for `.pkl` config files. 5 | 6 | ## 0.13.0 7 | 8 | - Added a new command that will generate local `yaml.schemas` settings. 9 | 10 | ## 0.12.0 11 | 12 | - Requires VS Code ^1.77.0. 13 | - Added support for internal tasks. They will not be displayed in the projects/tags view. 14 | 15 | ## 0.11.0 16 | 17 | - Added `stack` support to the projects view. Will now categorize based on stack + type. 18 | 19 | ## 0.10.0 20 | 21 | - Added YAML file validation for all moon configuration files. 22 | - Requires the `redhat.vscode-yaml` extension to be installed. VSCode should prompt you to install it. 23 | 24 | ## 0.9.0 25 | 26 | - Added a "Tags" view for projects in the moon console sidebar. 27 | 28 | ## 0.8.0 29 | 30 | - Added a `moon.logLevel` setting, to control the log level of all moon executed commands. 31 | - Added support for multiple VS Code workspace folders. 32 | - When you open a file in another workspace, the moon panels will refresh. 33 | - Removed support for moon < 1.0. 34 | - Replaced `moon.workspaceRoot` setting with `moon.rootPrefixes`. 35 | 36 | ## 0.7.0 37 | 38 | - Requires VS Code ^1.75.0. 39 | - Added action graph support (requires moon >= 1.15). 40 | - Added support for the `automation` project type. 41 | - Added a `moon.hideTasks` setting, to hide tasks in the projects view. 42 | 43 | ## 0.6.0 44 | 45 | - Added 19 new language icons (requires moon >= 0.25). 46 | 47 | ## 0.5.0 48 | 49 | - Added dependency and project graph in-editor visualization support. 50 | 51 | ## 0.4.0 52 | 53 | - Added support for 5 new language icons: Go, PHP, Python, Ruby, Rust 54 | 55 | ## 0.3.0 56 | 57 | - Changes to `moon.yml` will now automatically refresh projects. 58 | - Added file and folder icons to the `assets` folder. 59 | - This _does not_ associate them. You'll need to do that manually in your editor settings. 60 | 61 | ## 0.2.0 62 | 63 | - Added `moon check` support to the project rows in the Projects view. 64 | 65 | ## 0.1.0 66 | 67 | - Initial release! 68 | -------------------------------------------------------------------------------- /packages/vscode-extension/DEV.md: -------------------------------------------------------------------------------- 1 | # Development commands 2 | 3 | - https://code.visualstudio.com/api/get-started/your-first-extension#developing-the-extension 4 | - `F5` to start debugging the extension 5 | -------------------------------------------------------------------------------- /packages/vscode-extension/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 moonrepo LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or substantial 12 | portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 17 | OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /packages/vscode-extension/README.md: -------------------------------------------------------------------------------- 1 | # moon 2 | 3 | While moon provides a powerful and robust command line, an in-editor interface with deep integration 4 | can provide a much better developer experience, and that's exactly what this moon console does! 5 | 6 | Whether you're just learning, or an experienced veteran, this console will take you to the moon! 7 | 8 | ## Features 9 | 10 | ### Projects view 11 | 12 | The backbone of moon is the projects view. In this view, all moon configured projects will be 13 | listed, categorized by their `type`, and designated with their `language`. 14 | 15 | Each project can then be expanded to view all available tasks. Tasks can be ran by clicking the `▶` 16 | icon, or using the command palette. 17 | 18 | Screenshot of projects view 21 | 22 | > This view is available in both the "Explorer" and "moon" sections. 23 | 24 | ### Tags view 25 | 26 | Similar to the projects view, the tags view displays projects grouped by their `tags`. 27 | 28 | Screenshot of tags view 31 | 32 | > This view is only available in the "moon" section. 33 | 34 | ### Last run view 35 | 36 | Information about the last ran task will be displayed in a beautiful table with detailed stats. 37 | 38 | Screenshot of last run view 41 | 42 | > This view is only available in the "moon" section. 43 | 44 | ### Control panel 45 | 46 | To provide the best experience, all major features, enhancements, and integrations can be found 47 | within the moon specific control panel. Simply click the moon icon in the activity bar! 48 | 49 | Screenshot of moon activity 52 | 53 | ## Requirements 54 | 55 | This extension requires moon itself to be installed within the opened VS Code workspace. Learn more 56 | about [installing and configuring moon](https://moonrepo.dev/docs/install)! 57 | 58 | ## Settings 59 | 60 | The following settings are available for this extension. 61 | 62 | - `moon.binPath` - Relative path from moon's workspace root to the moon binary. Defaults to 63 | `node_modules/@moonrepo/cli/moon`. _Windows will auto-suffix with `.exe`!_ 64 | - `moon.hideTasks` - List of tasks to hide in the projects view, using target syntax. Supports 65 | fully-qualified targets (`app:build`) and partial targets (`:build` or `*:build`). Defaults to 66 | `[]`. 67 | - `moon.logLevel` - The log level to apply to all moon executed commands. Defaults to `info`. 68 | - `moon.rootPrefixes` - List of relative paths from the editor root in which to find moon's 69 | workspace root. Defaults to `['.']`. This is useful if moon is initialized in a sub-folder. 70 | 71 | ## Commands 72 | 73 | The following commands are available in the command palette (typically `cmd + shift + p`), and are 74 | prefixed with "moon". 75 | 76 | - **Open settings** - Opens the settings page and filters to all moon applicable settings. 77 | - **Run task** - Prompts the user for a task(s) and runs it in the terminal. 78 | - **View action graph** - Opens a panel that renders an interactive action graph visualization. 79 | - **View project graph** - Opens a panel that renders an interactive project graph visualization. 80 | 81 | ## Roadmap 82 | 83 | - [x] Projects view 84 | - [x] Categorize projects based on type 85 | - [x] List tasks 86 | - [x] Categorize tasks based on type 87 | - [x] Run a task 88 | - [x] Check a project 89 | - [x] Tags view 90 | - [x] Last run view 91 | - [x] Commands and command palette 92 | - [x] Watches and reacts to file system changes. 93 | - [x] Schema validation for YAML configs 94 | - [ ] moon language server 95 | - [ ] Auto-completion 96 | - [ ] In-editor code generation 97 | - [x] Graph visualizer 98 | - [x] Multi-workspace support 99 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/icons/file.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/icons/folder-open.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/icons/folder.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/bash.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/batch.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/c.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/cplusplus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/cpp.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/crystal.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/csharp.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/css.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/dart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/deno.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/dotnet.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/go.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/haskell.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/html.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/java.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/javascript.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/julia.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/kotlin.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/lua.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/node.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/ocaml.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/php.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/python.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/r.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/ruby.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/rust.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/scala.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/swift.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/typescript.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/unknown.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/langs/zig.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/moon-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moonrepo/dev/03da3c93c1227fff6fc3fcce67bce099b5933a4e/packages/vscode-extension/assets/moon-banner.png -------------------------------------------------------------------------------- /packages/vscode-extension/assets/moon-icon-theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "iconDefinitions": { 3 | "_file": { 4 | "iconPath": "./icons/file.svg" 5 | }, 6 | "_folder": { 7 | "iconPath": "./icons/folder.svg" 8 | }, 9 | "_folderOpen": { 10 | "iconPath": "./icons/folder-open.svg" 11 | } 12 | }, 13 | "fileNames": { 14 | "moon.yml": "_file" 15 | }, 16 | "folderNames": { 17 | ".moon": "_folder" 18 | }, 19 | "folderNamesExpanded": { 20 | ".moon": "_folderOpen" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/moon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/vscode-extension/assets/webview.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0; 3 | margin: 0; 4 | } 5 | 6 | .body { 7 | padding: 14px 20px; 8 | } 9 | 10 | table { 11 | border: 1px solid transparent; 12 | border-collapse: collapse; 13 | width: 100%; 14 | } 15 | 16 | td { 17 | padding: 6px; 18 | padding-left: 0; 19 | border: 1px solid transparent; 20 | border-bottom: 1px solid var(--divider-background); 21 | vertical-align: top; 22 | } 23 | 24 | td:last-child { 25 | padding-right: 0; 26 | } 27 | 28 | .action-label { 29 | font-weight: bold; 30 | color: var(--list-active-selection-foreground); 31 | } 32 | 33 | .action-icon { 34 | padding-top: 3px; 35 | } 36 | -------------------------------------------------------------------------------- /packages/vscode-extension/images/activity-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moonrepo/dev/03da3c93c1227fff6fc3fcce67bce099b5933a4e/packages/vscode-extension/images/activity-icon.png -------------------------------------------------------------------------------- /packages/vscode-extension/images/last-run-view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moonrepo/dev/03da3c93c1227fff6fc3fcce67bce099b5933a4e/packages/vscode-extension/images/last-run-view.png -------------------------------------------------------------------------------- /packages/vscode-extension/images/projects-view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moonrepo/dev/03da3c93c1227fff6fc3fcce67bce099b5933a4e/packages/vscode-extension/images/projects-view.png -------------------------------------------------------------------------------- /packages/vscode-extension/images/tags-view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moonrepo/dev/03da3c93c1227fff6fc3fcce67bce099b5933a4e/packages/vscode-extension/images/tags-view.png -------------------------------------------------------------------------------- /packages/vscode-extension/moon.yml: -------------------------------------------------------------------------------- 1 | stack: 'frontend' 2 | type: 'tool' 3 | tags: ['extension'] 4 | 5 | project: 6 | name: 'VS Code extension' 7 | description: 'This is to purely test metadata in the extension.' 8 | channel: '' 9 | owner: '' 10 | maintainers: [] 11 | 12 | workspace: 13 | inheritedTasks: 14 | exclude: ['build'] 15 | 16 | tasks: 17 | build: 18 | command: 'yarn run compile' 19 | inputs: 20 | - 'src/**/*' 21 | outputs: 22 | - 'lib' 23 | -------------------------------------------------------------------------------- /packages/vscode-extension/src/commands.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { satisfies } from 'semver'; 4 | import vscode, { ShellExecution, Task, TaskScope } from 'vscode'; 5 | import { GraphVisualizerView } from './graphVisualizerView'; 6 | import type { Workspace } from './workspace'; 7 | 8 | export async function checkProject( 9 | project: string, 10 | workspace: Workspace, 11 | modifier?: (task: Task) => void, 12 | ) { 13 | if (!workspace.root || !workspace.binPath) { 14 | return; 15 | } 16 | 17 | const task = new Task( 18 | { project, type: 'moon' }, 19 | TaskScope.Workspace, 20 | `moon check ${project}`, 21 | 'moon', 22 | new ShellExecution( 23 | workspace.binPath, 24 | [ 25 | 'check', 26 | project, 27 | '--log', 28 | vscode.workspace.getConfiguration('moon').get('logLevel', 'info'), 29 | ], 30 | { 31 | cwd: workspace.root, 32 | }, 33 | ), 34 | ); 35 | 36 | modifier?.(task); 37 | 38 | await vscode.tasks.executeTask(task); 39 | } 40 | 41 | export async function runTask( 42 | target: string, 43 | workspace: Workspace, 44 | modifier?: (task: Task) => void, 45 | ) { 46 | if (!workspace.root || !workspace.binPath) { 47 | return; 48 | } 49 | 50 | const task = new Task( 51 | { target, type: 'moon' }, 52 | TaskScope.Workspace, 53 | `moon run ${target}`, 54 | 'moon', 55 | new ShellExecution( 56 | workspace.binPath, 57 | [ 58 | 'run', 59 | ...target.split(' '), 60 | '--log', 61 | vscode.workspace.getConfiguration('moon').get('logLevel', 'info'), 62 | ], 63 | { 64 | cwd: workspace.root, 65 | }, 66 | ), 67 | ); 68 | 69 | modifier?.(task); 70 | 71 | await vscode.tasks.executeTask(task); 72 | } 73 | 74 | export async function runTaskByInput(workspace: Workspace) { 75 | if (!workspace.root || !workspace.binPath) { 76 | return; 77 | } 78 | 79 | const target = await vscode.window.showInputBox({ 80 | prompt: 'In the format of "scope:task" or ":task".', 81 | title: 'Target(s)', 82 | }); 83 | 84 | if (target) { 85 | await runTask(target, workspace); 86 | } 87 | } 88 | 89 | export async function viewActionGraph(context: vscode.ExtensionContext, workspace: Workspace) { 90 | await new GraphVisualizerView(context, workspace, 'action-graph').renderPanel(); 91 | } 92 | 93 | export async function viewProjectGraph(context: vscode.ExtensionContext, workspace: Workspace) { 94 | await new GraphVisualizerView(context, workspace, 'project-graph').renderPanel(); 95 | } 96 | 97 | export async function viewTaskGraph(context: vscode.ExtensionContext, workspace: Workspace) { 98 | const version = await workspace.getMoonVersion(); 99 | 100 | if (satisfies(version, '<1.30.0')) { 101 | await vscode.window.showErrorMessage(`Task graph requires moon >= 1.30.0, found ${version}`); 102 | 103 | return; 104 | } 105 | 106 | await new GraphVisualizerView(context, workspace, 'task-graph').renderPanel(); 107 | } 108 | 109 | export async function appendSchemasConfig(context: vscode.ExtensionContext, workspace: Workspace) { 110 | const version = await workspace.getMoonVersion(); 111 | 112 | if (satisfies(version, '<1.27.0')) { 113 | await vscode.window.showErrorMessage(`YAML schemas require moon >= 1.27.0, found ${version}`); 114 | 115 | return; 116 | } 117 | 118 | const vscodeDir = path.join(workspace.folder!.uri.fsPath, '.vscode'); 119 | const settingsPath = path.join(vscodeDir, 'settings.json'); 120 | 121 | const settings = ( 122 | fs.existsSync(settingsPath) ? JSON.parse(fs.readFileSync(settingsPath, 'utf8')) : {} 123 | ) as Record; 124 | 125 | const schemas = 126 | typeof settings['yaml.schemas'] === 'object' && Boolean(settings['yaml.schemas']) 127 | ? settings['yaml.schemas'] 128 | : {}; 129 | 130 | settings['yaml.schemas'] = { 131 | ...schemas, 132 | './.moon/cache/schemas/project.json': ['**/moon.yml'], 133 | './.moon/cache/schemas/tasks.json': [ 134 | path.join(workspace.rootPrefix, '.moon/tasks.yml'), 135 | path.join(workspace.rootPrefix, '.moon/tasks/**/*.yml'), 136 | ], 137 | './.moon/cache/schemas/template.json': ['**/template.yml'], 138 | './.moon/cache/schemas/toolchain.json': [ 139 | path.join(workspace.rootPrefix, '.moon/toolchain.yml'), 140 | ], 141 | './.moon/cache/schemas/workspace.json': [ 142 | path.join(workspace.rootPrefix, '.moon/workspace.yml'), 143 | ], 144 | }; 145 | 146 | if (!fs.existsSync(vscodeDir)) { 147 | fs.mkdirSync(vscodeDir); 148 | } 149 | 150 | fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2)); 151 | 152 | await vscode.window.showInformationMessage('Added `yaml.schemas` to `.vscode/settings.json`'); 153 | } 154 | -------------------------------------------------------------------------------- /packages/vscode-extension/src/extension.ts: -------------------------------------------------------------------------------- 1 | import vscode from 'vscode'; 2 | import { 3 | appendSchemasConfig, 4 | runTaskByInput, 5 | viewActionGraph, 6 | viewProjectGraph, 7 | viewTaskGraph, 8 | } from './commands'; 9 | import { LastRunProvider } from './lastRunView'; 10 | import { ProjectsProvider } from './projectsView'; 11 | import { Workspace } from './workspace'; 12 | 13 | export function activate(context: vscode.ExtensionContext) { 14 | const workspace = new Workspace(); 15 | const projectsProvider = new ProjectsProvider(context, workspace, 'category'); 16 | const tagsProvider = new ProjectsProvider(context, workspace, 'tag'); 17 | 18 | context.subscriptions.push( 19 | vscode.commands.registerCommand('moon.openSettings', () => 20 | vscode.commands.executeCommand('workbench.action.openSettings', '@ext:moonrepo.moon-console'), 21 | ), 22 | 23 | // Create commands 24 | vscode.commands.registerCommand('moon.runTaskByInput', () => runTaskByInput(workspace)), 25 | vscode.commands.registerCommand('moon.viewActionGraph', () => 26 | viewActionGraph(context, workspace), 27 | ), 28 | vscode.commands.registerCommand('moon.viewProjectGraph', () => 29 | viewProjectGraph(context, workspace), 30 | ), 31 | vscode.commands.registerCommand('moon.viewTaskGraph', () => viewTaskGraph(context, workspace)), 32 | vscode.commands.registerCommand('moon.appendSchemasConfig', () => 33 | appendSchemasConfig(context, workspace), 34 | ), 35 | 36 | // Create a tree view for all moon projects 37 | vscode.window.createTreeView('moonProjects', { 38 | showCollapseAll: true, 39 | treeDataProvider: projectsProvider, 40 | }), 41 | vscode.window.createTreeView('moonProjectsExternal', { 42 | showCollapseAll: true, 43 | treeDataProvider: projectsProvider, 44 | }), 45 | vscode.window.createTreeView('moonTags', { 46 | showCollapseAll: true, 47 | treeDataProvider: tagsProvider, 48 | }), 49 | 50 | // Create a webview for last run report 51 | vscode.window.registerWebviewViewProvider( 52 | 'moonLastRun', 53 | new LastRunProvider(context, workspace), 54 | ), 55 | ); 56 | } 57 | 58 | export function deactivate() {} 59 | -------------------------------------------------------------------------------- /packages/vscode-extension/src/graphVisualizerView.ts: -------------------------------------------------------------------------------- 1 | import { satisfies } from 'semver'; 2 | import vscode, { ViewColumn } from 'vscode'; 3 | import type { Workspace } from './workspace'; 4 | 5 | export type GraphType = 'action-graph' | 'project-graph' | 'task-graph'; 6 | 7 | export class GraphVisualizerView { 8 | context: vscode.ExtensionContext; 9 | 10 | panel: vscode.WebviewPanel; 11 | 12 | type: GraphType; 13 | 14 | workspace: Workspace; 15 | 16 | constructor(context: vscode.ExtensionContext, workspace: Workspace, type: GraphType) { 17 | this.context = context; 18 | this.workspace = workspace; 19 | this.type = type; 20 | this.panel = vscode.window.createWebviewPanel( 21 | type === 'action-graph' 22 | ? 'moonActionGraph' 23 | : type === 'project-graph' 24 | ? 'moonProjectGraph' 25 | : 'moonTaskGraph', 26 | type === 'action-graph' 27 | ? 'Action graph' 28 | : type === 'project-graph' 29 | ? 'Project graph' 30 | : 'Task graph', 31 | ViewColumn.Active, 32 | { 33 | enableScripts: true, 34 | localResourceRoots: [context.extensionUri], 35 | }, 36 | ); 37 | 38 | workspace.onDidChangeWorkspace(() => { 39 | void this.renderPanel(); 40 | }); 41 | } 42 | 43 | renderHtml(content: string) { 44 | const { title } = this.panel; 45 | const cssUri = this.panel.webview.asWebviewUri( 46 | vscode.Uri.joinPath(this.context.extensionUri, 'assets/webview.css'), 47 | ); 48 | 49 | return ` 50 | 51 | 52 | 53 | 54 | Moon visualizer | ${title} 55 | 56 | 57 | 61 | 62 | 63 | 64 | 65 | 66 | 69 | ${content} 70 | 71 | 72 | `; 73 | } 74 | 75 | async renderPanel() { 76 | const version = await this.workspace.getMoonVersion(); 77 | let command: string = this.type; 78 | 79 | if (command === 'action-graph' && satisfies(version, '<1.15.0')) { 80 | command = 'dep-graph'; 81 | } 82 | 83 | const data = await this.workspace.execMoon([command, '--json']); 84 | 85 | this.panel.webview.html = this.renderHtml( 86 | `
`, 87 | ); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /packages/vscode-extension/src/lastRunView.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import vscode from 'vscode'; 4 | import { formatDuration, prepareReportActions } from '@moonrepo/report'; 5 | import type { RunReport } from '@moonrepo/types'; 6 | import type { Workspace } from './workspace'; 7 | 8 | const SLOW_THRESHOLD_SECS = 120; 9 | 10 | export class LastRunProvider implements vscode.WebviewViewProvider { 11 | context: vscode.ExtensionContext; 12 | 13 | view?: vscode.WebviewView; 14 | 15 | workspace: Workspace; 16 | 17 | constructor(context: vscode.ExtensionContext, workspace: Workspace) { 18 | this.context = context; 19 | this.workspace = workspace; 20 | 21 | workspace.onDidChangeWorkspace((folder) => { 22 | this.renderView(); 23 | 24 | if (!folder) { 25 | return undefined; 26 | } 27 | 28 | // When the report is changed, refresh view 29 | const watcher = vscode.workspace.createFileSystemWatcher( 30 | new vscode.RelativePattern(folder.uri, workspace.getMoonDirPath('cache/runReport.json')), 31 | ); 32 | 33 | watcher.onDidChange(this.renderView, this); 34 | watcher.onDidCreate(this.renderView, this); 35 | watcher.onDidDelete(this.renderView, this); 36 | 37 | return watcher; 38 | }); 39 | } 40 | 41 | resolveWebviewView(webviewView: vscode.WebviewView): Thenable | void { 42 | webviewView.webview.options = { 43 | enableScripts: true, 44 | localResourceRoots: [this.context.extensionUri], 45 | }; 46 | 47 | this.view = webviewView; 48 | this.renderView(); 49 | } 50 | 51 | formatComments(comments: string[]): string { 52 | if (comments.length === 0) { 53 | return ''; 54 | } 55 | 56 | const content = comments 57 | .map((comment) => comment.replaceAll(/\*\*(\w+)\*\*/g, (_, match) => `${match}`)) 58 | .join(', '); 59 | 60 | return `| ${content}`; 61 | } 62 | 63 | renderHtml(content: string) { 64 | const cssUri = this.view?.webview.asWebviewUri( 65 | vscode.Uri.joinPath(this.context.extensionUri, 'assets/webview.css'), 66 | ); 67 | 68 | return ` 69 | 70 | 71 | 72 | 73 | moon - Last run report 74 | 75 | 76 | 77 | 78 | ${content} 79 | 80 | `; 81 | } 82 | 83 | renderView() { 84 | if (!this.view?.webview || !this.workspace.root) { 85 | return; 86 | } 87 | 88 | const runReportPath = path.join( 89 | this.workspace.root, 90 | this.workspace.getMoonDirPath('cache/runReport.json', false), 91 | ); 92 | 93 | if (fs.existsSync(runReportPath)) { 94 | const report = JSON.parse(fs.readFileSync(runReportPath, 'utf8')) as RunReport; 95 | 96 | const tableRows = prepareReportActions(report, SLOW_THRESHOLD_SECS).map( 97 | (action) => ` 98 | 99 | 100 | ${action.icon} 101 | 102 | 103 | ${action.label}
104 | ${action.time} | ${action.status} ${this.formatComments(action.comments)} 105 | 106 | 107 | `, 108 | ); 109 | 110 | this.view.webview.html = this.renderHtml(`Finished ${ 111 | report.context.primaryTargets.length > 0 112 | ? `${report.context.primaryTargets.join(', ')} ` 113 | : '' 114 | }in ${formatDuration(report.duration)}. 115 | 116 |

117 | 118 | 119 | ${tableRows.join('\n')} 120 |
121 | `); 122 | } else { 123 | this.view.webview.html = this.renderHtml(` 124 | No run report found. Run a task through the projects view or on the command line. 125 | `); 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /packages/vscode-extension/src/workspace.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import execa from 'execa'; 4 | import vscode from 'vscode'; 5 | 6 | export function isRealBin(binPath: string): boolean { 7 | const stats = fs.statSync(binPath); 8 | 9 | // When in the moonrepo/moon repository, the binary is actually fake, 10 | // so we need to account for that! 11 | return stats.size > 100; 12 | } 13 | 14 | export class Workspace { 15 | // Current moon binary path 16 | binPath: string | null = null; 17 | 18 | // Current vscode workspace folder 19 | folder: vscode.WorkspaceFolder | null = null; 20 | 21 | // Channel for logging 22 | logger: vscode.LogOutputChannel; 23 | 24 | // Current moon workspace root 25 | root: string | null = null; 26 | 27 | rootPrefix: string = ''; 28 | 29 | onDidChangeWorkspaceEmitter: vscode.EventEmitter; 30 | 31 | disposables: vscode.Disposable[] = []; 32 | 33 | constructor() { 34 | this.logger = vscode.window.createOutputChannel('moon', { log: true }); 35 | this.onDidChangeWorkspaceEmitter = new vscode.EventEmitter(); 36 | 37 | // Find moon workspace from default editor 38 | if (vscode.window.activeTextEditor) { 39 | this.findRoot(vscode.window.activeTextEditor.document.uri); 40 | } else { 41 | this.findDefaultRoot(); 42 | } 43 | 44 | // When an editor is changed, attempt to find the moon workspace 45 | vscode.window.onDidChangeActiveTextEditor((editor) => { 46 | if (editor && editor.document.uri.scheme === 'file') { 47 | this.findRoot(editor.document.uri); 48 | } 49 | }); 50 | } 51 | 52 | onDidChangeWorkspace( 53 | listener: (folder: vscode.WorkspaceFolder | null) => vscode.Disposable | void, 54 | ) { 55 | this.onDidChangeWorkspaceEmitter.event((folder) => { 56 | const disposable = listener(folder); 57 | 58 | if (disposable) { 59 | this.disposables.push(disposable); 60 | } 61 | }); 62 | } 63 | 64 | fireDidChangeWorkspace() { 65 | // Remove previous watchers 66 | this.disposables.forEach((disposable) => { 67 | disposable.dispose(); 68 | }); 69 | 70 | // Emit and add new watchers 71 | const { folder } = this; 72 | 73 | // Run in a timeout to ensure listeners have been registered, 74 | // otherwise this does nothing and the editor feels broken 75 | setTimeout(() => { 76 | this.onDidChangeWorkspaceEmitter.fire(folder); 77 | }, 0); 78 | } 79 | 80 | findDefaultRoot() { 81 | for (const folder of vscode.workspace.workspaceFolders ?? []) { 82 | this.findRoot(folder.uri); 83 | 84 | if (this.root) { 85 | break; 86 | } 87 | } 88 | } 89 | 90 | findRoot(openUri: vscode.Uri) { 91 | if (openUri.fsPath === 'moonrepo.moon-console.moon') { 92 | return; 93 | } 94 | 95 | if (this.root && openUri.fsPath.startsWith(this.root)) { 96 | return; 97 | } 98 | 99 | this.folder = null; 100 | this.root = null; 101 | this.rootPrefix = ''; 102 | this.binPath = null; 103 | 104 | this.logger.appendLine(`Attempting to find a VSC workspace folder for ${openUri.fsPath}`); 105 | 106 | const workspaceFolder = vscode.workspace.getWorkspaceFolder(openUri); 107 | 108 | if (workspaceFolder) { 109 | this.folder = workspaceFolder; 110 | 111 | this.logger.appendLine(`Found workspace folder ${workspaceFolder.uri.fsPath}`); 112 | this.logger.appendLine('Attempting to find a moon installation'); 113 | 114 | const rootPrefixes = vscode.workspace 115 | .getConfiguration('moon') 116 | .get('rootPrefixes', [] as string[]); 117 | rootPrefixes.push('.'); 118 | 119 | let foundRoot = false; 120 | 121 | for (const prefix of rootPrefixes) { 122 | const moonDir = path.join(workspaceFolder.uri.fsPath, prefix, '.moon'); 123 | 124 | if (fs.existsSync(moonDir)) { 125 | this.root = path.dirname(moonDir); 126 | this.rootPrefix = prefix; 127 | this.binPath = this.findMoonBin(); 128 | 129 | this.logger.appendLine(`Found moon workspace root at ${this.root}`); 130 | 131 | if (this.binPath) { 132 | this.logger.appendLine(`Found moon binary at ${this.binPath}`); 133 | } 134 | 135 | foundRoot = true; 136 | break; 137 | } 138 | } 139 | 140 | this.fireDidChangeWorkspace(); 141 | 142 | if (!foundRoot) { 143 | this.logger.appendLine('Did not find a moon installation, disabling'); 144 | } 145 | } else { 146 | this.logger.appendLine('Did not find a workspace folder, disabling moon'); 147 | } 148 | 149 | // Update context 150 | void vscode.commands.executeCommand('setContext', 'moon.inWorkspaceRoot', this.root !== null); 151 | 152 | void vscode.commands.executeCommand( 153 | 'setContext', 154 | 'moon.hasBinary', 155 | this.binPath !== null && isRealBin(this.binPath), 156 | ); 157 | } 158 | 159 | findMoonBin(): string | null { 160 | if (!this.root) { 161 | return null; 162 | } 163 | 164 | const isWindows = process.platform === 'win32'; 165 | let binPath = vscode.workspace.getConfiguration('moon').get('binPath', 'moon'); 166 | 167 | if (isWindows && !binPath.endsWith('.exe')) { 168 | binPath += '.exe'; 169 | } 170 | 171 | if (!path.isAbsolute(binPath)) { 172 | binPath = path.join(this.root, binPath); 173 | } 174 | 175 | if (fs.existsSync(binPath)) { 176 | return binPath; 177 | } 178 | 179 | const paths = process.env.PATH?.split(isWindows ? ';' : ':') ?? []; 180 | const binName = isWindows ? 'moon.exe' : 'moon'; 181 | 182 | for (const dir of paths) { 183 | const globalBin = path.join(dir, binName); 184 | 185 | if (fs.existsSync(globalBin)) { 186 | return globalBin; 187 | } 188 | } 189 | 190 | return null; 191 | } 192 | 193 | async execMoon(args: string[]): Promise { 194 | if (!args.includes('--json')) { 195 | args.push('--log', vscode.workspace.getConfiguration('moon').get('logLevel', 'info')); 196 | } 197 | 198 | try { 199 | const result = await execa(this.binPath ?? 'moon', args, { 200 | cwd: this.root ?? process.cwd(), 201 | }); 202 | 203 | return result.stdout; 204 | } catch (error: unknown) { 205 | console.error(error); 206 | 207 | throw error; 208 | } 209 | } 210 | 211 | getMoonDirPath(file: string, withPrefix: boolean = true): string { 212 | return path.join(withPrefix ? this.rootPrefix : '.', '.moon', file); 213 | } 214 | 215 | async getMoonVersion(): Promise { 216 | try { 217 | const result = await this.execMoon(['--version']); 218 | 219 | // Output is: moon 0.0.0 220 | const parts = result.split(' '); 221 | 222 | return parts.at(-1)!; 223 | } catch { 224 | return '0.0.0'; 225 | } 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /packages/vscode-extension/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.options.json", 3 | "compilerOptions": { 4 | "outDir": "../../.moon/cache/types/packages/vscode-extension" 5 | }, 6 | "include": [ 7 | ".eslintrc.js", 8 | "src/**/*" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /tests/setup.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.options.json", 3 | "files": [], 4 | "references": [ 5 | { 6 | "path": "packages/babel-preset" 7 | }, 8 | { 9 | "path": "packages/dev" 10 | }, 11 | { 12 | "path": "packages/eslint-config" 13 | }, 14 | { 15 | "path": "packages/jest-preset" 16 | }, 17 | { 18 | "path": "packages/vscode-extension" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /tsconfig.options.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tsconfig-moon/tsconfig.projects.json" 3 | } 4 | --------------------------------------------------------------------------------