Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ac802ed6db | |||
| 63883a44a4 | |||
| d1c0272359 | |||
| b46485f9be | |||
| df252a6dc0 | |||
| 1877db6f64 | |||
| c17da55c14 | |||
| 17932150ba | |||
| 3bf8cbdc62 | |||
| 232db2ed49 | |||
| e2f155391e | |||
| e665be4d4d | |||
| 83531de539 | |||
| 0e9993fcf1 | |||
| f9c138ce76 | |||
| ada1599219 | |||
| 5d32213b87 | |||
| 713bdf1d56 | |||
| 981b8eaf4d | |||
| 4d35cc7d4f | |||
| 45c98676ce | |||
| 5ab53625e2 | |||
| 75fd85f1e7 | |||
| d41a8e0df0 | |||
| 36d9ca3365 | |||
| 06dcc69d32 | |||
| b4b5dd7ed5 | |||
| 574fe37d91 | |||
| 377b70cd98 | |||
| 2757bda2df | |||
| a0cf68ec87 | |||
| 05893ff5d5 | |||
| 8951a7c3ab | |||
| 8e6a4854e7 | |||
| fe1a82c9e4 | |||
| b3ac4d5cfc |
@@ -161,11 +161,6 @@ jobs:
|
||||
command: |
|
||||
pnpm nx affected -t e2e-macos --parallel=1 --base=$NX_BASE --head=$NX_HEAD
|
||||
no_output_timeout: 45m
|
||||
- run:
|
||||
name: Close CI group
|
||||
command: |
|
||||
pnpm nx-cloud stop-all-agents
|
||||
no_output_timeout: 45m
|
||||
|
||||
# -------------------------
|
||||
# WORKFLOWS(JOBS)
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
settings:
|
||||
- host: macos-latest
|
||||
- host: macos-13
|
||||
target: x86_64-apple-darwin
|
||||
build: |
|
||||
pnpm nx run-many --target=build-native -- --target=x86_64-apple-darwin
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
target: x86_64-unknown-linux-musl
|
||||
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine
|
||||
build: set -e && pnpm nx run-many --target=build-native -- --target=x86_64-unknown-linux-musl
|
||||
- host: macos-latest
|
||||
- host: macos-13
|
||||
target: aarch64-apple-darwin
|
||||
build: |
|
||||
sudo rm -Rf /Library/Developer/CommandLineTools/SDKs/*;
|
||||
@@ -155,34 +155,35 @@ jobs:
|
||||
build-freebsd:
|
||||
runs-on: macos-12
|
||||
name: Build FreeBSD
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build
|
||||
id: build
|
||||
uses: vmactions/freebsd-vm@v0
|
||||
uses: cross-platform-actions/action@v0.21.0
|
||||
env:
|
||||
DEBUG: napi:*
|
||||
RUSTUP_HOME: /usr/local/rustup
|
||||
CARGO_HOME: /usr/local/cargo
|
||||
RUSTUP_IO_THREADS: 1
|
||||
with:
|
||||
envs: DEBUG RUSTUP_HOME CARGO_HOME RUSTUP_IO_THREADS
|
||||
usesh: true
|
||||
mem: 4096
|
||||
prepare: |
|
||||
pkg install -y -f curl node libnghttp2 npm
|
||||
npm install --location=global --ignore-scripts pnpm
|
||||
operating_system: freebsd
|
||||
version: '13.2'
|
||||
architecture: x86-64
|
||||
environment_variables: DEBUG RUSTUP_IO_THREADS CI
|
||||
shell: bash
|
||||
run: |
|
||||
env
|
||||
whoami
|
||||
sudo pkg install -y -f node libnghttp2 npm git
|
||||
sudo npm install --location=global --ignore-scripts pnpm
|
||||
curl https://sh.rustup.rs -sSf --output rustup.sh
|
||||
sh rustup.sh -y --profile minimal --default-toolchain stable
|
||||
export PATH="/usr/local/cargo/bin:$PATH"
|
||||
source "$HOME/.cargo/env"
|
||||
echo "~~~~ rustc --version ~~~~"
|
||||
rustc --version
|
||||
echo "~~~~ node -v ~~~~"
|
||||
node -v
|
||||
echo "~~~~ pnpm --version ~~~~"
|
||||
pnpm --version
|
||||
run: |
|
||||
export PATH="/usr/local/cargo/bin:$PATH"
|
||||
pwd
|
||||
ls -lah
|
||||
whoami
|
||||
@@ -191,9 +192,13 @@ jobs:
|
||||
mkdir -p /Users/runner/work/_temp/_github_workflow
|
||||
echo "{}" > /Users/runner/work/_temp/_github_workflow/event.json
|
||||
pnpm install --frozen-lockfile --ignore-scripts
|
||||
pnpm nx run-many --target=build-native -- --target=x86_64-unknown-freebsd
|
||||
pnpm nx run-many --outputStyle stream --target=build-native -- --target=x86_64-unknown-freebsd
|
||||
pnpm nx reset
|
||||
rm -rf node_modules
|
||||
rm -rf dist
|
||||
echo "KILL ALL NODE PROCESSES"
|
||||
killall node
|
||||
echo "COMPLETE"
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
|
||||
Generated
-10
@@ -1353,7 +1353,6 @@ dependencies = [
|
||||
"napi-build",
|
||||
"napi-derive",
|
||||
"once_cell",
|
||||
"os_type",
|
||||
"parking_lot",
|
||||
"rayon",
|
||||
"regex",
|
||||
@@ -1380,15 +1379,6 @@ version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "os_type"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e24d44c0eea30167516ed8f6daca4b5e3eebcde1bde1e4e6e08b809fb02c7ba5"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
|
||||
@@ -139,7 +139,7 @@ Package manager to use
|
||||
|
||||
Type: `string`
|
||||
|
||||
Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "next", "nextjs-standalone", "react-native", "expo", "nest", "express", "react", "angular", "node-standalone", "node-monorepo", "ts-standalone"]. To build your own see https://nx.dev/extending-nx/recipes/create-preset
|
||||
Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "vue-monorepo", "vue-standalone", "next", "nextjs-standalone", "react-native", "expo", "nest", "express", "react", "angular", "node-standalone", "node-monorepo", "ts-standalone"]. To build your own see https://nx.dev/extending-nx/recipes/create-preset
|
||||
|
||||
### routing
|
||||
|
||||
|
||||
@@ -15,19 +15,19 @@
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string",
|
||||
"$default": { "$source": "argv", "index": 0 },
|
||||
"description": "The path to locate the federated module.",
|
||||
"x-prompt": "What is the path to the module to be federated?"
|
||||
},
|
||||
"name": {
|
||||
"description": "The name of the module.",
|
||||
"type": "string",
|
||||
"$default": { "$source": "argv", "index": 0 },
|
||||
"x-prompt": "What name would you like to use for the module?",
|
||||
"pattern": "^[a-zA-Z][^:]*$",
|
||||
"x-priority": "important"
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "The path to locate the federated module.",
|
||||
"x-prompt": "What is the path to the module to be federated?"
|
||||
},
|
||||
"remote": {
|
||||
"type": "string",
|
||||
"description": "The name of the remote.",
|
||||
|
||||
@@ -155,12 +155,6 @@
|
||||
"type": "boolean",
|
||||
"description": "Includes third-party packages in the bundle (i.e. npm packages)."
|
||||
},
|
||||
"dependenciesFieldType": {
|
||||
"type": "string",
|
||||
"description": "When `bundleInternalProjectsOnly` is true, this option determines whether external packages should be in 'dependencies' or 'peerDependencies' field in the generated package.json file.",
|
||||
"enum": ["dependencies", "peerDependencies"],
|
||||
"default": "dependencies"
|
||||
},
|
||||
"esbuildOptions": {
|
||||
"type": "object",
|
||||
"description": "Additional options to pass to esbuild. See https://esbuild.github.io/api/. Cannot be used with 'esbuildConfig' option.",
|
||||
|
||||
@@ -139,7 +139,7 @@ Package manager to use
|
||||
|
||||
Type: `string`
|
||||
|
||||
Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "next", "nextjs-standalone", "react-native", "expo", "nest", "express", "react", "angular", "node-standalone", "node-monorepo", "ts-standalone"]. To build your own see https://nx.dev/extending-nx/recipes/create-preset
|
||||
Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "vue-monorepo", "vue-standalone", "next", "nextjs-standalone", "react-native", "expo", "nest", "express", "react", "angular", "node-standalone", "node-monorepo", "ts-standalone"]. To build your own see https://nx.dev/extending-nx/recipes/create-preset
|
||||
|
||||
### routing
|
||||
|
||||
|
||||
@@ -56,6 +56,13 @@
|
||||
"default": false,
|
||||
"description": "Do not add dependencies to `package.json`.",
|
||||
"x-priority": "internal"
|
||||
},
|
||||
"rootProject": {
|
||||
"description": "Create a application at the root of the workspace",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"hidden": true,
|
||||
"x-priority": "internal"
|
||||
}
|
||||
},
|
||||
"required": ["project"],
|
||||
|
||||
@@ -15,19 +15,19 @@
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string",
|
||||
"$default": { "$source": "argv", "index": 0 },
|
||||
"description": "The path to locate the federated module. This path should be relative to the workspace root and the file should exist.",
|
||||
"x-prompt": "What is the path to the module to be federated?"
|
||||
},
|
||||
"name": {
|
||||
"description": "The name of the module.",
|
||||
"type": "string",
|
||||
"$default": { "$source": "argv", "index": 0 },
|
||||
"x-prompt": "What name would you like to use for the module?",
|
||||
"pattern": "^[a-zA-Z][^:]*$",
|
||||
"x-priority": "important"
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "The path to locate the federated module. This path should be relative to the workspace root and the file should exist.",
|
||||
"x-prompt": "What is the path to the module to be federated?"
|
||||
},
|
||||
"remote": {
|
||||
"type": "string",
|
||||
"description": "The name of the remote.",
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
},
|
||||
"unitTestRunner": {
|
||||
"type": "string",
|
||||
"enum": ["jest", "vitest", "none"],
|
||||
"enum": ["vitest", "none"],
|
||||
"description": "Test runner to use for unit tests.",
|
||||
"x-prompt": "Which unit test runner would you like to use?",
|
||||
"default": "vitest"
|
||||
|
||||
@@ -100,15 +100,9 @@
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"x-priority": "internal"
|
||||
},
|
||||
"unitTestRunner": {
|
||||
"type": "string",
|
||||
"enum": ["vitest", "jest", "none"],
|
||||
"description": "Test runner to use for unit tests.",
|
||||
"x-prompt": "What unit test runner should be used?"
|
||||
}
|
||||
},
|
||||
"required": ["name", "project"],
|
||||
"required": ["name"],
|
||||
"presets": []
|
||||
},
|
||||
"aliases": ["c"],
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
},
|
||||
"unitTestRunner": {
|
||||
"type": "string",
|
||||
"enum": ["vitest", "jest", "none"],
|
||||
"enum": ["vitest", "none"],
|
||||
"description": "Test runner to use for unit tests.",
|
||||
"x-prompt": "What unit test runner should be used?"
|
||||
},
|
||||
|
||||
@@ -46,14 +46,14 @@ Now that we have created the module, we need to configure it to be federated.
|
||||
{%tab label="React"%}
|
||||
|
||||
```shell
|
||||
nx generate @nx/react:federate-module Hello --remote=greeting --path=hello/src/index.ts --projectNameAndRootFormat=as-provided
|
||||
nx generate @nx/react:federate-module hello/src/index.ts --name=hello --remote=greeting --projectNameAndRootFormat=as-provided
|
||||
```
|
||||
|
||||
{% /tab %}
|
||||
{%tab label="Angular"%}
|
||||
|
||||
```shell
|
||||
nx generate @nx/angular:federate-module Hello --remote=greeting --path=hello/src/index.ts --projectNameAndRootFormat=as-provided
|
||||
nx generate @nx/angular:federate-module hello/src/index.ts --name=hello --remote=greeting --projectNameAndRootFormat=as-provided
|
||||
```
|
||||
|
||||
{% /tab %}
|
||||
|
||||
@@ -326,7 +326,7 @@ describe('Angular Module Federation', () => {
|
||||
|
||||
// Federate Module
|
||||
runCLI(
|
||||
`generate @nx/angular:federate-module ${module} --remote=${remote} --path=${lib}/src/index.ts --no-interactive`
|
||||
`generate @nx/angular:federate-module ${lib}/src/index.ts --name=${module} --remote=${remote} --no-interactive`
|
||||
);
|
||||
|
||||
updateFile(`${lib}/src/index.ts`, `export { isEven } from './lib/${lib}';`);
|
||||
@@ -403,7 +403,7 @@ describe('Angular Module Federation', () => {
|
||||
|
||||
// Federate Module
|
||||
runCLI(
|
||||
`generate @nx/angular:federate-module ${module} --remote=${childRemote} --path=${lib}/src/index.ts --no-interactive`
|
||||
`generate @nx/angular:federate-module ${lib}/src/index.ts --name=${module} --remote=${childRemote} --no-interactive`
|
||||
);
|
||||
|
||||
updateFile(`${lib}/src/index.ts`, `export { isEven } from './lib/${lib}';`);
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
"executor": "@nx/jest:jest",
|
||||
"options": {
|
||||
"jestConfig": "e2e/eslint/jest.config.ts",
|
||||
"passWithNoTests": true,
|
||||
"runInBand": true
|
||||
},
|
||||
"outputs": ["{workspaceRoot}/coverage/e2e/eslint"]
|
||||
|
||||
@@ -680,7 +680,9 @@ describe('Linter', () => {
|
||||
// should have plugin extends
|
||||
expect(appEslint.overrides[0].extends).toBeDefined();
|
||||
expect(appEslint.overrides[1].extends).toBeDefined();
|
||||
expect(e2eEslint.overrides[0].extends).toBeDefined();
|
||||
expect(
|
||||
e2eEslint.overrides.some((override) => override.extends)
|
||||
).toBeTruthy();
|
||||
|
||||
runCLI(`generate @nx/js:lib ${mylib} --unitTestRunner=jest`);
|
||||
verifySuccessfulMigratedSetup(myapp, mylib);
|
||||
@@ -691,7 +693,9 @@ describe('Linter', () => {
|
||||
// should have no plugin extends
|
||||
expect(appEslint.overrides[0].extends).toBeUndefined();
|
||||
expect(appEslint.overrides[1].extends).toBeUndefined();
|
||||
expect(e2eEslint.overrides[0].extends).toBeUndefined();
|
||||
expect(
|
||||
e2eEslint.overrides.some((override) => override.extends)
|
||||
).toBeFalsy();
|
||||
});
|
||||
|
||||
it('(Angular standalone) should set root project config to app and e2e app and migrate when another lib is added', () => {
|
||||
@@ -708,7 +712,9 @@ describe('Linter', () => {
|
||||
|
||||
// should have plugin extends
|
||||
expect(appEslint.overrides[1].extends).toBeDefined();
|
||||
expect(e2eEslint.overrides[0].extends).toBeDefined();
|
||||
expect(
|
||||
e2eEslint.overrides.some((override) => override.extends)
|
||||
).toBeTruthy();
|
||||
|
||||
runCLI(`generate @nx/js:lib ${mylib} --no-interactive`);
|
||||
verifySuccessfulMigratedSetup(myapp, mylib);
|
||||
@@ -720,7 +726,9 @@ describe('Linter', () => {
|
||||
expect(appEslint.overrides[1].extends).toEqual([
|
||||
'plugin:@nx/angular-template',
|
||||
]);
|
||||
expect(e2eEslint.overrides[0].extends).toBeUndefined();
|
||||
expect(
|
||||
e2eEslint.overrides.some((override) => override.extends)
|
||||
).toBeFalsy();
|
||||
});
|
||||
|
||||
it('(Node standalone) should set root project config to app and e2e app and migrate when another lib is added', async () => {
|
||||
|
||||
@@ -475,7 +475,7 @@ describe('React Module Federation', () => {
|
||||
|
||||
// Federate Module
|
||||
runCLI(
|
||||
`generate @nx/react:federate-module ${module} --remote=${remote} --path=${lib}/src/index.ts --no-interactive`
|
||||
`generate @nx/react:federate-module ${lib}/src/index.ts --name=${module} --remote=${remote} --no-interactive`
|
||||
);
|
||||
|
||||
updateFile(
|
||||
@@ -566,7 +566,7 @@ describe('React Module Federation', () => {
|
||||
|
||||
// Federate Module
|
||||
runCLI(
|
||||
`generate @nx/react:federate-module ${module} --remote=${childRemote} --path=${lib}/src/index.ts --no-interactive`
|
||||
`generate @nx/react:federate-module ${lib}/src/index.ts --name=${module} --remote=${childRemote} --no-interactive`
|
||||
);
|
||||
|
||||
updateFile(
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { FeedContainer } from '@nx/nx-dev/feature-ai';
|
||||
import { DocumentationHeader } from '@nx/nx-dev/ui-common';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { NextSeo } from 'next-seo';
|
||||
import { useNavToggle } from '../../lib/navigation-toggle.effect';
|
||||
import { cx } from '@nx/nx-dev/ui-primitives';
|
||||
|
||||
export default function AiDocs(): JSX.Element {
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
|
||||
return (
|
||||
<>
|
||||
<NextSeo
|
||||
@@ -38,6 +39,10 @@ export default function AiDocs(): JSX.Element {
|
||||
role="main"
|
||||
className="flex h-full flex-1 overflow-y-hidden"
|
||||
>
|
||||
<div className="hidden">
|
||||
<SidebarContainer menu={{ sections: [] }} navIsOpen={navIsOpen} />
|
||||
</div>
|
||||
|
||||
<FeedContainer />
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -180,7 +180,10 @@ export function SidebarMobile({
|
||||
const isNxCloud: boolean = router.asPath.startsWith('/nx-cloud');
|
||||
const isAPI: boolean = router.asPath.startsWith('/nx-api');
|
||||
const isPlugins: boolean = router.asPath.startsWith('/extending-nx');
|
||||
const isNx: boolean = !isNxCloud && !isAPI && !isPlugins;
|
||||
const isChangelog: boolean = router.asPath.startsWith('/changelog');
|
||||
const isAiChat: boolean = router.asPath.startsWith('/ai-chat');
|
||||
const isNx: boolean =
|
||||
!isNxCloud && !isAPI && !isPlugins && !isChangelog && !isAiChat;
|
||||
|
||||
const sections = [
|
||||
{ name: 'Home', href: '/', current: false },
|
||||
@@ -190,15 +193,25 @@ export function SidebarMobile({
|
||||
href: '/nx-cloud/intro/ci-with-nx',
|
||||
current: isNxCloud,
|
||||
},
|
||||
{
|
||||
name: 'Extending Nx',
|
||||
href: '/extending-nx/intro/getting-started',
|
||||
current: isPlugins,
|
||||
},
|
||||
{
|
||||
name: 'API',
|
||||
href: '/nx-api',
|
||||
current: isAPI,
|
||||
},
|
||||
{
|
||||
name: 'Extending Nx',
|
||||
href: '/extending-nx/intro/getting-started',
|
||||
current: isPlugins,
|
||||
name: 'Changelog',
|
||||
href: '/changelog',
|
||||
current: isChangelog,
|
||||
},
|
||||
{
|
||||
name: 'AI Chat (beta)',
|
||||
href: '/ai-chat',
|
||||
current: isAiChat,
|
||||
},
|
||||
];
|
||||
return (
|
||||
|
||||
@@ -10,8 +10,7 @@
|
||||
"executor": "@nx/jest:jest",
|
||||
"outputs": ["{workspaceRoot}/coverage/nx-dev/ui-home"],
|
||||
"options": {
|
||||
"jestConfig": "nx-dev/ui-home/jest.config.ts",
|
||||
"passWithNoTests": true
|
||||
"jestConfig": "nx-dev/ui-home/jest.config.ts"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,14 +28,7 @@
|
||||
"executor": "@nx/jest:jest",
|
||||
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
||||
"options": {
|
||||
"jestConfig": "nx-dev/util-ai/jest.config.ts",
|
||||
"passWithNoTests": true
|
||||
},
|
||||
"configurations": {
|
||||
"ci": {
|
||||
"ci": true,
|
||||
"codeCoverage": true
|
||||
}
|
||||
"jestConfig": "nx-dev/util-ai/jest.config.ts"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -26,6 +26,13 @@
|
||||
]
|
||||
},
|
||||
"release": {
|
||||
"releaseTagPattern": "{version}",
|
||||
"changelog": {
|
||||
"workspaceChangelog": {
|
||||
"createRelease": "github",
|
||||
"file": false
|
||||
}
|
||||
},
|
||||
"groups": {
|
||||
"npm": {
|
||||
"projects": [
|
||||
@@ -181,9 +188,6 @@
|
||||
],
|
||||
"cache": true
|
||||
},
|
||||
"lint-base": {
|
||||
"cache": true
|
||||
},
|
||||
"build-ng": {
|
||||
"cache": true
|
||||
},
|
||||
@@ -195,6 +199,19 @@
|
||||
},
|
||||
"copy-docs": {
|
||||
"cache": true
|
||||
},
|
||||
"@nx/jest:jest": {
|
||||
"cache": true,
|
||||
"inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"],
|
||||
"options": {
|
||||
"passWithNoTests": true
|
||||
},
|
||||
"configurations": {
|
||||
"ci": {
|
||||
"ci": true,
|
||||
"codeCoverage": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"plugins": ["@monodon/rust"],
|
||||
|
||||
+19
-19
@@ -66,19 +66,19 @@
|
||||
"@nguniversal/builders": "~16.2.0",
|
||||
"@nuxt/kit": "^3.7.4",
|
||||
"@nuxt/schema": "^3.7.4",
|
||||
"@nx/angular": "17.0.0-rc.2",
|
||||
"@nx/cypress": "17.0.0-rc.2",
|
||||
"@nx/devkit": "17.0.0-rc.2",
|
||||
"@nx/esbuild": "17.0.0-rc.2",
|
||||
"@nx/eslint-plugin": "17.0.0-rc.2",
|
||||
"@nx/jest": "17.0.0-rc.2",
|
||||
"@nx/js": "17.0.0-rc.2",
|
||||
"@nx/next": "17.0.0-rc.2",
|
||||
"@nx/playwright": "17.0.0-rc.2",
|
||||
"@nx/react": "17.0.0-rc.2",
|
||||
"@nx/storybook": "17.0.0-rc.2",
|
||||
"@nx/web": "17.0.0-rc.2",
|
||||
"@nx/webpack": "17.0.0-rc.2",
|
||||
"@nx/angular": "17.1.0-beta.4",
|
||||
"@nx/cypress": "17.1.0-beta.4",
|
||||
"@nx/devkit": "17.1.0-beta.4",
|
||||
"@nx/esbuild": "17.1.0-beta.4",
|
||||
"@nx/eslint-plugin": "17.1.0-beta.4",
|
||||
"@nx/jest": "17.1.0-beta.4",
|
||||
"@nx/js": "17.1.0-beta.4",
|
||||
"@nx/next": "17.1.0-beta.4",
|
||||
"@nx/playwright": "17.1.0-beta.4",
|
||||
"@nx/react": "17.1.0-beta.4",
|
||||
"@nx/storybook": "17.1.0-beta.4",
|
||||
"@nx/web": "17.1.0-beta.4",
|
||||
"@nx/webpack": "17.1.0-beta.4",
|
||||
"@parcel/watcher": "2.0.4",
|
||||
"@phenomnomnominal/tsquery": "~5.0.1",
|
||||
"@playwright/test": "^1.36.1",
|
||||
@@ -93,10 +93,10 @@
|
||||
"@rollup/plugin-url": "^7.0.0",
|
||||
"@schematics/angular": "~16.2.0",
|
||||
"@side/jest-runtime": "^1.1.0",
|
||||
"@storybook/addon-essentials": "7.2.2",
|
||||
"@storybook/core-server": "7.2.2",
|
||||
"@storybook/react": "7.2.2",
|
||||
"@storybook/react-webpack5": "7.2.2",
|
||||
"@storybook/addon-essentials": "7.5.3",
|
||||
"@storybook/core-server": "7.5.3",
|
||||
"@storybook/react": "7.5.3",
|
||||
"@storybook/react-webpack5": "7.5.3",
|
||||
"@storybook/types": "^7.1.1",
|
||||
"@supabase/supabase-js": "^2.26.0",
|
||||
"@svgr/rollup": "^8.0.1",
|
||||
@@ -230,7 +230,7 @@
|
||||
"ng-packagr": "~16.2.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"npm-package-arg": "11.0.1",
|
||||
"nx": "17.0.0-rc.2",
|
||||
"nx": "17.1.0-beta.4",
|
||||
"octokit": "^2.0.14",
|
||||
"open": "^8.4.0",
|
||||
"openai": "~4.3.1",
|
||||
@@ -296,7 +296,7 @@
|
||||
"xstate": "4.34.0",
|
||||
"yargs": "^17.6.2",
|
||||
"yargs-parser": "21.1.1",
|
||||
"@nx/eslint": "17.0.0-rc.2"
|
||||
"@nx/eslint": "17.1.0-beta.4"
|
||||
},
|
||||
"author": "Victor Savkin",
|
||||
"license": "MIT",
|
||||
|
||||
+2
-1
@@ -21,7 +21,8 @@ import {
|
||||
getRemotes,
|
||||
} from '@nx/webpack/src/utils/module-federation';
|
||||
import { fork } from 'child_process';
|
||||
import { combineLatest, concatMap, from, switchMap } from 'rxjs';
|
||||
import { combineLatest, from } from 'rxjs';
|
||||
import { concatMap, switchMap } from 'rxjs/operators';
|
||||
|
||||
export function executeModuleFederationDevServerBuilder(
|
||||
schema: Schema,
|
||||
|
||||
@@ -31,6 +31,7 @@ export async function addE2e(tree: Tree, options: NormalizedSchema) {
|
||||
skipPackageJson: options.skipPackageJson,
|
||||
skipFormat: true,
|
||||
devServerTarget: `${options.name}:serve:development`,
|
||||
rootProject: options.rootProject,
|
||||
});
|
||||
} else if (options.e2eTestRunner === 'playwright') {
|
||||
const { configurationGenerator: playwrightConfigurationGenerator } =
|
||||
@@ -57,6 +58,7 @@ export async function addE2e(tree: Tree, options: NormalizedSchema) {
|
||||
options.name
|
||||
}`,
|
||||
webServerAddress: `http://localhost:${options.port ?? 4200}`,
|
||||
rootProject: options.rootProject,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,22 +12,22 @@
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "The name of the module.",
|
||||
"path": {
|
||||
"type": "string",
|
||||
"$default": {
|
||||
"$source": "argv",
|
||||
"index": 0
|
||||
},
|
||||
"description": "The path to locate the federated module.",
|
||||
"x-prompt": "What is the path to the module to be federated?"
|
||||
},
|
||||
"name": {
|
||||
"description": "The name of the module.",
|
||||
"type": "string",
|
||||
"x-prompt": "What name would you like to use for the module?",
|
||||
"pattern": "^[a-zA-Z][^:]*$",
|
||||
"x-priority": "important"
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "The path to locate the federated module.",
|
||||
"x-prompt": "What is the path to the module to be federated?"
|
||||
},
|
||||
"remote": {
|
||||
"type": "string",
|
||||
"description": "The name of the remote.",
|
||||
|
||||
@@ -10,14 +10,14 @@ export function normalizeNewProjectPrefix(
|
||||
): string {
|
||||
// Prefix needs to be a valid html selector, if npmScope it's not valid, we don't default
|
||||
// to it and let it fall through to the Angular schematic to handle it
|
||||
// https://github.com/angular/angular-cli/blob/1c634cd327e5a850553b258aa2d5e6a6b2c75c65/packages/schematics/angular/component/index.ts#L130
|
||||
// https://github.com/angular/angular-cli/blob/aa9f0528f174e856a4923cb24861fdf6e6f96b48/packages/schematics/angular/component/index.ts#L64
|
||||
const htmlSelectorRegex =
|
||||
/^[a-zA-Z][.0-9a-zA-Z]*(:?-[a-zA-Z][.0-9a-zA-Z]*)*$/;
|
||||
/^[a-zA-Z][.0-9a-zA-Z]*((:?-[0-9]+)*|(:?-[a-zA-Z][.0-9a-zA-Z]*(:?-[0-9]+)*)*)$/;
|
||||
|
||||
if (prefix) {
|
||||
if (!htmlSelectorRegex.test(prefix)) {
|
||||
throw new Error(
|
||||
'The provided "prefix" is invalid. The prefix must start with a letter, and must contain only alphanumeric characters or dashes. When adding a dash the segment after the dash must also start with a letter.'
|
||||
'The provided "prefix" is invalid. The prefix must start with a letter, and must contain only alphanumeric characters or dashes.'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ There are two options that can be followed to resolve this issue:
|
||||
|
||||
If you encountered this error when creating a new Nx Workspace, the workspace name or "npmScope" is invalid to use as the selector prefix for the application being generated.
|
||||
|
||||
Valid selector prefixes must start with a letter, and must contain only alphanumeric characters or dashes. When adding a dash the segment after the dash must also start with a letter.`);
|
||||
Valid selector prefixes must start with a letter, and must contain only alphanumeric characters or dashes.`);
|
||||
}
|
||||
|
||||
return npmScope || fallbackPrefix;
|
||||
|
||||
@@ -112,10 +112,6 @@ export const commandsObject: yargs.Argv<Arguments> = yargs
|
||||
describe: chalk.dim`Customizes the initial content of your workspace. Default presets include: [${Object.values(
|
||||
Preset
|
||||
)
|
||||
// TODO(v17): Remove this option when @nx/vue is released.
|
||||
.filter(
|
||||
(p) => p !== Preset.VueStandalone && p !== Preset.VueMonorepo
|
||||
)
|
||||
.map((p) => `"${p}"`)
|
||||
.join(
|
||||
', '
|
||||
@@ -244,7 +240,6 @@ function normalizeAndWarnOnDeprecatedPreset(
|
||||
return async (args: yargs.Arguments<Arguments>): Promise<void> => {
|
||||
if (!args.preset) return;
|
||||
if (deprecatedPresets[args.preset]) {
|
||||
args.preset = deprecatedPresets[args.preset] as Preset;
|
||||
output.addVerticalSeparator();
|
||||
output.note({
|
||||
title: `The "${args.preset}" preset is deprecated.`,
|
||||
@@ -256,6 +251,7 @@ function normalizeAndWarnOnDeprecatedPreset(
|
||||
}" preset instead.`,
|
||||
],
|
||||
});
|
||||
args.preset = deprecatedPresets[args.preset] as Preset;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ export interface CypressE2EConfigSchema {
|
||||
linter?: Linter;
|
||||
port?: number | 'cypress-auto';
|
||||
jsx?: boolean;
|
||||
rootProject?: boolean;
|
||||
}
|
||||
|
||||
type NormalizedSchema = ReturnType<typeof normalizeOptions>;
|
||||
@@ -91,7 +92,7 @@ In this case you need to provide a devServerTarget,'<projectName>:<targetName>[:
|
||||
return {
|
||||
...options,
|
||||
bundler: options.bundler ?? 'webpack',
|
||||
rootProject: projectConfig.root === '.',
|
||||
rootProject: options.rootProject ?? projectConfig.root === '.',
|
||||
linter: options.linter ?? Linter.EsLint,
|
||||
devServerTarget:
|
||||
options.devServerTarget ??
|
||||
|
||||
@@ -12,5 +12,12 @@
|
||||
"reporters": ["detox/runners/jest/reporter"],
|
||||
"testEnvironment": "detox/runners/jest/testEnvironment",
|
||||
"verbose": true,
|
||||
"setupFilesAfterEnv": ["<rootDir>/test-setup.ts"]
|
||||
"setupFilesAfterEnv": ["<rootDir>/test-setup.ts"],
|
||||
"transform": {
|
||||
"^.+\\.(ts|js|html)$": [
|
||||
"ts-jest",
|
||||
{ "tsconfig": "<rootDir>/tsconfig.e2e.json" }
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ export interface EsBuildExecutorOptions {
|
||||
assets: (AssetGlob | string)[];
|
||||
bundle?: boolean;
|
||||
deleteOutputPath?: boolean;
|
||||
dependenciesFieldType?: boolean;
|
||||
esbuildOptions?: Record<string, any>;
|
||||
esbuildConfig?: string;
|
||||
external?: string[];
|
||||
|
||||
@@ -130,12 +130,6 @@
|
||||
"type": "boolean",
|
||||
"description": "Includes third-party packages in the bundle (i.e. npm packages)."
|
||||
},
|
||||
"dependenciesFieldType": {
|
||||
"type": "string",
|
||||
"description": "When `bundleInternalProjectsOnly` is true, this option determines whether external packages should be in 'dependencies' or 'peerDependencies' field in the generated package.json file.",
|
||||
"enum": ["dependencies", "peerDependencies"],
|
||||
"default": "dependencies"
|
||||
},
|
||||
"esbuildOptions": {
|
||||
"type": "object",
|
||||
"description": "Additional options to pass to esbuild. See https://esbuild.github.io/api/. Cannot be used with 'esbuildConfig' option.",
|
||||
|
||||
@@ -99,7 +99,6 @@ function migrateEslintFile(projectEslintPath: string, tree: Tree) {
|
||||
'plugin:@nrwl/typescript',
|
||||
'plugin:@nrwl/javascript',
|
||||
]);
|
||||
console.warn('Flat eslint config is not supported yet for migration');
|
||||
tree.write(projectEslintPath, config);
|
||||
} else {
|
||||
updateJson(tree, projectEslintPath, (json) => {
|
||||
|
||||
@@ -335,18 +335,24 @@ export function addBlockToFlatConfigExport(
|
||||
});
|
||||
const insert = printer.printNode(ts.EmitHint.Expression, config, source);
|
||||
if (options.insertAtTheEnd) {
|
||||
const index =
|
||||
exportsArray.length > 0
|
||||
? exportsArray.at(exportsArray.length - 1).end
|
||||
: exportsArray.pos;
|
||||
return applyChangesToString(content, [
|
||||
{
|
||||
type: ChangeType.Insert,
|
||||
index: exportsArray[exportsArray.length - 1].end,
|
||||
index,
|
||||
text: `,\n${insert}`,
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
const index =
|
||||
exportsArray.length > 0 ? exportsArray.at(0).pos : exportsArray.pos;
|
||||
return applyChangesToString(content, [
|
||||
{
|
||||
type: ChangeType.Insert,
|
||||
index: exportsArray[0].pos,
|
||||
index,
|
||||
text: `\n${insert},`,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -99,6 +99,7 @@ module.exports = function (api: any, options: NxWebBabelPresetOptions = {}) {
|
||||
require.resolve('@babel/plugin-proposal-decorators'),
|
||||
options.decorators ?? { legacy: true },
|
||||
],
|
||||
[require.resolve('@babel/plugin-transform-class-properties'), { loose }],
|
||||
].filter(Boolean),
|
||||
overrides: [
|
||||
// Convert `const enum` to `enum`. The former cannot be supported by babel
|
||||
|
||||
@@ -23,6 +23,12 @@
|
||||
"version": "16.8.2-beta.0",
|
||||
"description": "Remove invalid options (strict, noInterop) for ES6 type modules.",
|
||||
"factory": "./src/migrations/update-16-8-2/update-swcrc"
|
||||
},
|
||||
"update-17-0-0-remove-deprecated-build-options": {
|
||||
"cli": "nx",
|
||||
"version": "17.0.2",
|
||||
"description": "Remove deprecated build options",
|
||||
"implementation": "./src/migrations/update-17-0-0/remove-deprecated-build-options"
|
||||
}
|
||||
},
|
||||
"packageJsonUpdates": {
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"@babel/core": "^7.22.9",
|
||||
"@babel/plugin-proposal-decorators": "^7.22.7",
|
||||
"@babel/plugin-transform-runtime": "^7.22.9",
|
||||
"@babel/plugin-transform-class-properties": "^7.22.5",
|
||||
"@babel/preset-env": "^7.22.9",
|
||||
"@babel/preset-typescript": "^7.22.5",
|
||||
"@babel/runtime": "^7.22.6",
|
||||
|
||||
@@ -1359,4 +1359,32 @@ describe('lib', () => {
|
||||
expect(tree.exists('web/my-lib/src/lib/my-lib.ts')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('--testEnvironment', () => {
|
||||
it('should generate a vite config with testEnvironment set to node', async () => {
|
||||
await libraryGenerator(tree, {
|
||||
...defaultOptions,
|
||||
name: 'my-node-lib',
|
||||
unitTestRunner: 'vitest',
|
||||
testEnvironment: 'node',
|
||||
});
|
||||
|
||||
const content = tree.read('my-node-lib/vite.config.ts', 'utf-8');
|
||||
|
||||
expect(content).toContain(`environment: 'node'`);
|
||||
});
|
||||
|
||||
it('should generate a vite config with testEnvironment set to jsdom by default', async () => {
|
||||
await libraryGenerator(tree, {
|
||||
...defaultOptions,
|
||||
name: 'my-jsdom-lib',
|
||||
unitTestRunner: 'vitest',
|
||||
testEnvironment: undefined,
|
||||
});
|
||||
|
||||
const content = tree.read('my-jsdom-lib/vite.config.ts', 'utf-8');
|
||||
|
||||
expect(content).toContain(`environment: 'jsdom'`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -99,6 +99,7 @@ export async function libraryGeneratorInternal(
|
||||
project: options.name,
|
||||
includeLib: true,
|
||||
includeVitest: options.unitTestRunner === 'vitest',
|
||||
testEnvironment: options.testEnvironment,
|
||||
},
|
||||
false
|
||||
);
|
||||
@@ -136,6 +137,7 @@ export async function libraryGeneratorInternal(
|
||||
project: options.name,
|
||||
includeLib: false,
|
||||
includeVitest: true,
|
||||
testEnvironment: options.testEnvironment,
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
@@ -53,6 +53,17 @@ describe('remove-deprecated-build-options', () => {
|
||||
await expect(migration(tree)).resolves.not.toThrow();
|
||||
});
|
||||
|
||||
it('should work if a target is an empty object', async () => {
|
||||
addProjectConfiguration(tree, 'proj', {
|
||||
root: 'proj',
|
||||
targets: {
|
||||
build: {},
|
||||
},
|
||||
});
|
||||
|
||||
await expect(migration(tree)).resolves.not.toThrow();
|
||||
});
|
||||
|
||||
it('should not update community executors', async () => {
|
||||
addProjectConfiguration(tree, 'proj', {
|
||||
root: 'proj',
|
||||
|
||||
@@ -19,7 +19,8 @@ export default async function (tree: Tree) {
|
||||
|
||||
for (const target of Object.values(projectConfig.targets)) {
|
||||
if (
|
||||
target.executor.startsWith('@nx/') &&
|
||||
target.executor?.startsWith('@nx/') &&
|
||||
target.options &&
|
||||
('buildableProjectDepsInPackageJsonType' in target.options ||
|
||||
'updateBuildableProjectDepsInPackageJson' in target.options)
|
||||
) {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { addLocalRegistryScripts } from './add-local-registry-scripts';
|
||||
import { Tree, writeJson } from '@nx/devkit';
|
||||
import { createTree } from '@nx/devkit/testing';
|
||||
|
||||
describe('addLocalRegistryScripts', () => {
|
||||
let tree: Tree;
|
||||
const startLocalRegistryPath = 'tools/scripts/start-local-registry.ts';
|
||||
const stopLocalRegistryPath = 'tools/scripts/stop-local-registry.ts';
|
||||
|
||||
beforeEach(() => {
|
||||
tree = createTree();
|
||||
writeJson(tree, 'project.json', {
|
||||
name: 'mylib',
|
||||
});
|
||||
});
|
||||
|
||||
it('should add "start-local-registry.ts" and "stop-local-registry.ts" in workspace\'s "tools/scripts" folder', () => {
|
||||
expect(addLocalRegistryScripts(tree)).toEqual({
|
||||
startLocalRegistryPath,
|
||||
stopLocalRegistryPath,
|
||||
});
|
||||
|
||||
expect(tree.exists(startLocalRegistryPath)).toBe(true);
|
||||
expect(tree.exists(stopLocalRegistryPath)).toBe(true);
|
||||
});
|
||||
|
||||
it('should set published version to "0.0.0-e2e"', () => {
|
||||
addLocalRegistryScripts(tree);
|
||||
|
||||
const startLocalRegistry = tree.read(startLocalRegistryPath, 'utf-8');
|
||||
expect(/'0\.0\.0-e2e'/.test(startLocalRegistry)).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -22,7 +22,7 @@ export default async () => {
|
||||
const nx = require.resolve('nx');
|
||||
execFileSync(
|
||||
nx,
|
||||
['run-many', '--targets', 'publish', '--ver', '1.0.0', '--tag', 'e2e'],
|
||||
['run-many', '--targets', 'publish', '--ver', '0.0.0-e2e', '--tag', 'e2e'],
|
||||
{ env: process.env, stdio: 'inherit' }
|
||||
);
|
||||
};
|
||||
|
||||
@@ -118,70 +118,54 @@ describe('AssetInputOutputHandler', () => {
|
||||
deletedMockedWatchedFile(path.join(projectDir, 'docs/test1.md'));
|
||||
deletedMockedWatchedFile(path.join(projectDir, 'docs/test2.md'));
|
||||
|
||||
expect(callback.mock.calls).toEqual([
|
||||
[
|
||||
[
|
||||
{
|
||||
type: 'create',
|
||||
src: path.join(rootDir, 'LICENSE'),
|
||||
dest: path.join(rootDir, 'dist/mylib/LICENSE'),
|
||||
},
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
{
|
||||
type: 'create',
|
||||
src: path.join(rootDir, 'mylib/README.md'),
|
||||
dest: path.join(rootDir, 'dist/mylib/README.md'),
|
||||
},
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
{
|
||||
type: 'create',
|
||||
src: path.join(rootDir, 'mylib/docs/test1.md'),
|
||||
dest: path.join(rootDir, 'dist/mylib/docs/test1.md'),
|
||||
},
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
{
|
||||
type: 'create',
|
||||
src: path.join(rootDir, 'mylib/docs/test2.md'),
|
||||
dest: path.join(rootDir, 'dist/mylib/docs/test2.md'),
|
||||
},
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
{
|
||||
type: 'update',
|
||||
src: path.join(rootDir, 'mylib/docs/test1.md'),
|
||||
dest: path.join(rootDir, 'dist/mylib/docs/test1.md'),
|
||||
},
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
{
|
||||
type: 'delete',
|
||||
src: path.join(rootDir, 'mylib/docs/test1.md'),
|
||||
dest: path.join(rootDir, 'dist/mylib/docs/test1.md'),
|
||||
},
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
{
|
||||
type: 'delete',
|
||||
src: path.join(rootDir, 'mylib/docs/test2.md'),
|
||||
dest: path.join(rootDir, 'dist/mylib/docs/test2.md'),
|
||||
},
|
||||
],
|
||||
],
|
||||
expect(callback).toHaveBeenCalledWith([
|
||||
{
|
||||
type: 'create',
|
||||
src: path.join(rootDir, 'LICENSE'),
|
||||
dest: path.join(rootDir, 'dist/mylib/LICENSE'),
|
||||
},
|
||||
]);
|
||||
expect(callback).toHaveBeenCalledWith([
|
||||
{
|
||||
type: 'create',
|
||||
src: path.join(rootDir, 'mylib/README.md'),
|
||||
dest: path.join(rootDir, 'dist/mylib/README.md'),
|
||||
},
|
||||
]);
|
||||
expect(callback).toHaveBeenCalledWith([
|
||||
{
|
||||
type: 'create',
|
||||
src: path.join(rootDir, 'mylib/docs/test1.md'),
|
||||
dest: path.join(rootDir, 'dist/mylib/docs/test1.md'),
|
||||
},
|
||||
]);
|
||||
expect(callback).toHaveBeenCalledWith([
|
||||
{
|
||||
type: 'create',
|
||||
src: path.join(rootDir, 'mylib/docs/test2.md'),
|
||||
dest: path.join(rootDir, 'dist/mylib/docs/test2.md'),
|
||||
},
|
||||
]);
|
||||
expect(callback).toHaveBeenCalledWith([
|
||||
{
|
||||
type: 'update',
|
||||
src: path.join(rootDir, 'mylib/docs/test1.md'),
|
||||
dest: path.join(rootDir, 'dist/mylib/docs/test1.md'),
|
||||
},
|
||||
]);
|
||||
expect(callback).toHaveBeenCalledWith([
|
||||
{
|
||||
type: 'delete',
|
||||
src: path.join(rootDir, 'mylib/docs/test1.md'),
|
||||
dest: path.join(rootDir, 'dist/mylib/docs/test1.md'),
|
||||
},
|
||||
]);
|
||||
expect(callback).toHaveBeenCalledWith([
|
||||
{
|
||||
type: 'delete',
|
||||
src: path.join(rootDir, 'mylib/docs/test2.md'),
|
||||
dest: path.join(rootDir, 'dist/mylib/docs/test2.md'),
|
||||
},
|
||||
]);
|
||||
|
||||
dispose();
|
||||
@@ -202,39 +186,31 @@ describe('AssetInputOutputHandler', () => {
|
||||
|
||||
await sut.processAllAssetsOnce();
|
||||
|
||||
expect(callback.mock.calls).toEqual([
|
||||
[
|
||||
[
|
||||
{
|
||||
type: 'create',
|
||||
src: path.join(rootDir, 'LICENSE'),
|
||||
dest: path.join(rootDir, 'dist/mylib/LICENSE'),
|
||||
},
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
{
|
||||
type: 'create',
|
||||
src: path.join(rootDir, 'mylib/README.md'),
|
||||
dest: path.join(rootDir, 'dist/mylib/README.md'),
|
||||
},
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
{
|
||||
type: 'create',
|
||||
src: path.join(rootDir, 'mylib/docs/test1.md'),
|
||||
dest: path.join(rootDir, 'dist/mylib/docs/test1.md'),
|
||||
},
|
||||
{
|
||||
type: 'create',
|
||||
src: path.join(rootDir, 'mylib/docs/test2.md'),
|
||||
dest: path.join(rootDir, 'dist/mylib/docs/test2.md'),
|
||||
},
|
||||
],
|
||||
],
|
||||
expect(callback).toHaveBeenCalledWith([
|
||||
{
|
||||
type: 'create',
|
||||
src: path.join(rootDir, 'LICENSE'),
|
||||
dest: path.join(rootDir, 'dist/mylib/LICENSE'),
|
||||
},
|
||||
]);
|
||||
expect(callback).toHaveBeenCalledWith([
|
||||
{
|
||||
type: 'create',
|
||||
src: path.join(rootDir, 'mylib/README.md'),
|
||||
dest: path.join(rootDir, 'dist/mylib/README.md'),
|
||||
},
|
||||
]);
|
||||
expect(callback).toHaveBeenCalledWith([
|
||||
{
|
||||
type: 'create',
|
||||
src: path.join(rootDir, 'mylib/docs/test1.md'),
|
||||
dest: path.join(rootDir, 'dist/mylib/docs/test1.md'),
|
||||
},
|
||||
{
|
||||
type: 'create',
|
||||
src: path.join(rootDir, 'mylib/docs/test2.md'),
|
||||
dest: path.join(rootDir, 'dist/mylib/docs/test2.md'),
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
"test": {
|
||||
"executor": "@nx/jest:jest",
|
||||
"options": {
|
||||
"jestConfig": "packages/nuxt/jest.config.ts",
|
||||
"passWithNoTests": true
|
||||
"jestConfig": "packages/nuxt/jest.config.ts"
|
||||
},
|
||||
"outputs": ["{workspaceRoot}/coverage/packages/nuxt"]
|
||||
},
|
||||
|
||||
@@ -18,7 +18,6 @@ import { getRelativePathToRootTsConfig } from '@nx/js';
|
||||
import { updateGitIgnore } from '../../utils/update-gitignore';
|
||||
import { addBuildTarget, addServeTarget } from './lib/add-targets';
|
||||
import { Linter } from '@nx/eslint';
|
||||
import { addJest } from '@nx/vue';
|
||||
import { addE2e } from './lib/add-e2e';
|
||||
import { nxVersion } from '../../utils/versions';
|
||||
import { addLinting } from '../../utils/add-linting';
|
||||
@@ -74,14 +73,6 @@ export async function applicationGenerator(tree: Tree, schema: Schema) {
|
||||
})
|
||||
);
|
||||
|
||||
if (options.unitTestRunner === 'jest') {
|
||||
tasks.push(
|
||||
await addJest(tree, {
|
||||
name: options.name,
|
||||
projectRoot: options.appProjectRoot,
|
||||
})
|
||||
);
|
||||
}
|
||||
if (options.unitTestRunner === 'vitest') {
|
||||
const { vitestGenerator } = ensurePackage('@nx/vite', nxVersion);
|
||||
tasks.push(
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ export interface Schema {
|
||||
projectNameAndRootFormat?: ProjectNameAndRootFormat;
|
||||
linter?: Linter;
|
||||
skipFormat?: boolean;
|
||||
unitTestRunner?: 'jest' | 'vitest' | 'none';
|
||||
unitTestRunner?: 'vitest' | 'none';
|
||||
e2eTestRunner?: 'cypress' | 'playwright' | 'none';
|
||||
tags?: string;
|
||||
js?: boolean;
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
},
|
||||
"unitTestRunner": {
|
||||
"type": "string",
|
||||
"enum": ["jest", "vitest", "none"],
|
||||
"enum": ["vitest", "none"],
|
||||
"description": "Test runner to use for unit tests.",
|
||||
"x-prompt": "Which unit test runner would you like to use?",
|
||||
"default": "none"
|
||||
|
||||
@@ -9,5 +9,4 @@ export interface Schema {
|
||||
inSourceTests?: boolean;
|
||||
skipFormat?: boolean;
|
||||
directory?: string;
|
||||
unitTestRunner?: 'jest' | 'vitest' | 'none';
|
||||
}
|
||||
|
||||
@@ -79,12 +79,6 @@
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"x-priority": "internal"
|
||||
},
|
||||
"unitTestRunner": {
|
||||
"type": "string",
|
||||
"enum": ["vitest", "jest", "none"],
|
||||
"description": "Test runner to use for unit tests.",
|
||||
"x-prompt": "What unit test runner should be used?"
|
||||
}
|
||||
},
|
||||
"required": ["name", "project"]
|
||||
|
||||
@@ -16,7 +16,7 @@ export async function addLinting(
|
||||
linter: Linter;
|
||||
projectName: string;
|
||||
projectRoot: string;
|
||||
unitTestRunner?: 'jest' | 'vitest' | 'none';
|
||||
unitTestRunner?: 'vitest' | 'none';
|
||||
rootProject?: boolean;
|
||||
}
|
||||
) {
|
||||
|
||||
@@ -14,7 +14,6 @@ ignore = '0.4'
|
||||
ignore-files = "1.3.0"
|
||||
itertools = "0.10.5"
|
||||
once_cell = "1.18.0"
|
||||
os_type = "2.6.0"
|
||||
parking_lot = { version = "0.12.1", features = ["send_guard"] }
|
||||
napi = { version = '2.12.6', default-features = false, features = [
|
||||
'anyhow',
|
||||
|
||||
@@ -209,6 +209,7 @@ function handleAngularCLIFallbacks(workspace: WorkspaceTypeAndRoot) {
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
// nx-ignore-next-line
|
||||
const cli = require.resolve('@angular/cli/lib/init.js', {
|
||||
paths: [workspace.dir],
|
||||
});
|
||||
|
||||
@@ -200,6 +200,7 @@ function resolveNx(workspace: WorkspaceTypeAndRoot | null) {
|
||||
} catch {
|
||||
// TODO(v17): Remove this
|
||||
// fallback for old CLI install setup
|
||||
// nx-ignore-next-line
|
||||
return require.resolve('@nrwl/cli/bin/nx.js', {
|
||||
paths: [workspace ? workspace.dir : globalsRoot],
|
||||
});
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
initCloud,
|
||||
printFinalMessage,
|
||||
runInstall,
|
||||
updateGitIgnore,
|
||||
} from './utils';
|
||||
|
||||
type Options = Pick<InitArgs, 'nxCloud' | 'interactive' | 'cacheable'>;
|
||||
@@ -88,6 +89,7 @@ export async function addNxToMonorepo(options: Options) {
|
||||
scriptOutputs
|
||||
);
|
||||
|
||||
updateGitIgnore(repoRoot);
|
||||
addDepsToPackageJson(repoRoot);
|
||||
|
||||
output.log({ title: '📦 Installing dependencies' });
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
markRootPackageJsonAsNxProject,
|
||||
printFinalMessage,
|
||||
runInstall,
|
||||
updateGitIgnore,
|
||||
} from './utils';
|
||||
import { nxVersion } from '../../../utils/versions';
|
||||
|
||||
@@ -117,6 +118,7 @@ export async function addNxToNest(options: Options, packageJson: PackageJson) {
|
||||
|
||||
const pmc = getPackageManagerCommand();
|
||||
|
||||
updateGitIgnore(repoRoot);
|
||||
addDepsToPackageJson(repoRoot);
|
||||
addNestPluginToPackageJson(repoRoot);
|
||||
markRootPackageJsonAsNxProject(
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
markRootPackageJsonAsNxProject,
|
||||
printFinalMessage,
|
||||
runInstall,
|
||||
updateGitIgnore,
|
||||
} from './utils';
|
||||
|
||||
type Options = Pick<InitArgs, 'nxCloud' | 'interactive' | 'cacheable'>;
|
||||
@@ -72,6 +73,7 @@ export async function addNxToNpmRepo(options: Options) {
|
||||
|
||||
const pmc = getPackageManagerCommand();
|
||||
|
||||
updateGitIgnore(repoRoot);
|
||||
addDepsToPackageJson(repoRoot);
|
||||
markRootPackageJsonAsNxProject(
|
||||
repoRoot,
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
} from '../../../utils/package-manager';
|
||||
import { joinPathFragments } from '../../../utils/path';
|
||||
import { nxVersion } from '../../../utils/versions';
|
||||
import { readFileSync, writeFileSync } from 'fs';
|
||||
|
||||
export async function askAboutNxCloud(): Promise<boolean> {
|
||||
return await enquirer
|
||||
@@ -121,6 +122,17 @@ export function addDepsToPackageJson(repoRoot: string) {
|
||||
writeJsonFile(path, json);
|
||||
}
|
||||
|
||||
export function updateGitIgnore(root: string) {
|
||||
const ignorePath = join(root, '.gitignore');
|
||||
try {
|
||||
let contents = readFileSync(ignorePath, 'utf-8');
|
||||
if (!contents.includes('.nx/cache')) {
|
||||
contents = [contents, '', '.nx/cache'].join('\n');
|
||||
writeFileSync(ignorePath, contents, 'utf-8');
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
export function runInstall(
|
||||
repoRoot: string,
|
||||
pmc: PackageManagerCommands = getPackageManagerCommand()
|
||||
|
||||
@@ -2,7 +2,6 @@ import { execSync } from 'child_process';
|
||||
import { prompt } from 'enquirer';
|
||||
import { existsSync } from 'fs';
|
||||
import { prerelease } from 'semver';
|
||||
import * as parser from 'yargs-parser';
|
||||
import { addNxToMonorepo } from './implementation/add-nx-to-monorepo';
|
||||
import { addNxToNest } from './implementation/add-nx-to-nest';
|
||||
import { addNxToNpmRepo } from './implementation/add-nx-to-npm-repo';
|
||||
|
||||
@@ -207,22 +207,24 @@ function readAndCombineAllProjectConfigurations(tree: Tree): {
|
||||
const json = readJson(tree, projectFile);
|
||||
const config = buildProjectFromProjectJson(json, projectFile);
|
||||
mergeProjectConfigurationIntoRootMap(rootMap, config);
|
||||
} else {
|
||||
} else if (basename(projectFile) === 'package.json') {
|
||||
const packageJson = readJson<PackageJson>(tree, projectFile);
|
||||
const config = buildProjectConfigurationFromPackageJson(
|
||||
packageJson,
|
||||
projectFile,
|
||||
readNxJson(tree)
|
||||
);
|
||||
mergeProjectConfigurationIntoRootMap(
|
||||
rootMap,
|
||||
// Inferred targets, tags, etc don't show up when running generators
|
||||
// This is to help avoid running into issues when trying to update the workspace
|
||||
{
|
||||
name: config.name,
|
||||
root: config.root,
|
||||
}
|
||||
);
|
||||
if (!rootMap.has(config.root)) {
|
||||
mergeProjectConfigurationIntoRootMap(
|
||||
rootMap,
|
||||
// Inferred targets, tags, etc don't show up when running generators
|
||||
// This is to help avoid running into issues when trying to update the workspace
|
||||
{
|
||||
name: config.name,
|
||||
root: config.root,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,9 @@ use swc_common::{BytePos, SourceMap, Spanned};
|
||||
use swc_ecma_ast::EsVersion::EsNext;
|
||||
use swc_ecma_parser::error::Error;
|
||||
use swc_ecma_parser::lexer::Lexer;
|
||||
use swc_ecma_parser::token::Keyword::{Class, Default_, Export, Function, Import};
|
||||
use swc_ecma_parser::token::Keyword::{
|
||||
Catch, Class, Default_, Export, Finally, Function, Import, Try,
|
||||
};
|
||||
use swc_ecma_parser::token::Word::{Ident, Keyword};
|
||||
use swc_ecma_parser::token::{BinOpToken, Token, TokenAndSpan};
|
||||
use swc_ecma_parser::{Syntax, Tokens, TsConfig};
|
||||
@@ -43,6 +45,7 @@ enum BlockType {
|
||||
Object,
|
||||
ObjectType,
|
||||
ArrowFunction,
|
||||
TryCatchFinally,
|
||||
}
|
||||
|
||||
fn is_identifier(token: &Token) -> bool {
|
||||
@@ -55,6 +58,7 @@ struct State<'a> {
|
||||
pub previous_token: Option<TokenAndSpan>,
|
||||
pub import_type: ImportType,
|
||||
open_brace_count: i128,
|
||||
open_bracket_count: i128,
|
||||
blocks_stack: Vec<BlockType>,
|
||||
next_block_type: BlockType,
|
||||
}
|
||||
@@ -66,6 +70,7 @@ impl<'a> State<'a> {
|
||||
current_token: None,
|
||||
previous_token: None,
|
||||
open_brace_count: 0,
|
||||
open_bracket_count: 0,
|
||||
blocks_stack: vec![],
|
||||
next_block_type: BlockType::Block,
|
||||
import_type: ImportType::Dynamic,
|
||||
@@ -106,11 +111,19 @@ impl<'a> State<'a> {
|
||||
// The block has closed so remove it from the block stack
|
||||
self.blocks_stack.pop();
|
||||
}
|
||||
Token::LBracket => {
|
||||
self.open_bracket_count += 1;
|
||||
}
|
||||
Token::RBracket => {
|
||||
self.open_bracket_count -= 1;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Keep track of when we are in an object declaration because colons mean different things
|
||||
let in_object_declaration = self.blocks_stack.contains(&BlockType::Object);
|
||||
// Keep track of when we are in an array declaration because commas mean different things
|
||||
let in_array_declaration = self.open_bracket_count > 0;
|
||||
|
||||
let new_line = self.lexer.had_line_break_before_last();
|
||||
|
||||
@@ -141,6 +154,13 @@ impl<'a> State<'a> {
|
||||
Keyword(keyword) if *keyword == Class => {
|
||||
self.next_block_type = BlockType::Class;
|
||||
}
|
||||
|
||||
// If a try/catch/finally keyword appears, the next open brace will start a function block
|
||||
Keyword(keyword)
|
||||
if *keyword == Try || *keyword == Catch || *keyword == Finally =>
|
||||
{
|
||||
self.next_block_type = BlockType::TryCatchFinally;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
Token::AssignOp(_) => {
|
||||
@@ -167,6 +187,25 @@ impl<'a> State<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
// When an array opens, the next brace will be an object
|
||||
// Matches [{ }]
|
||||
Token::LBracket => {
|
||||
if let Some(t) = &self.previous_token {
|
||||
match t.token {
|
||||
Token::Colon => {
|
||||
self.next_block_type = BlockType::ObjectType;
|
||||
}
|
||||
_ => {
|
||||
self.next_block_type = BlockType::Object;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Token::Comma => {
|
||||
if in_array_declaration {
|
||||
self.next_block_type = BlockType::Object;
|
||||
}
|
||||
}
|
||||
Token::BinOp(op) => match op {
|
||||
BinOpToken::Lt => {
|
||||
// Matches things like Foo<typeof import('a')>
|
||||
@@ -407,9 +446,15 @@ fn find_specifier_in_require(state: &mut State) -> Option<(String, ImportType)>
|
||||
Token::LParen |
|
||||
// Matches things like require.resolve
|
||||
Token::Dot |
|
||||
Token::Comma |
|
||||
Token::LBrace |
|
||||
Token::RBrace |
|
||||
Token::LBracket |
|
||||
Token::RBracket |
|
||||
Token::Colon |
|
||||
Token::Word(Ident(_)) => {}
|
||||
// This could be a string literal
|
||||
Token::Str { value, .. } => {
|
||||
Token::Str { value, .. } if import.is_none() => {
|
||||
import = Some(value.to_string());
|
||||
}
|
||||
|
||||
@@ -434,6 +479,8 @@ fn find_specifier_in_require(state: &mut State) -> Option<(String, ImportType)>
|
||||
return None;
|
||||
}
|
||||
}
|
||||
// If we found an import, definitely wait for the RParen so it gets added
|
||||
_ if import.is_some() => {}
|
||||
// Anything else means this is not a require of a string literal
|
||||
_ => {
|
||||
return None;
|
||||
@@ -560,7 +607,7 @@ fn process_file(
|
||||
|
||||
let code_is_not_ignored = |(specifier, pos): (String, BytePos)| {
|
||||
let line_with_code = cm.lookup_line(pos).expect("All code is on a line");
|
||||
if lines_with_nx_ignore_comments.contains(&(line_with_code - 1)) {
|
||||
if line_with_code > 0 && lines_with_nx_ignore_comments.contains(&(line_with_code - 1)) {
|
||||
None
|
||||
} else {
|
||||
Some(specifier)
|
||||
@@ -618,8 +665,13 @@ fn find_imports(
|
||||
#[cfg(test)]
|
||||
mod find_imports {
|
||||
use super::*;
|
||||
use crate::native::utils::glob::build_glob_set;
|
||||
use crate::native::utils::path::Normalize;
|
||||
use crate::native::walker::nx_walker;
|
||||
use assert_fs::prelude::*;
|
||||
use assert_fs::TempDir;
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use swc_common::comments::NoopComments;
|
||||
|
||||
#[test]
|
||||
@@ -820,7 +872,7 @@ import 'a4'; import 'a5';
|
||||
.unwrap();
|
||||
|
||||
let result = results.get(0).unwrap();
|
||||
let ast_results: ImportResult = find_imports_with_ast(test_file_path);
|
||||
let ast_results: ImportResult = find_imports_with_ast(test_file_path).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
result.static_import_expressions,
|
||||
@@ -977,6 +1029,20 @@ import('./dynamic-import.vue')
|
||||
}
|
||||
const a = 1;
|
||||
export class App {}
|
||||
|
||||
|
||||
const a: [{ a: typeof import('static-import-in-array-type-in-object')}] = [];
|
||||
|
||||
const a = [{ a: import('dynamic-import-in-object-in-array')}];
|
||||
|
||||
const a = { a: [import('dynamic-import-in-array-in-object')]};
|
||||
|
||||
const routes = [
|
||||
{},
|
||||
{
|
||||
lazy: () => import('dynamic-import-lazy-route')
|
||||
}
|
||||
]
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -990,7 +1056,7 @@ import('./dynamic-import.vue')
|
||||
.unwrap();
|
||||
|
||||
let result = results.get(0).unwrap();
|
||||
let ast_results: ImportResult = find_imports_with_ast(test_file_path);
|
||||
let ast_results: ImportResult = find_imports_with_ast(test_file_path).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
result.static_import_expressions,
|
||||
@@ -1048,7 +1114,7 @@ import('./dynamic-import.vue')
|
||||
.unwrap();
|
||||
|
||||
let result = results.get(0).unwrap();
|
||||
let ast_results: ImportResult = find_imports_with_ast(test_file_path);
|
||||
let ast_results: ImportResult = find_imports_with_ast(test_file_path).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
result.static_import_expressions,
|
||||
@@ -1087,7 +1153,7 @@ import('./dynamic-import.vue')
|
||||
.unwrap();
|
||||
|
||||
let result = results.get(0).unwrap();
|
||||
let ast_results: ImportResult = find_imports_with_ast(test_file_path);
|
||||
let ast_results: ImportResult = find_imports_with_ast(test_file_path).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
result.static_import_expressions,
|
||||
@@ -1135,7 +1201,7 @@ import('./dynamic-import.vue')
|
||||
.unwrap();
|
||||
|
||||
let result = results.get(0).unwrap();
|
||||
let ast_results: ImportResult = find_imports_with_ast(test_file_path);
|
||||
let ast_results: ImportResult = find_imports_with_ast(test_file_path).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
result.static_import_expressions,
|
||||
@@ -1220,7 +1286,7 @@ import('./dynamic-import.vue')
|
||||
.unwrap();
|
||||
|
||||
let result = results.get(0).unwrap();
|
||||
let ast_results: ImportResult = find_imports_with_ast(test_file_path);
|
||||
let ast_results: ImportResult = find_imports_with_ast(test_file_path).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
result.static_import_expressions,
|
||||
@@ -1272,7 +1338,7 @@ import('./dynamic-import.vue')
|
||||
.unwrap();
|
||||
|
||||
let result = results.get(0).unwrap();
|
||||
let ast_results: ImportResult = find_imports_with_ast(test_file_path);
|
||||
let ast_results: ImportResult = find_imports_with_ast(test_file_path).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
result.static_import_expressions,
|
||||
@@ -1284,8 +1350,60 @@ import('./dynamic-import.vue')
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn should_find_imports_properly_for_all_files_in_nx_repo() {
|
||||
let current_dir = env::current_dir().unwrap();
|
||||
|
||||
let mut ancestors = current_dir.ancestors();
|
||||
|
||||
ancestors.next();
|
||||
ancestors.next();
|
||||
let root = PathBuf::from(ancestors.next().unwrap());
|
||||
|
||||
let files = nx_walker(root.clone(), move |receiver| {
|
||||
let mut files = vec![];
|
||||
let glob = build_glob_set(&["**/*.[jt]s"]).unwrap();
|
||||
for (path, _) in receiver {
|
||||
if glob.is_match(&path) {
|
||||
files.push(root.join(path).to_normalized_string());
|
||||
}
|
||||
}
|
||||
files
|
||||
});
|
||||
|
||||
let results: HashMap<_, _> =
|
||||
find_imports(HashMap::from([(String::from("nx"), files.clone())]))
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|import_result| (import_result.file.clone(), import_result))
|
||||
.collect();
|
||||
|
||||
let ast_results: HashMap<_, _> = files
|
||||
.into_iter()
|
||||
.filter_map(|p| find_imports_with_ast(p).ok())
|
||||
.map(|import_result| (import_result.file.clone(), import_result))
|
||||
.collect();
|
||||
|
||||
for (path, import_result) in results {
|
||||
let ast_result = ast_results.get(&path);
|
||||
|
||||
if let Some(ast_result) = ast_result {
|
||||
dbg!(&path, &import_result, &ast_result);
|
||||
assert_eq!(
|
||||
import_result.static_import_expressions,
|
||||
ast_result.static_import_expressions
|
||||
);
|
||||
assert_eq!(
|
||||
import_result.dynamic_import_expressions,
|
||||
ast_result.dynamic_import_expressions
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This function finds imports with the ast which verifies that the imports we find are the same as the ones typescript finds
|
||||
fn find_imports_with_ast(file_path: String) -> ImportResult {
|
||||
fn find_imports_with_ast(file_path: String) -> anyhow::Result<ImportResult> {
|
||||
let cm = Arc::<SourceMap>::default()
|
||||
.load_file(Path::new(file_path.as_str()))
|
||||
.unwrap();
|
||||
@@ -1306,7 +1424,7 @@ import('./dynamic-import.vue')
|
||||
None,
|
||||
&mut errs,
|
||||
)
|
||||
.unwrap();
|
||||
.map_err(|_| anyhow::anyhow!("Failed to create ast"))?;
|
||||
|
||||
let comments = NoopComments;
|
||||
let deps = swc_ecma_dep_graph::analyze_dependencies(&module, &comments);
|
||||
@@ -1333,11 +1451,11 @@ import('./dynamic-import.vue')
|
||||
static_import_expressions.push(dep.specifier.to_string());
|
||||
}
|
||||
}
|
||||
ImportResult {
|
||||
Ok(ImportResult {
|
||||
source_project: String::from("source"),
|
||||
file: file_path,
|
||||
static_import_expressions,
|
||||
dynamic_import_expressions,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
use ignore::WalkBuilder;
|
||||
use ignore_files::IgnoreFile;
|
||||
use once_cell::sync::Lazy;
|
||||
use os_type::{OSInformation, OSType};
|
||||
use std::{fs, path::PathBuf};
|
||||
use tracing::trace;
|
||||
use watchexec_events::{Event, Tag};
|
||||
@@ -56,10 +54,8 @@ pub(super) fn get_ignore_files<T: AsRef<str>>(root: T) -> Vec<IgnoreFile> {
|
||||
// .collect()
|
||||
// }
|
||||
|
||||
static OS_PLATFORM: Lazy<OSInformation> = Lazy::new(os_type::current_platform);
|
||||
|
||||
pub(super) fn transform_event(watch_event: &Event) -> Option<Event> {
|
||||
if OS_PLATFORM.os_type == OSType::Debian || OS_PLATFORM.os_type == OSType::Arch {
|
||||
if cfg!(linux) {
|
||||
let tags = watch_event
|
||||
.tags
|
||||
.clone()
|
||||
|
||||
@@ -23,7 +23,10 @@ export async function normalizeProjectNodes(
|
||||
nxJson: NxJsonConfiguration
|
||||
) {
|
||||
const toAdd = [];
|
||||
const projects = Object.keys(ctx.projects);
|
||||
// Sorting projects by name to make sure that the order of projects in the graph is deterministic.
|
||||
// This is important to ensure that expanded properties referencing projects (e.g. implicit dependencies)
|
||||
// are also deterministic, and thus don't cause the calculated project configuration hash to shift.
|
||||
const projects = Object.keys(ctx.projects).sort();
|
||||
|
||||
// Used for expanding implicit dependencies (e.g. `@proj/*` or `tag:foo`)
|
||||
const partialProjectGraphNodes = projects.reduce((graph, project) => {
|
||||
|
||||
@@ -258,7 +258,9 @@ function buildAllWorkspaceFiles(
|
||||
): FileData[] {
|
||||
performance.mark('get-all-workspace-files:start');
|
||||
let fileData: FileData[] = Object.values(projectFileMap).flat();
|
||||
fileData = fileData.concat(globalFiles).sort();
|
||||
fileData = fileData
|
||||
.concat(globalFiles)
|
||||
.sort((a, b) => a.file.localeCompare(b.file));
|
||||
performance.mark('get-all-workspace-files:end');
|
||||
performance.measure(
|
||||
'get-all-workspace-files',
|
||||
|
||||
@@ -25,6 +25,7 @@ export interface WorkspaceTypeAndRoot {
|
||||
|
||||
function isAngularCliInstalled(root: string): boolean {
|
||||
try {
|
||||
// nx-ignore-next-line
|
||||
require.resolve('@angular/cli', {
|
||||
paths: [root],
|
||||
});
|
||||
|
||||
@@ -22,6 +22,7 @@ export interface PackageManagerCommands {
|
||||
addDev: string;
|
||||
rm: string;
|
||||
exec: string;
|
||||
dlx: string;
|
||||
list: string;
|
||||
run: (script: string, args: string) => string;
|
||||
}
|
||||
@@ -74,13 +75,14 @@ export function getPackageManagerCommand(
|
||||
addDev: useBerry ? 'yarn add -D' : 'yarn add -D -W',
|
||||
rm: 'yarn remove',
|
||||
exec: 'yarn',
|
||||
dlx: useBerry ? 'yarn dlx' : 'yarn',
|
||||
run: (script: string, args: string) => `yarn ${script} ${args}`,
|
||||
list: useBerry ? 'yarn info --name-only' : 'yarn list',
|
||||
};
|
||||
},
|
||||
pnpm: () => {
|
||||
const pnpmVersion = getPackageManagerVersion('pnpm', root);
|
||||
const useExec = gte(pnpmVersion, '6.13.0');
|
||||
const modernPnpm = gte(pnpmVersion, '6.13.0');
|
||||
const includeDoubleDashBeforeArgs = lt(pnpmVersion, '7.0.0');
|
||||
const isPnpmWorkspace = existsSync(join(root, 'pnpm-workspace.yaml'));
|
||||
|
||||
@@ -90,7 +92,8 @@ export function getPackageManagerCommand(
|
||||
add: isPnpmWorkspace ? 'pnpm add -w' : 'pnpm add',
|
||||
addDev: isPnpmWorkspace ? 'pnpm add -Dw' : 'pnpm add -D',
|
||||
rm: 'pnpm rm',
|
||||
exec: useExec ? 'pnpm exec' : 'pnpx',
|
||||
exec: modernPnpm ? 'pnpm exec' : 'pnpx',
|
||||
dlx: modernPnpm ? 'pnpm dlx' : 'pnpx',
|
||||
run: (script: string, args: string) =>
|
||||
includeDoubleDashBeforeArgs
|
||||
? `pnpm run ${script} -- ${args}`
|
||||
@@ -109,6 +112,7 @@ export function getPackageManagerCommand(
|
||||
addDev: 'npm install -D',
|
||||
rm: 'npm rm',
|
||||
exec: 'npx',
|
||||
dlx: 'npx',
|
||||
run: (script: string, args: string) => `npm run ${script} -- ${args}`,
|
||||
list: 'npm ls',
|
||||
};
|
||||
|
||||
@@ -1743,6 +1743,44 @@ describe('params', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should use a multiselect if type is array and x-prompt uses shorthand', () => {
|
||||
const prompts = getPromptsForSchema(
|
||||
{},
|
||||
{
|
||||
properties: {
|
||||
pets: {
|
||||
type: 'array',
|
||||
'x-prompt': 'What kind of pets do you have?',
|
||||
items: {
|
||||
enum: ['cat', 'dog', 'fish'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
version: 2,
|
||||
projects: {},
|
||||
}
|
||||
);
|
||||
|
||||
expect(prompts).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"choices": [
|
||||
"cat",
|
||||
"dog",
|
||||
"fish",
|
||||
],
|
||||
"limit": 10,
|
||||
"message": "What kind of pets do you have?",
|
||||
"name": "pets",
|
||||
"type": "multiselect",
|
||||
"validate": [Function],
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
describe('Project prompts', () => {
|
||||
it('should use an autocomplete prompt for a property named project', () => {
|
||||
const prompts = getPromptsForSchema(
|
||||
|
||||
@@ -785,10 +785,23 @@ export function getPromptsForSchema(
|
||||
// Normalize x-prompt
|
||||
if (typeof v['x-prompt'] === 'string') {
|
||||
const message = v['x-prompt'];
|
||||
v['x-prompt'] = {
|
||||
type: v.type === 'boolean' ? 'confirm' : 'input',
|
||||
message,
|
||||
};
|
||||
if (v.type === 'boolean') {
|
||||
v['x-prompt'] = {
|
||||
type: 'confirm',
|
||||
message,
|
||||
};
|
||||
} else if (v.type === 'array' && v.items?.enum) {
|
||||
v['x-prompt'] = {
|
||||
type: 'multiselect',
|
||||
items: v.items.enum,
|
||||
message,
|
||||
};
|
||||
} else {
|
||||
v['x-prompt'] = {
|
||||
type: 'input',
|
||||
message,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
question.message = v['x-prompt'].message;
|
||||
|
||||
@@ -46,7 +46,7 @@ export async function configurationGenerator(
|
||||
js: options.js,
|
||||
directory: options.directory,
|
||||
setParserOptionsProject: options.setParserOptionsProject,
|
||||
rootProject: projectConfig.root === '.',
|
||||
rootProject: options.rootProject ?? projectConfig.root === '.',
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -21,4 +21,5 @@ export interface ConfigurationGeneratorSchema {
|
||||
* @example: "http://localhost:4200"
|
||||
**/
|
||||
webServerAddress?: string;
|
||||
rootProject?: boolean;
|
||||
}
|
||||
|
||||
@@ -55,6 +55,13 @@
|
||||
"default": false,
|
||||
"description": "Do not add dependencies to `package.json`.",
|
||||
"x-priority": "internal"
|
||||
},
|
||||
"rootProject": {
|
||||
"description": "Create a application at the root of the workspace",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"hidden": true,
|
||||
"x-priority": "internal"
|
||||
}
|
||||
},
|
||||
"required": ["project"]
|
||||
|
||||
@@ -51,7 +51,7 @@ describe('NxPlugin e2e-project Generator', () => {
|
||||
|
||||
expect(tree.exists('apps/my-plugin-e2e/tsconfig.json')).toBeTruthy();
|
||||
expect(
|
||||
tree.exists('apps/my-plugin-e2e/tests/my-plugin.spec.ts')
|
||||
tree.exists('apps/my-plugin-e2e/src/my-plugin.spec.ts')
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ async function addJest(host: Tree, options: NormalizedSchema) {
|
||||
addProjectConfiguration(host, options.projectName, {
|
||||
root: options.projectRoot,
|
||||
projectType: 'application',
|
||||
sourceRoot: `${options.projectRoot}/tests`,
|
||||
sourceRoot: `${options.projectRoot}/src`,
|
||||
targets: {},
|
||||
implicitDependencies: [options.pluginName],
|
||||
});
|
||||
|
||||
@@ -43,6 +43,7 @@ export async function addE2e(
|
||||
skipFormat: true,
|
||||
devServerTarget: `${options.projectName}:serve`,
|
||||
jsx: true,
|
||||
rootProject: options.rootProject,
|
||||
});
|
||||
}
|
||||
case 'playwright': {
|
||||
@@ -68,6 +69,7 @@ export async function addE2e(
|
||||
options.name
|
||||
}`,
|
||||
webServerAddress: 'http://localhost:4200',
|
||||
rootProject: options.rootProject,
|
||||
});
|
||||
}
|
||||
case 'none':
|
||||
|
||||
@@ -12,22 +12,22 @@
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "The name of the module.",
|
||||
"path": {
|
||||
"type": "string",
|
||||
"$default": {
|
||||
"$source": "argv",
|
||||
"index": 0
|
||||
},
|
||||
"description": "The path to locate the federated module. This path should be relative to the workspace root and the file should exist.",
|
||||
"x-prompt": "What is the path to the module to be federated?"
|
||||
},
|
||||
"name": {
|
||||
"description": "The name of the module.",
|
||||
"type": "string",
|
||||
"x-prompt": "What name would you like to use for the module?",
|
||||
"pattern": "^[a-zA-Z][^:]*$",
|
||||
"x-priority": "important"
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "The path to locate the federated module. This path should be relative to the workspace root and the file should exist.",
|
||||
"x-prompt": "What is the path to the module to be federated?"
|
||||
},
|
||||
"remote": {
|
||||
"type": "string",
|
||||
"description": "The name of the remote.",
|
||||
|
||||
@@ -19,6 +19,10 @@ const knownLocations = [
|
||||
'pages/styles.css',
|
||||
'pages/styles.scss',
|
||||
'pages/styles.less',
|
||||
|
||||
'app/global.css',
|
||||
'app/global.scss',
|
||||
'app/global.less',
|
||||
];
|
||||
|
||||
export function addTailwindStyleImports(
|
||||
|
||||
@@ -8,8 +8,8 @@ export const reactDomVersion = '18.2.0';
|
||||
export const reactIsVersion = '18.2.0';
|
||||
export const swcLoaderVersion = '0.1.15';
|
||||
export const babelLoaderVersion = '^9.1.2';
|
||||
export const typesReactVersion = '18.2.24';
|
||||
export const typesReactDomVersion = '18.2.9';
|
||||
export const typesReactVersion = '18.2.33';
|
||||
export const typesReactDomVersion = '18.2.14';
|
||||
export const typesReactIsVersion = '18.2.2';
|
||||
|
||||
export const typesNodeVersion = '18.14.2';
|
||||
|
||||
@@ -11,9 +11,9 @@ exports[`@nx/storybook:init dependencies for package.json should add angular rel
|
||||
"@angular/forms": "*",
|
||||
"@nx/js": "0.0.1",
|
||||
"@nx/storybook": "0.0.1",
|
||||
"@storybook/addon-essentials": "7.2.2",
|
||||
"@storybook/angular": "7.2.2",
|
||||
"@storybook/core-server": "7.2.2",
|
||||
"@storybook/addon-essentials": "7.5.3",
|
||||
"@storybook/angular": "7.5.3",
|
||||
"@storybook/core-server": "7.5.3",
|
||||
"@swc-node/register": "~1.6.7",
|
||||
"@swc/core": "~1.3.85",
|
||||
"existing": "1.0.0",
|
||||
|
||||
@@ -15,7 +15,7 @@ export function callUpgrade(schema: Schema): 1 | Buffer {
|
||||
});
|
||||
|
||||
execSync(
|
||||
`${pm.exec} storybook@latest upgrade ${
|
||||
`${pm.dlx} storybook@latest upgrade ${
|
||||
schema.autoAcceptAllPrompts ? '--yes' : ''
|
||||
}`,
|
||||
{
|
||||
@@ -73,7 +73,7 @@ export function callAutomigrate(
|
||||
Object.entries(allStorybookProjects).forEach(
|
||||
([projectName, storybookProjectInfo]) => {
|
||||
const pm = getPackageManagerCommand();
|
||||
const commandToRun = `${pm.exec} storybook@latest automigrate --config-dir ${storybookProjectInfo.configDir} --renderer ${storybookProjectInfo.uiFramework}`;
|
||||
const commandToRun = `${pm.dlx} storybook@latest automigrate --config-dir ${storybookProjectInfo.configDir} --renderer ${storybookProjectInfo.uiFramework}`;
|
||||
try {
|
||||
output.log({
|
||||
title: `Calling sb automigrate for ${projectName}`,
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
"test": {
|
||||
"executor": "@nx/jest:jest",
|
||||
"options": {
|
||||
"jestConfig": "packages/vite/jest.config.ts",
|
||||
"passWithNoTests": true
|
||||
"jestConfig": "packages/vite/jest.config.ts"
|
||||
},
|
||||
"outputs": ["{workspaceRoot}/coverage/packages/vite"]
|
||||
},
|
||||
|
||||
@@ -805,7 +805,7 @@ function handleViteConfigFileExists(
|
||||
cache: {
|
||||
dir: `${offsetFromRoot}node_modules/.vitest`,
|
||||
},
|
||||
environment: 'jsdom',
|
||||
environment: options.testEnvironment ?? 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
};
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
"nx",
|
||||
"typescript",
|
||||
"@nx/cypress",
|
||||
"@nx/jest",
|
||||
"@nx/playwright",
|
||||
"@nx/storybook"
|
||||
]
|
||||
|
||||
@@ -9,6 +9,5 @@ export {
|
||||
} from './src/generators/stories/stories';
|
||||
export { type InitSchema } from './src/generators/init/schema';
|
||||
export { vueInitGenerator } from './src/generators/init/init';
|
||||
export { addJest } from './src/generators/application/lib/add-jest';
|
||||
export * from './src/utils/versions';
|
||||
export * from './src/utils/add-linting';
|
||||
|
||||
@@ -34,8 +34,7 @@
|
||||
"@nx/js": "file:../js",
|
||||
"@nx/eslint": "file:../eslint",
|
||||
"@nx/vite": "file:../vite",
|
||||
"@nx/web": "file:../web",
|
||||
"@phenomnomnominal/tsquery": "~5.0.1"
|
||||
"@nx/web": "file:../web"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
"test": {
|
||||
"executor": "@nx/jest:jest",
|
||||
"options": {
|
||||
"jestConfig": "packages/vue/jest.config.ts",
|
||||
"passWithNoTests": true
|
||||
"jestConfig": "packages/vue/jest.config.ts"
|
||||
},
|
||||
"outputs": ["{workspaceRoot}/coverage/packages/vue"]
|
||||
},
|
||||
|
||||
@@ -14,7 +14,6 @@ import { addLinting } from '../../utils/add-linting';
|
||||
import { addE2e } from './lib/add-e2e';
|
||||
import { createApplicationFiles } from './lib/create-application-files';
|
||||
import { addVite } from './lib/add-vite';
|
||||
import { addJest } from './lib/add-jest';
|
||||
import { extractTsConfigBase } from '../../utils/create-ts-config';
|
||||
|
||||
export async function applicationGenerator(
|
||||
@@ -62,14 +61,6 @@ export async function applicationGenerator(
|
||||
|
||||
tasks.push(await addVite(tree, options));
|
||||
|
||||
if (options.unitTestRunner === 'jest')
|
||||
tasks.push(
|
||||
await addJest(tree, {
|
||||
name: options.name,
|
||||
projectRoot: options.appProjectRoot,
|
||||
})
|
||||
);
|
||||
|
||||
tasks.push(await addE2e(tree, options));
|
||||
|
||||
if (options.js) toJS(tree);
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
import {
|
||||
addDependenciesToPackageJson,
|
||||
ensurePackage,
|
||||
GeneratorCallback,
|
||||
runTasksInSerial,
|
||||
Tree,
|
||||
} from '@nx/devkit';
|
||||
import { nxVersion, vueJest3Version } from '../../../utils/versions';
|
||||
import { setupJestProject } from '../../../utils/setup-jest';
|
||||
|
||||
export async function addJest(
|
||||
tree: Tree,
|
||||
options: { name: string; projectRoot: string }
|
||||
): Promise<GeneratorCallback> {
|
||||
const tasks: GeneratorCallback[] = [];
|
||||
const { configurationGenerator } = ensurePackage<typeof import('@nx/jest')>(
|
||||
'@nx/jest',
|
||||
nxVersion
|
||||
);
|
||||
tasks.push(
|
||||
await configurationGenerator(tree, {
|
||||
project: options.name,
|
||||
skipFormat: true,
|
||||
testEnvironment: 'jsdom',
|
||||
compiler: 'babel',
|
||||
})
|
||||
);
|
||||
|
||||
setupJestProject(tree, options.projectRoot);
|
||||
|
||||
tasks.push(
|
||||
addDependenciesToPackageJson(
|
||||
tree,
|
||||
{},
|
||||
{
|
||||
'@vue/vue3-jest': vueJest3Version,
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
return runTasksInSerial(...tasks);
|
||||
}
|
||||
+1
-1
@@ -8,7 +8,7 @@ export interface Schema {
|
||||
directory?: string;
|
||||
projectNameAndRootFormat?: ProjectNameAndRootFormat;
|
||||
tags?: string;
|
||||
unitTestRunner?: 'jest' | 'vitest' | 'none';
|
||||
unitTestRunner?: 'vitest' | 'none';
|
||||
inSourceTests?: boolean;
|
||||
e2eTestRunner: 'cypress' | 'playwright' | 'none';
|
||||
linter: Linter;
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
},
|
||||
"unitTestRunner": {
|
||||
"type": "string",
|
||||
"enum": ["jest", "vitest", "none"],
|
||||
"enum": ["vitest", "none"],
|
||||
"description": "Test runner to use for unit tests.",
|
||||
"x-prompt": "Which unit test runner would you like to use?",
|
||||
"default": "vitest"
|
||||
|
||||
@@ -102,13 +102,7 @@
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"x-priority": "internal"
|
||||
},
|
||||
"unitTestRunner": {
|
||||
"type": "string",
|
||||
"enum": ["vitest", "jest", "none"],
|
||||
"description": "Test runner to use for unit tests.",
|
||||
"x-prompt": "What unit test runner should be used?"
|
||||
}
|
||||
},
|
||||
"required": ["name", "project"]
|
||||
"required": ["name"]
|
||||
}
|
||||
|
||||
@@ -27,151 +27,6 @@ exports[`lib nested should create a local tsconfig.json 1`] = `
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`lib should add correct jest.config.ts and dependencies to package.json 1`] = `
|
||||
{
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0",
|
||||
"vue": "^3.3.4",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nx/cypress": "0.0.1",
|
||||
"@nx/eslint": "0.0.1",
|
||||
"@nx/eslint-plugin": "0.0.1",
|
||||
"@nx/jest": "0.0.1",
|
||||
"@nx/js": "0.0.1",
|
||||
"@nx/rollup": "0.0.1",
|
||||
"@nx/vite": "0.0.1",
|
||||
"@nx/vue": "0.0.1",
|
||||
"@swc-node/register": "~1.6.7",
|
||||
"@swc/core": "~1.3.85",
|
||||
"@types/jest": "^29.4.0",
|
||||
"@types/node": "16.11.7",
|
||||
"@typescript-eslint/eslint-plugin": "^5.60.1",
|
||||
"@typescript-eslint/parser": "^5.60.1",
|
||||
"@vitejs/plugin-vue": "^4.3.1",
|
||||
"@vue/eslint-config-prettier": "7.1.0",
|
||||
"@vue/eslint-config-typescript": "^11.0.3",
|
||||
"@vue/test-utils": "^2.4.1",
|
||||
"@vue/tsconfig": "^0.4.0",
|
||||
"@vue/vue3-jest": "^29.2.6",
|
||||
"babel-jest": "^29.4.1",
|
||||
"eslint": "~8.46.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-vue": "^9.16.1",
|
||||
"jest": "^29.4.1",
|
||||
"jest-environment-jsdom": "^29.4.1",
|
||||
"prettier": "^2.6.2",
|
||||
"ts-jest": "^29.1.0",
|
||||
"ts-node": "10.9.1",
|
||||
"typescript": "~5.1.3",
|
||||
"vue-tsc": "^1.8.8",
|
||||
},
|
||||
"name": "@proj/source",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`lib should add correct jest.config.ts and dependencies to package.json 2`] = `
|
||||
{
|
||||
"ignorePatterns": [
|
||||
"**/*",
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"*.ts",
|
||||
"*.tsx",
|
||||
"*.js",
|
||||
"*.jsx",
|
||||
"*.vue",
|
||||
],
|
||||
"rules": {
|
||||
"@nx/enforce-module-boundaries": [
|
||||
"error",
|
||||
{
|
||||
"allow": [],
|
||||
"depConstraints": [
|
||||
{
|
||||
"onlyDependOnLibsWithTags": [
|
||||
"*",
|
||||
],
|
||||
"sourceTag": "*",
|
||||
},
|
||||
],
|
||||
"enforceBuildableLibDependency": true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"extends": [
|
||||
"plugin:@nx/typescript",
|
||||
],
|
||||
"files": [
|
||||
"*.ts",
|
||||
"*.tsx",
|
||||
],
|
||||
"rules": {},
|
||||
},
|
||||
{
|
||||
"extends": [
|
||||
"plugin:@nx/javascript",
|
||||
],
|
||||
"files": [
|
||||
"*.js",
|
||||
"*.jsx",
|
||||
],
|
||||
"rules": {},
|
||||
},
|
||||
{
|
||||
"env": {
|
||||
"jest": true,
|
||||
},
|
||||
"files": [
|
||||
"*.spec.ts",
|
||||
"*.spec.tsx",
|
||||
"*.spec.js",
|
||||
"*.spec.jsx",
|
||||
],
|
||||
"rules": {},
|
||||
},
|
||||
],
|
||||
"plugins": [
|
||||
"@nx",
|
||||
],
|
||||
"root": true,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`lib should add correct jest.config.ts and dependencies to package.json 3`] = `
|
||||
"/* eslint-disable */
|
||||
export default {
|
||||
displayName: 'my-lib',
|
||||
preset: '../jest.preset.js',
|
||||
|
||||
coverageDirectory: '../coverage/my-lib',
|
||||
moduleFileExtensions: ['js', 'ts', 'json', 'vue'],
|
||||
transform: {
|
||||
'^.+.[tj]sx?$': ['babel-jest'],
|
||||
'^.+.vue$': [
|
||||
'@vue/vue3-jest',
|
||||
{
|
||||
tsConfig: './tsconfig.spec.json',
|
||||
},
|
||||
],
|
||||
},
|
||||
testEnvironment: 'jsdom',
|
||||
testMatch: ['**/*.spec.ts?(x)', '**/__tests__/*.ts?(x)'],
|
||||
};
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib should add correct jest.config.ts and dependencies to package.json 4`] = `
|
||||
"{
|
||||
"presets": ["@nx/js/babel"]
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`lib should add vite types to tsconfigs and generate correct vite.config.ts file 1`] = `
|
||||
"/// <reference types='vitest' />
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
import {
|
||||
addDependenciesToPackageJson,
|
||||
ensurePackage,
|
||||
GeneratorCallback,
|
||||
runTasksInSerial,
|
||||
Tree,
|
||||
} from '@nx/devkit';
|
||||
|
||||
import { nxVersion, vueJest3Version } from '../../../utils/versions';
|
||||
import { setupJestProject } from '../../../utils/setup-jest';
|
||||
import { NormalizedSchema } from '../schema';
|
||||
|
||||
export async function addJest(
|
||||
tree: Tree,
|
||||
options: NormalizedSchema
|
||||
): Promise<GeneratorCallback> {
|
||||
const tasks: GeneratorCallback[] = [];
|
||||
const { configurationGenerator } = ensurePackage<typeof import('@nx/jest')>(
|
||||
'@nx/jest',
|
||||
nxVersion
|
||||
);
|
||||
const jestTask = await configurationGenerator(tree, {
|
||||
project: options.name,
|
||||
skipFormat: true,
|
||||
testEnvironment: 'jsdom',
|
||||
compiler: 'babel',
|
||||
});
|
||||
tasks.push(jestTask);
|
||||
|
||||
setupJestProject(tree, options.projectRoot);
|
||||
tasks.push(
|
||||
addDependenciesToPackageJson(
|
||||
tree,
|
||||
{},
|
||||
{
|
||||
'@vue/vue3-jest': vueJest3Version,
|
||||
}
|
||||
)
|
||||
);
|
||||
return runTasksInSerial(...tasks);
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
import type { Tree } from '@nx/devkit';
|
||||
import { Linter } from '@nx/eslint';
|
||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||
import { normalizeOptions } from './normalize-options';
|
||||
|
||||
describe('normalizeOptions', () => {
|
||||
let tree: Tree;
|
||||
|
||||
beforeEach(() => {
|
||||
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||
});
|
||||
|
||||
it('should set unitTestRunner=jest and bundler=none by default', async () => {
|
||||
const options = await normalizeOptions(tree, {
|
||||
name: 'test',
|
||||
linter: Linter.None,
|
||||
unitTestRunner: 'vitest',
|
||||
});
|
||||
|
||||
expect(options).toMatchObject({
|
||||
bundler: 'none',
|
||||
unitTestRunner: 'vitest',
|
||||
});
|
||||
});
|
||||
|
||||
it('should set unitTestRunner=vitest by default when bundler is vite', async () => {
|
||||
const options = await normalizeOptions(tree, {
|
||||
name: 'test',
|
||||
linter: Linter.None,
|
||||
bundler: 'vite',
|
||||
unitTestRunner: 'vitest',
|
||||
});
|
||||
|
||||
expect(options).toMatchObject({
|
||||
bundler: 'vite',
|
||||
unitTestRunner: 'vitest',
|
||||
});
|
||||
});
|
||||
|
||||
it('should set maintain unitTestRunner when bundler is vite', async () => {
|
||||
const options = await normalizeOptions(tree, {
|
||||
name: 'test',
|
||||
linter: Linter.None,
|
||||
bundler: 'vite',
|
||||
unitTestRunner: 'vitest',
|
||||
});
|
||||
|
||||
expect(options).toMatchObject({
|
||||
bundler: 'vite',
|
||||
unitTestRunner: 'vitest',
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -84,14 +84,6 @@ describe('lib', () => {
|
||||
expect(readJson(tree, '/package.json')).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should add correct jest.config.ts and dependencies to package.json', async () => {
|
||||
await libraryGenerator(tree, { ...defaultSchema, unitTestRunner: 'jest' });
|
||||
expect(readJson(tree, '/package.json')).toMatchSnapshot();
|
||||
expect(readJson(tree, '.eslintrc.json')).toMatchSnapshot();
|
||||
expect(tree.read('my-lib/jest.config.ts', 'utf-8')).toMatchSnapshot();
|
||||
expect(tree.read('my-lib/.babelrc', 'utf-8')).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should update root tsconfig.base.json', async () => {
|
||||
await libraryGenerator(tree, defaultSchema);
|
||||
const tsconfigJson = readJson(tree, '/tsconfig.base.json');
|
||||
|
||||
@@ -17,7 +17,6 @@ import { createLibraryFiles } from './lib/create-library-files';
|
||||
import { extractTsConfigBase } from '../../utils/create-ts-config';
|
||||
import componentGenerator from '../component/component';
|
||||
import { addVite } from './lib/add-vite';
|
||||
import { addJest } from './lib/add-jest';
|
||||
|
||||
export async function libraryGenerator(tree: Tree, schema: Schema) {
|
||||
const tasks: GeneratorCallback[] = [];
|
||||
@@ -52,9 +51,6 @@ export async function libraryGenerator(tree: Tree, schema: Schema) {
|
||||
|
||||
tasks.push(await addVite(tree, options));
|
||||
|
||||
if (options.unitTestRunner === 'jest')
|
||||
tasks.push(await addJest(tree, options));
|
||||
|
||||
if (options.component) {
|
||||
await componentGenerator(tree, {
|
||||
name: options.name,
|
||||
|
||||
+2
-2
@@ -22,7 +22,7 @@ export interface Schema {
|
||||
skipTsConfig?: boolean;
|
||||
strict?: boolean;
|
||||
tags?: string;
|
||||
unitTestRunner?: 'jest' | 'vitest' | 'none';
|
||||
unitTestRunner?: 'vitest' | 'none';
|
||||
minimal?: boolean;
|
||||
e2eTestRunner?: 'cypress' | 'none';
|
||||
}
|
||||
@@ -37,5 +37,5 @@ export interface NormalizedSchema extends Schema {
|
||||
parsedTags: string[];
|
||||
appMain?: string;
|
||||
appSourceRoot?: string;
|
||||
unitTestRunner?: 'jest' | 'vitest' | 'none';
|
||||
unitTestRunner?: 'vitest' | 'none';
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
},
|
||||
"unitTestRunner": {
|
||||
"type": "string",
|
||||
"enum": ["vitest", "jest", "none"],
|
||||
"enum": ["vitest", "none"],
|
||||
"description": "Test runner to use for unit tests.",
|
||||
"x-prompt": "What unit test runner should be used?"
|
||||
},
|
||||
|
||||
@@ -116,7 +116,7 @@ export async function createTestUILib(libName: string): Promise<Tree> {
|
||||
component: true,
|
||||
skipFormat: true,
|
||||
skipTsConfig: false,
|
||||
unitTestRunner: 'jest',
|
||||
unitTestRunner: 'vitest',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
});
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ export async function addLinting(
|
||||
linter: Linter;
|
||||
name: string;
|
||||
projectRoot: string;
|
||||
unitTestRunner?: 'jest' | 'vitest' | 'none';
|
||||
unitTestRunner?: 'vitest' | 'none';
|
||||
setParserOptionsProject?: boolean;
|
||||
skipPackageJson?: boolean;
|
||||
rootProject?: boolean;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user