🎯 MapView v2.0 - Global Deployment Ready

 MAJOR FEATURES:
• Auto-zoom intelligence với smart bounds fitting
• Enhanced 3D GPS markers với pulsing effects
• Professional route display với 6-layer rendering
• Status-based parking icons với availability indicators
• Production-ready build optimizations

🗺️ AUTO-ZOOM FEATURES:
• Smart bounds fitting cho GPS + selected parking
• Adaptive padding (50px) cho visual balance
• Max zoom control (level 16) để tránh quá gần
• Dynamic centering khi không có selection

🎨 ENHANCED VISUALS:
• 3D GPS marker với multi-layer pulse effects
• Advanced parking icons với status colors
• Selection highlighting với animation
• Dimming system cho non-selected items

🛣️ ROUTE SYSTEM:
• OpenRouteService API integration
• Multi-layer route rendering (glow, shadow, main, animated)
• Real-time distance & duration calculation
• Visual route info trong popup

📱 PRODUCTION READY:
• SSR safe với dynamic imports
• Build errors resolved
• Global deployment via Vercel
• Optimized performance

🌍 DEPLOYMENT:
• Vercel: https://whatever-ctk2auuxr-phong12hexdockworks-projects.vercel.app
• Bundle size: 22.8 kB optimized
• Global CDN distribution
• HTTPS enabled

💾 VERSION CONTROL:
• MapView-v2.0.tsx backup created
• MAPVIEW_VERSIONS.md documentation
• Full version history tracking
This commit is contained in:
2025-07-20 19:52:16 +07:00
parent 3203463a6a
commit c65cc97a33
64624 changed files with 7199453 additions and 6462 deletions

64
backend/node_modules/@nestjs/cli/.circleci/config.yml generated vendored Normal file
View File

@@ -0,0 +1,64 @@
version: 2
aliases:
- &restore-cache
restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- &install-deps
run:
name: Install dependencies
command: npm ci --ignore-scripts
- &build-packages
run:
name: Build
command: npm run build
- &run-unit-tests
run:
name: Test
command: npm run test -- --runInBand --no-cache
jobs:
build:
working_directory: ~/nest
docker:
- image: cimg/node:22.3
steps:
- checkout
- run:
name: Update NPM version
command: sudo npm install -g npm@latest
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: Install dependencies
command: npm ci --ignore-scripts
- save_cache:
key: dependency-cache-{{ checksum "package.json" }}
paths:
- ./node_modules
- run:
name: Build
command: npm run build
unit_tests:
working_directory: ~/nest
docker:
- image: cimg/node:22.3
steps:
- checkout
- *restore-cache
- *install-deps
- *build-packages
- run:
name: Clean build artifacts
command: npm run clean
- *run-unit-tests
workflows:
version: 2
build-and-test:
jobs:
- build
- unit_tests:
requires:
- build

View File

@@ -0,0 +1,106 @@
name: "\U0001F41B Bug Report"
description: "If something isn't working as expected \U0001F914"
labels: ["needs triage", "bug"]
body:
- type: markdown
attributes:
value: |
## :warning: We use GitHub Issues to track bug reports, feature requests and regressions
If you are not sure that your issue is a bug, you could:
- use our [Discord community](https://discord.gg/NestJS)
- use [StackOverflow using the tag `nestjs`](https://stackoverflow.com/questions/tagged/nestjs)
- If it's just a quick question you can ping [our Twitter](https://twitter.com/nestframework)
**NOTE:** You don't need to answer questions that you know that aren't relevant.
---
- type: checkboxes
attributes:
label: "Is there an existing issue for this?"
description: "Please search [here](./?q=is%3Aissue) to see if an issue already exists for the bug you encountered"
options:
- label: "I have searched the existing issues"
required: true
- type: textarea
validations:
required: true
attributes:
label: "Current behavior"
description: "How the issue manifests?"
- type: input
validations:
required: true
attributes:
label: "Minimum reproduction code"
description: "An URL to some git repository or gist that reproduces this issue. [Wtf is a minimum reproduction?](https://jmcdo29.github.io/wtf-is-a-minimum-reproduction)"
placeholder: "https://github.com/..."
- type: textarea
attributes:
label: "Steps to reproduce"
description: |
How the issue manifests?
You could leave this blank if you alread write this in your reproduction code/repo
placeholder: |
1. `npm i`
2. `npm start:dev`
3. See error...
- type: textarea
validations:
required: true
attributes:
label: "Expected behavior"
description: "A clear and concise description of what you expected to happend (or code)"
- type: markdown
attributes:
value: |
---
- type: input
validations:
required: true
attributes:
label: "Package version"
description: |
Which version of `@nestjs/cli` are you using?
**Tip**: Make sure that all of yours `@nestjs/*` dependencies are in sync!
placeholder: "8.1.3"
- type: input
attributes:
label: "NestJS version"
description: "Which version of `@nestjs/core` are you using?"
placeholder: "8.1.3"
- type: input
attributes:
label: "Node.js version"
description: "Which version of Node.js are you using?"
placeholder: "14.17.6"
- type: checkboxes
attributes:
label: "In which operating systems have you tested?"
options:
- label: macOS
- label: Windows
- label: Linux
- type: markdown
attributes:
value: |
---
- type: textarea
attributes:
label: "Other"
description: |
Anything else relevant? eg: Logs, OS version, IDE, package manager, etc.
**Tip:** You can attach images, recordings or log files by clicking this area to highlight it and then dragging files in

View File

@@ -0,0 +1,52 @@
name: "\U0001F680 Feature Request"
description: "I have a suggestion \U0001F63B!"
labels: ["feature"]
body:
- type: markdown
attributes:
value: |
## :warning: We use GitHub Issues to track bug reports, feature requests and regressions
If you are not sure that your issue is a bug, you could:
- use our [Discord community](https://discord.gg/NestJS)
- use [StackOverflow using the tag `nestjs`](https://stackoverflow.com/questions/tagged/nestjs)
- If it's just a quick question you can ping [our Twitter](https://twitter.com/nestframework)
---
- type: checkboxes
attributes:
label: "Is there an existing issue that is already proposing this?"
description: "Please search [here](./?q=is%3Aissue) to see if an issue already exists for the feature you are requesting"
options:
- label: "I have searched the existing issues"
required: true
- type: textarea
validations:
required: true
attributes:
label: "Is your feature request related to a problem? Please describe it"
description: "A clear and concise description of what the problem is"
placeholder: |
I have an issue when ...
- type: textarea
validations:
required: true
attributes:
label: "Describe the solution you'd like"
description: "A clear and concise description of what you want to happen. Add any considered drawbacks"
- type: textarea
attributes:
label: "Teachability, documentation, adoption, migration strategy"
description: "If you can, explain how users will be able to use this and possibly write out a version the docs. Maybe a screenshot or design?"
- type: textarea
validations:
required: true
attributes:
label: "What is the motivation / use case for changing the behavior?"
description: "Describe the motivation or the concrete use case"

View File

@@ -0,0 +1,78 @@
name: "\U0001F4A5 Regression"
description: "Report an unexpected behavior while upgrading your Nest application!"
labels: ["needs triage"]
body:
- type: markdown
attributes:
value: |
## :warning: We use GitHub Issues to track bug reports, feature requests and regressions
If you are not sure that your issue is a bug, you could:
- use our [Discord community](https://discord.gg/NestJS)
- use [StackOverflow using the tag `nestjs`](https://stackoverflow.com/questions/tagged/nestjs)
- If it's just a quick question you can ping [our Twitter](https://twitter.com/nestframework)
**NOTE:** You don't need to answer questions that you know that aren't relevant.
---
- type: checkboxes
attributes:
label: "Did you read the migration guide?"
description: "Check out the [migration guide here](https://docs.nestjs.com/migration-guide)!"
options:
- label: "I have read the whole migration guide"
required: false
- type: checkboxes
attributes:
label: "Is there an existing issue that is already proposing this?"
description: "Please search [here](./?q=is%3Aissue) to see if an issue already exists for the feature you are requesting"
options:
- label: "I have searched the existing issues"
required: true
- type: input
attributes:
label: "Potential Commit/PR that introduced the regression"
description: "If you have time to investigate, what PR/date/version introduced this issue"
placeholder: "PR #123 or commit 5b3c4a4"
- type: input
attributes:
label: "Versions"
description: "From which version of `@nestjs/cli` to which version you are upgrading"
placeholder: "8.1.0 -> 8.1.3"
- type: textarea
validations:
required: true
attributes:
label: "Describe the regression"
description: "A clear and concise description of what the regression is"
- type: textarea
attributes:
label: "Minimum reproduction code"
description: |
Please share a git repo, a gist, or step-by-step instructions. [Wtf is a minimum reproduction?](https://jmcdo29.github.io/wtf-is-a-minimum-reproduction)
**Tip:** If you leave a minimum repository, we will understand your issue faster!
value: |
```ts
```
- type: textarea
validations:
required: true
attributes:
label: "Expected behavior"
description: "A clear and concise description of what you expected to happend (or code)"
- type: textarea
attributes:
label: "Other"
description: |
Anything else relevant? eg: Logs, OS version, IDE, package manager, etc.
**Tip:** You can attach images, recordings or log files by clicking this area to highlight it and then dragging files in

View File

@@ -0,0 +1,7 @@
## To encourage contributors to use issue templates, we don't allow blank issues
blank_issues_enabled: false
contact_links:
- name: "\u2753 Discord Community of NestJS"
url: "https://discord.gg/NestJS"
about: "Please ask support questions or discuss suggestions/enhancements here."

View File

@@ -0,0 +1,41 @@
## PR Checklist
Please check if your PR fulfills the following requirements:
- [ ] The commit message follows our guidelines: https://github.com/nestjs/nest/blob/master/CONTRIBUTING.md
- [ ] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)
## PR Type
What kind of change does this PR introduce?
<!-- Please check the one that applies to this PR using "x". -->
```
[ ] Bugfix
[ ] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Build related changes
[ ] CI related changes
[ ] Other... Please describe:
```
## What is the current behavior?
<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->
Issue Number: N/A
## What is the new behavior?
## Does this PR introduce a breaking change?
```
[ ] Yes
[ ] No
```
<!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. -->
## Other information

1
backend/node_modules/@nestjs/cli/.husky/commit-msg generated vendored Executable file
View File

@@ -0,0 +1 @@
npx --no-install commitlint --edit $1

1
backend/node_modules/@nestjs/cli/.husky/pre-commit generated vendored Executable file
View File

@@ -0,0 +1 @@
npx --no-install lint-staged

226
backend/node_modules/@nestjs/cli/CONTRIBUTING.md generated vendored Normal file
View File

@@ -0,0 +1,226 @@
# Contributing to Nest CLI
We would love for you to contribute to Nest and help make it even better than it is today! As a contributor, here are the guidelines we would like you to follow :
- [Question or Problem?](#question)
- [Issues and Bugs](#issue)
- [Feature Requests](#feature)
- [Submission Guidelines](#submit)
## <a name="question"></a> Got a Question or Problem ?
**Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests.** You've got much better chances of getting your question answered on Stack Overflow where the questions should be tagged with tag nestjs.
[Stack Overflow](https://stackoverflow.com/questions/tagged/nestjs) is a much better place to ask questions since:
- questions and answers stay available for public viewing so your question / answer might help someone else
- Stack Overflow's voting system assures that the best answers are prominently visible.
To save your and our time, we will systematically close all issues that are requests for general support and redirect people to Stack Overflow.
If you would like to chat about the question in real-time, you can reach out via [our discord channel][discord].
## <a name="issue"></a> Found a Bug?
If you find a bug in the source code, you can help us by
[submitting an issue](#submit-issue). Even better, you can [submit a Pull Request](#submit-pr) with a fix.
## <a name="feature"></a> Missing a Feature?
You can _request_ a new feature by [submitting an issue](#submit-issue) to our GitHub
Repository. If you would like to _implement_ a new feature, please submit an issue with
a proposal for your work first, to be sure that we can use it.
Please consider what kind of change it is:
- For a **Major Feature**, first open an issue and outline your proposal so that it can be
discussed. This will also allow us to better coordinate our efforts, prevent duplication of work,
and help you to craft the change so that it is successfully accepted into the project. For your issue name, please prefix your proposal with `[discussion]`, for example "[discussion]: your feature idea".
- **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
## <a name="submit"></a> Submission Guidelines
### <a name="submit-issue"></a> Submitting an Issue
Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs we will systematically ask you to provide a minimal reproduction scenario using a repository or [Gist](https://gist.github.com/). Having a live, reproducible scenario gives us wealth of important information without going back & forth to you with additional questions like:
- version of NestJS-CLI used (`nest info`)
- and most importantly - a use-case that fails
Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you we are going to close an issue that doesn't have enough info to be reproduced.
You can file new issues by filling out our [new issue form](https://github.com/nestjs/nest/issues/new).
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
Before you submit your Pull Request (PR) consider the following guidelines:
1. Search [GitHub](https://github.com/nestjs/nest/pulls) for an open or closed PR that relates to your submission. You don't want to duplicate effort.
1. Fork the nestjs/nest-cli repo.
1. Get a gpg key to sign your commits, see [help](https://help.github.com/articles/about-gpg/).
1. Create your patch, **including appropriate test cases**.
1. Commit your changes using a descriptive commit message
```shell
git commit -am "<message>"
```
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
1. Push your branch to GitHub:
```shell
git push origin my-fix-branch
```
Note: you can use -u to set your branch in upstream and just push for the next times.
1. In GitHub, send a pull request to `nestjs/nest-cli:master`.
- If we suggest changes then:
- Make the required updates.
- Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
```shell
git rebase master -i
git push -f
```
That's it! Thank you for your contribution!
#### After your pull request is merged
After your pull request is merged, you can safely delete your branch and pull the changes
from the main (upstream) repository:
- Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
```shell
git push origin --delete my-fix-branch
```
- Check out the master branch:
```shell
git checkout master -f
```
- Delete the local branch:
```shell
git branch -D my-fix-branch
```
- Update your master with the latest upstream version:
```shell
git pull --ff upstream master
```
## <a name="rules"></a> Coding Rules
To ensure consistency throughout the source code, keep these rules in mind as you are working:
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
<!--
// We're working on auto-documentation.
* All public API methods **must be documented**. (Details TBC). -->
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at
**100 characters**. An automated formatter is available ( `npm run format` ).
## <a name="commit"></a> Commit Message Guidelines
We have very precise rules over how our git commit messages can be formatted. This leads to **more
readable messages** that are easy to follow when looking through the **project history**. But also,
we use the git commit messages to **generate the Nest change log**.
### Commit Message Format
Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
format that includes a **type**, a **scope** and a **subject**:
```
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
```
The **header** is mandatory and the **scope** of the header is optional.
Any line of the commit message cannot be longer than 100 characters! This allows the message to be easier
to read on GitHub as well as in various git tools.
Footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.
Samples: (even more [samples](https://github.com/nestjs/nest/commits/master))
```
docs(changelog) update change log to beta.5
```
```
fix(@nestjs/core) need to depend on latest rxjs and zone.js
The version in our package.json gets copied to the one we publish, and users need the latest of these.
```
### Revert
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
### Type
Must be one of the following:
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
* **chore**: Updating tasks etc; no production code change
* **ci**: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
* **docs**: Documentation only changes
* **feat**: A new feature
* **fix**: A bug fix
* **perf**: A code change that improves performance
* **refactor**: A code change that neither fixes a bug nor adds a feature
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
* **test**: Adding missing tests or correcting existing tests
### Subject
The subject contains succinct description of the change:
* use the imperative, present tense: "change" not "changed" nor "changes"
* don't capitalize first letter
* no dot (.) at the end
### Body
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
The body should include the motivation for the change and contrast this with previous behavior.
### Footer
The footer should contain any information about **Breaking Changes** and is also the place to
reference GitHub issues that this commit **Closes**.
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.
A detailed explanation can be found in this [document][commit-message-format].
<!-- ## <a name="cla"></a> Signing the CLA
Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code
changes to be accepted, the CLA must be signed. It's a quick process, we promise!
* For individuals we have a [simple click-through form][individual-cla].
* For corporations we'll need you to
[print, sign and one of scan+email, fax or mail the form][corporate-cla]. -->
<!-- [angular-group]: https://groups.google.com/forum/#!forum/angular -->
<!-- [coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md -->
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
[github]: https://github.com/nestjs/nest
[discord]: https://discord.gg/nestjs
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
[js-style-guide]: https://google.github.io/styleguide/jsguide.html
[jsfiddle]: http://jsfiddle.net
[plunker]: http://plnkr.co/edit
[runnable]: http://runnable.com
<!-- [stackoverflow]: http://stackoverflow.com/questions/tagged/angular -->

24
backend/node_modules/@nestjs/cli/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,24 @@
(The MIT License)
Copyright (c) 2017-2023
Kamil Mysliwiec <https://kamilmysliwiec.com>
Thomas Ricart <thomasr2309@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

43
backend/node_modules/@nestjs/cli/README.md generated vendored Normal file
View File

@@ -0,0 +1,43 @@
<p align="center">
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="120" alt="Nest Logo" /></a>
</p>
<p align="center">A progressive <a href="http://nodejs.org" target="blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
<p align="center">
<a href="https://www.npmjs.com/~nestjscore"><img src="https://img.shields.io/npm/v/@nestjs/cli.svg" alt="NPM Version" /></a>
<a href="https://www.npmjs.com/~nestjscore"><img src="https://img.shields.io/npm/l/@nestjs/cli.svg" alt="Package License" /></a>
<a href="https://www.npmjs.com/~nestjscore"><img src="https://img.shields.io/npm/dm/@nestjs/cli.svg" alt="NPM Downloads" /></a>
<a href="https://coveralls.io/github/nestjs/nest?branch=master" target="_blank"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#9" alt="Coverage" /></a>
<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
<a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg"/></a>
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
<a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow"></a>
## Description
The Nest CLI is a command-line interface tool that helps you to initialize, develop, and maintain your Nest applications. It assists in multiple ways, including scaffolding the project, serving it in development mode, and building and bundling the application for production distribution. It embodies best-practice architectural patterns to encourage well-structured apps.
The CLI works with [schematics](https://github.com/angular/angular-cli/tree/master/packages/angular_devkit/schematics), and provides built in support from the schematics collection at [@nestjs/schematics](https://github.com/nestjs/schematics).
Read more [here](https://docs.nestjs.com/cli/overview).
## Installation
```
$ npm install -g @nestjs/cli
```
## Usage
Learn more in the [official documentation](https://docs.nestjs.com/cli/overview).
## Stay in touch
- Website - [https://nestjs.com](https://nestjs.com/)
- Twitter - [@nestframework](https://twitter.com/nestframework)
## License
Nest is [MIT licensed](LICENSE).

View File

@@ -0,0 +1,4 @@
import { Input } from '../commands';
export declare abstract class AbstractAction {
abstract handle(inputs?: Input[], options?: Input[], extraFlags?: string[]): Promise<void>;
}

View File

@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AbstractAction = void 0;
class AbstractAction {
}
exports.AbstractAction = AbstractAction;

View File

@@ -0,0 +1,12 @@
import { Input } from '../commands';
import { AbstractAction } from './abstract.action';
export declare class AddAction extends AbstractAction {
handle(inputs: Input[], options: Input[], extraFlags: string[]): Promise<void>;
private getSourceRoot;
private installPackage;
private addLibrary;
private getLibraryName;
private getPackageName;
private getCollectionName;
private getTagName;
}

113
backend/node_modules/@nestjs/cli/actions/add.action.js generated vendored Normal file
View File

@@ -0,0 +1,113 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AddAction = void 0;
const chalk = require("chalk");
const get_value_or_default_1 = require("../lib/compiler/helpers/get-value-or-default");
const package_managers_1 = require("../lib/package-managers");
const schematics_1 = require("../lib/schematics");
const ui_1 = require("../lib/ui");
const load_configuration_1 = require("../lib/utils/load-configuration");
const project_utils_1 = require("../lib/utils/project-utils");
const abstract_action_1 = require("./abstract.action");
const schematicName = 'nest-add';
class AddAction extends abstract_action_1.AbstractAction {
async handle(inputs, options, extraFlags) {
const libraryName = this.getLibraryName(inputs);
const packageName = this.getPackageName(libraryName);
const collectionName = this.getCollectionName(libraryName, packageName);
const tagName = this.getTagName(packageName);
const skipInstall = (0, project_utils_1.hasValidOptionFlag)('skip-install', options);
const packageInstallSuccess = skipInstall || (await this.installPackage(collectionName, tagName));
if (packageInstallSuccess) {
const sourceRootOption = await this.getSourceRoot(inputs.concat(options));
options.push(sourceRootOption);
await this.addLibrary(collectionName, options, extraFlags);
}
else {
console.error(chalk.red(ui_1.MESSAGES.LIBRARY_INSTALLATION_FAILED_BAD_PACKAGE(libraryName)));
throw new Error(ui_1.MESSAGES.LIBRARY_INSTALLATION_FAILED_BAD_PACKAGE(libraryName));
}
}
async getSourceRoot(inputs) {
const configuration = await (0, load_configuration_1.loadConfiguration)();
const configurationProjects = configuration.projects;
const appName = inputs.find((option) => option.name === 'project')
.value;
let sourceRoot = appName
? (0, get_value_or_default_1.getValueOrDefault)(configuration, 'sourceRoot', appName)
: configuration.sourceRoot;
const shouldAsk = (0, project_utils_1.shouldAskForProject)(schematicName, configurationProjects, appName);
if (shouldAsk) {
const defaultLabel = ' [ Default ]';
let defaultProjectName = configuration.sourceRoot + defaultLabel;
for (const property in configurationProjects) {
if (configurationProjects[property].sourceRoot ===
configuration.sourceRoot) {
defaultProjectName = property + defaultLabel;
break;
}
}
const projects = (0, project_utils_1.moveDefaultProjectToStart)(configuration, defaultProjectName, defaultLabel);
const answers = await (0, project_utils_1.askForProjectName)(ui_1.MESSAGES.LIBRARY_PROJECT_SELECTION_QUESTION, projects);
const project = answers.appName.replace(defaultLabel, '');
if (project !== configuration.sourceRoot) {
sourceRoot = configurationProjects[project].sourceRoot;
}
}
return { name: 'sourceRoot', value: sourceRoot };
}
async installPackage(collectionName, tagName) {
const manager = await package_managers_1.PackageManagerFactory.find();
tagName = tagName || 'latest';
let installResult = false;
try {
installResult = await manager.addProduction([collectionName], tagName);
}
catch (error) {
if (error && error.message) {
console.error(chalk.red(error.message));
}
}
return installResult;
}
async addLibrary(collectionName, options, extraFlags) {
console.info(ui_1.MESSAGES.LIBRARY_INSTALLATION_STARTS);
const schematicOptions = [];
schematicOptions.push(new schematics_1.SchematicOption('sourceRoot', options.find((option) => option.name === 'sourceRoot').value));
const extraFlagsString = extraFlags ? extraFlags.join(' ') : undefined;
try {
const collection = schematics_1.CollectionFactory.create(collectionName);
await collection.execute(schematicName, schematicOptions, extraFlagsString);
}
catch (error) {
if (error && error.message) {
console.error(chalk.red(error.message));
return Promise.reject();
}
}
}
getLibraryName(inputs) {
const libraryInput = inputs.find((input) => input.name === 'library');
if (!libraryInput) {
throw new Error('No library found in command input');
}
return libraryInput.value;
}
getPackageName(library) {
return library.startsWith('@')
? library.split('/', 2).join('/')
: library.split('/', 1)[0];
}
getCollectionName(library, packageName) {
return ((packageName.startsWith('@')
? packageName.split('@', 2).join('@')
: packageName.split('@', 1).join('@')) +
library.slice(packageName.length));
}
getTagName(packageName) {
return packageName.startsWith('@')
? packageName.split('@', 3)[2]
: packageName.split('@', 2)[1];
}
}
exports.AddAction = AddAction;

View File

@@ -0,0 +1,22 @@
import { Input } from '../commands';
import { AssetsManager } from '../lib/compiler/assets-manager';
import { TsConfigProvider } from '../lib/compiler/helpers/tsconfig-provider';
import { PluginsLoader } from '../lib/compiler/plugins/plugins-loader';
import { TypeScriptBinaryLoader } from '../lib/compiler/typescript-loader';
import { ConfigurationLoader } from '../lib/configuration';
import { FileSystemReader } from '../lib/readers';
import { AbstractAction } from './abstract.action';
export declare class BuildAction extends AbstractAction {
protected readonly pluginsLoader: PluginsLoader;
protected readonly tsLoader: TypeScriptBinaryLoader;
protected readonly tsConfigProvider: TsConfigProvider;
protected readonly fileSystemReader: FileSystemReader;
protected readonly loader: ConfigurationLoader;
protected readonly assetsManager: AssetsManager;
handle(commandInputs: Input[], commandOptions: Input[]): Promise<void>;
runBuild(commandInputs: Input[], commandOptions: Input[], watchMode: boolean, watchAssetsMode: boolean, isDebugEnabled?: boolean, onSuccess?: () => void): Promise<void>;
private runSwc;
private runWebpack;
private runTsc;
private getWebpackConfigFactoryByPath;
}

View File

@@ -0,0 +1,124 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BuildAction = void 0;
const chalk = require("chalk");
const path_1 = require("path");
const assets_manager_1 = require("../lib/compiler/assets-manager");
const delete_out_dir_1 = require("../lib/compiler/helpers/delete-out-dir");
const get_builder_1 = require("../lib/compiler/helpers/get-builder");
const get_tsc_config_path_1 = require("../lib/compiler/helpers/get-tsc-config.path");
const get_value_or_default_1 = require("../lib/compiler/helpers/get-value-or-default");
const get_webpack_config_path_1 = require("../lib/compiler/helpers/get-webpack-config-path");
const tsconfig_provider_1 = require("../lib/compiler/helpers/tsconfig-provider");
const plugins_loader_1 = require("../lib/compiler/plugins/plugins-loader");
const typescript_loader_1 = require("../lib/compiler/typescript-loader");
const configuration_1 = require("../lib/configuration");
const defaults_1 = require("../lib/configuration/defaults");
const readers_1 = require("../lib/readers");
const ui_1 = require("../lib/ui");
const is_module_available_1 = require("../lib/utils/is-module-available");
const abstract_action_1 = require("./abstract.action");
class BuildAction extends abstract_action_1.AbstractAction {
constructor() {
super(...arguments);
this.pluginsLoader = new plugins_loader_1.PluginsLoader();
this.tsLoader = new typescript_loader_1.TypeScriptBinaryLoader();
this.tsConfigProvider = new tsconfig_provider_1.TsConfigProvider(this.tsLoader);
this.fileSystemReader = new readers_1.FileSystemReader(process.cwd());
this.loader = new configuration_1.NestConfigurationLoader(this.fileSystemReader);
this.assetsManager = new assets_manager_1.AssetsManager();
}
async handle(commandInputs, commandOptions) {
try {
const watchModeOption = commandOptions.find((option) => option.name === 'watch');
const watchMode = !!(watchModeOption && watchModeOption.value);
const watchAssetsModeOption = commandOptions.find((option) => option.name === 'watchAssets');
const watchAssetsMode = !!(watchAssetsModeOption && watchAssetsModeOption.value);
await this.runBuild(commandInputs, commandOptions, watchMode, watchAssetsMode);
}
catch (err) {
if (err instanceof Error) {
console.log(`\n${ui_1.ERROR_PREFIX} ${err.message}\n`);
}
else {
console.error(`\n${chalk.red(err)}\n`);
}
process.exit(1);
}
}
async runBuild(commandInputs, commandOptions, watchMode, watchAssetsMode, isDebugEnabled = false, onSuccess) {
const configFileName = commandOptions.find((option) => option.name === 'config').value;
const configuration = await this.loader.load(configFileName);
const appName = commandInputs.find((input) => input.name === 'app')
.value;
const pathToTsconfig = (0, get_tsc_config_path_1.getTscConfigPath)(configuration, commandOptions, appName);
const { options: tsOptions } = this.tsConfigProvider.getByConfigFilename(pathToTsconfig);
const outDir = tsOptions.outDir || defaults_1.defaultOutDir;
const isWebpackEnabled = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'compilerOptions.webpack', appName, 'webpack', commandOptions);
const builder = isWebpackEnabled
? { type: 'webpack' }
: (0, get_builder_1.getBuilder)(configuration, commandOptions, appName);
await (0, delete_out_dir_1.deleteOutDirIfEnabled)(configuration, appName, outDir);
this.assetsManager.copyAssets(configuration, appName, outDir, watchAssetsMode);
const typeCheck = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'compilerOptions.typeCheck', appName, 'typeCheck', commandOptions);
if (typeCheck && builder.type !== 'swc') {
console.warn(ui_1.INFO_PREFIX +
` "typeCheck" will not have any effect when "builder" is not "swc".`);
}
switch (builder.type) {
case 'tsc':
return this.runTsc(watchMode, commandOptions, configuration, pathToTsconfig, appName, onSuccess);
case 'webpack':
return this.runWebpack(configuration, appName, commandOptions, pathToTsconfig, isDebugEnabled, watchMode, onSuccess);
case 'swc':
return this.runSwc(configuration, appName, pathToTsconfig, watchMode, commandOptions, tsOptions, onSuccess);
}
}
async runSwc(configuration, appName, pathToTsconfig, watchMode, options, tsOptions, onSuccess) {
const { SwcCompiler } = await Promise.resolve().then(() => require('../lib/compiler/swc/swc-compiler'));
const swc = new SwcCompiler(this.pluginsLoader);
await swc.run(configuration, pathToTsconfig, appName, {
watch: watchMode,
typeCheck: (0, get_value_or_default_1.getValueOrDefault)(configuration, 'compilerOptions.typeCheck', appName, 'typeCheck', options),
tsOptions,
assetsManager: this.assetsManager,
}, onSuccess);
}
async runWebpack(configuration, appName, commandOptions, pathToTsconfig, debug, watchMode, onSuccess) {
const { WebpackCompiler } = await Promise.resolve().then(() => require('../lib/compiler/webpack-compiler'));
const webpackCompiler = new WebpackCompiler(this.pluginsLoader);
const webpackPath = (0, get_webpack_config_path_1.getWebpackConfigPath)(configuration, commandOptions, appName) ??
defaults_1.defaultWebpackConfigFilename;
const webpackConfigFactoryOrConfig = this.getWebpackConfigFactoryByPath(webpackPath, defaults_1.defaultWebpackConfigFilename);
return webpackCompiler.run(configuration, pathToTsconfig, appName, {
inputs: commandOptions,
webpackConfigFactoryOrConfig,
debug,
watchMode,
assetsManager: this.assetsManager,
}, onSuccess);
}
async runTsc(watchMode, options, configuration, pathToTsconfig, appName, onSuccess) {
if (watchMode) {
const { WatchCompiler } = await Promise.resolve().then(() => require('../lib/compiler/watch-compiler'));
const watchCompiler = new WatchCompiler(this.pluginsLoader, this.tsConfigProvider, this.tsLoader);
const isPreserveWatchOutputEnabled = options.find((option) => option.name === 'preserveWatchOutput' && option.value === true)?.value;
watchCompiler.run(configuration, pathToTsconfig, appName, { preserveWatchOutput: isPreserveWatchOutputEnabled }, onSuccess);
}
else {
const { Compiler } = await Promise.resolve().then(() => require('../lib/compiler/compiler'));
const compiler = new Compiler(this.pluginsLoader, this.tsConfigProvider, this.tsLoader);
compiler.run(configuration, pathToTsconfig, appName, undefined, onSuccess);
this.assetsManager.closeWatchers();
}
}
getWebpackConfigFactoryByPath(webpackPath, defaultPath) {
const pathToWebpackFile = (0, path_1.join)(process.cwd(), webpackPath);
const isWebpackFileAvailable = (0, is_module_available_1.isModuleAvailable)(pathToWebpackFile);
if (!isWebpackFileAvailable && webpackPath === defaultPath) {
return ({}) => ({});
}
return require(pathToWebpackFile);
}
}
exports.BuildAction = BuildAction;

View File

@@ -0,0 +1,5 @@
import { Input } from '../commands';
import { AbstractAction } from './abstract.action';
export declare class GenerateAction extends AbstractAction {
handle(inputs: Input[], options: Input[]): Promise<void>;
}

View File

@@ -0,0 +1,95 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GenerateAction = void 0;
const chalk = require("chalk");
const path = require("path");
const get_value_or_default_1 = require("../lib/compiler/helpers/get-value-or-default");
const schematics_1 = require("../lib/schematics");
const ui_1 = require("../lib/ui");
const load_configuration_1 = require("../lib/utils/load-configuration");
const project_utils_1 = require("../lib/utils/project-utils");
const abstract_action_1 = require("./abstract.action");
class GenerateAction extends abstract_action_1.AbstractAction {
async handle(inputs, options) {
await generateFiles(inputs.concat(options));
}
}
exports.GenerateAction = GenerateAction;
const generateFiles = async (inputs) => {
const configuration = await (0, load_configuration_1.loadConfiguration)();
const collectionOption = inputs.find((option) => option.name === 'collection').value;
const schematic = inputs.find((option) => option.name === 'schematic')
.value;
const appName = inputs.find((option) => option.name === 'project')
.value;
const spec = inputs.find((option) => option.name === 'spec');
const flat = inputs.find((option) => option.name === 'flat');
const specFileSuffix = inputs.find((option) => option.name === 'specFileSuffix');
const collection = schematics_1.CollectionFactory.create(collectionOption || configuration.collection || schematics_1.Collection.NESTJS);
const schematicOptions = mapSchematicOptions(inputs);
schematicOptions.push(new schematics_1.SchematicOption('language', configuration.language));
const configurationProjects = configuration.projects;
let sourceRoot = appName
? (0, get_value_or_default_1.getValueOrDefault)(configuration, 'sourceRoot', appName)
: configuration.sourceRoot;
const specValue = spec.value;
const flatValue = !!flat?.value;
const specFileSuffixValue = specFileSuffix.value;
const specOptions = spec.options;
let generateSpec = (0, project_utils_1.shouldGenerateSpec)(configuration, schematic, appName, specValue, specOptions.passedAsInput);
let generateFlat = (0, project_utils_1.shouldGenerateFlat)(configuration, appName, flatValue);
let generateSpecFileSuffix = (0, project_utils_1.getSpecFileSuffix)(configuration, appName, specFileSuffixValue);
// If you only add a `lib` we actually don't have monorepo: true BUT we do have "projects"
// Ensure we don't run for new app/libs schematics
if ((0, project_utils_1.shouldAskForProject)(schematic, configurationProjects, appName)) {
const defaultLabel = ' [ Default ]';
let defaultProjectName = configuration.sourceRoot + defaultLabel;
for (const property in configurationProjects) {
if (configurationProjects[property].sourceRoot === configuration.sourceRoot) {
defaultProjectName = property + defaultLabel;
break;
}
}
const projects = (0, project_utils_1.moveDefaultProjectToStart)(configuration, defaultProjectName, defaultLabel);
const answers = await (0, project_utils_1.askForProjectName)(ui_1.MESSAGES.PROJECT_SELECTION_QUESTION, projects);
const project = answers.appName.replace(defaultLabel, '');
if (project !== configuration.sourceRoot) {
sourceRoot = configurationProjects[project].sourceRoot;
}
if (answers.appName !== defaultProjectName) {
// Only overwrite if the appName is not the default- as it has already been loaded above
generateSpec = (0, project_utils_1.shouldGenerateSpec)(configuration, schematic, answers.appName, specValue, specOptions.passedAsInput);
generateFlat = (0, project_utils_1.shouldGenerateFlat)(configuration, answers.appNames, flatValue);
generateSpecFileSuffix = (0, project_utils_1.getSpecFileSuffix)(configuration, appName, specFileSuffixValue);
}
}
if (configuration.generateOptions?.baseDir) {
sourceRoot = path.join(sourceRoot, configuration.generateOptions.baseDir);
}
schematicOptions.push(new schematics_1.SchematicOption('sourceRoot', sourceRoot));
schematicOptions.push(new schematics_1.SchematicOption('spec', generateSpec));
schematicOptions.push(new schematics_1.SchematicOption('flat', generateFlat));
schematicOptions.push(new schematics_1.SchematicOption('specFileSuffix', generateSpecFileSuffix));
try {
const schematicInput = inputs.find((input) => input.name === 'schematic');
if (!schematicInput) {
throw new Error('Unable to find a schematic for this configuration');
}
await collection.execute(schematicInput.value, schematicOptions);
}
catch (error) {
if (error && error.message) {
console.error(chalk.red(error.message));
}
}
};
const mapSchematicOptions = (inputs) => {
const excludedInputNames = ['schematic', 'spec', 'flat', 'specFileSuffix'];
const options = [];
inputs.forEach((input) => {
if (!excludedInputNames.includes(input.name) && input.value !== undefined) {
options.push(new schematics_1.SchematicOption(input.name, input.value));
}
});
return options;
};

7
backend/node_modules/@nestjs/cli/actions/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,7 @@
export * from './abstract.action';
export * from './build.action';
export * from './generate.action';
export * from './info.action';
export * from './new.action';
export * from './start.action';
export * from './add.action';

23
backend/node_modules/@nestjs/cli/actions/index.js generated vendored Normal file
View File

@@ -0,0 +1,23 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./abstract.action"), exports);
__exportStar(require("./build.action"), exports);
__exportStar(require("./generate.action"), exports);
__exportStar(require("./info.action"), exports);
__exportStar(require("./new.action"), exports);
__exportStar(require("./start.action"), exports);
__exportStar(require("./add.action"), exports);

View File

@@ -0,0 +1,35 @@
import { AbstractAction } from './abstract.action';
interface LockfileDependency {
version: string;
}
interface PackageJsonDependencies {
[key: string]: LockfileDependency;
}
interface NestDependency {
name: string;
value: string;
packageName: string;
}
interface NestDependencyWarnings {
[key: string]: Array<NestDependency>;
}
export declare class InfoAction extends AbstractAction {
private manager;
private warningMessageDependenciesWhiteList;
handle(): Promise<void>;
private displayBanner;
private displaySystemInformation;
displayPackageManagerVersion(): Promise<void>;
displayNestInformation(): Promise<void>;
displayNestInformationFromPackage(): Promise<void>;
displayCliVersion(): void;
readProjectPackageDependencies(): PackageJsonDependencies;
displayNestVersions(dependencies: PackageJsonDependencies): void;
displayWarningMessage(nestDependencies: NestDependency[]): void;
buildNestVersionsWarningMessage(nestDependencies: NestDependency[]): NestDependencyWarnings;
buildNestVersionsMessage(dependencies: PackageJsonDependencies): NestDependency[];
collectNestDependencies(dependencies: PackageJsonDependencies): NestDependency[];
format(dependencies: NestDependency[]): NestDependency[];
rightPad(name: string, length: number): string;
}
export {};

181
backend/node_modules/@nestjs/cli/actions/info.action.js generated vendored Normal file
View File

@@ -0,0 +1,181 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.InfoAction = void 0;
const chalk = require("chalk");
const fs_1 = require("fs");
const os_1 = require("os");
const path_1 = require("path");
const package_managers_1 = require("../lib/package-managers");
const ui_1 = require("../lib/ui");
const abstract_action_1 = require("./abstract.action");
const os_info_utils_1 = require("../lib/utils/os-info.utils");
class InfoAction extends abstract_action_1.AbstractAction {
constructor() {
super(...arguments);
// Nest dependencies whitelist used to compare the major version
this.warningMessageDependenciesWhiteList = [
'@nestjs/core',
'@nestjs/common',
'@nestjs/schematics',
'@nestjs/platform-express',
'@nestjs/platform-fastify',
'@nestjs/platform-socket.io',
'@nestjs/platform-ws',
'@nestjs/websockets',
];
}
async handle() {
this.manager = await package_managers_1.PackageManagerFactory.find();
this.displayBanner();
await this.displaySystemInformation();
await this.displayNestInformation();
}
displayBanner() {
console.info(chalk.red(ui_1.BANNER));
}
async displaySystemInformation() {
console.info(chalk.green('[System Information]'));
console.info('OS Version :', chalk.blue((0, os_info_utils_1.default)((0, os_1.platform)(), (0, os_1.release)()), (0, os_1.release)()));
console.info('NodeJS Version :', chalk.blue(process.version));
await this.displayPackageManagerVersion();
}
async displayPackageManagerVersion() {
try {
const version = await this.manager.version();
console.info(`${this.manager.name} Version :`, chalk.blue(version), '\n');
}
catch {
console.error(`${this.manager.name} Version :`, chalk.red('Unknown'), '\n');
}
}
async displayNestInformation() {
this.displayCliVersion();
console.info(chalk.green('[Nest Platform Information]'));
await this.displayNestInformationFromPackage();
}
async displayNestInformationFromPackage() {
try {
const dependencies = this.readProjectPackageDependencies();
this.displayNestVersions(dependencies);
}
catch (err) {
console.error(chalk.red(ui_1.MESSAGES.NEST_INFORMATION_PACKAGE_MANAGER_FAILED));
}
}
displayCliVersion() {
console.info(chalk.green('[Nest CLI]'));
console.info('Nest CLI Version :', chalk.blue(JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, '../package.json')).toString())
.version), '\n');
}
readProjectPackageDependencies() {
const buffer = (0, fs_1.readFileSync)((0, path_1.join)(process.cwd(), 'package.json'));
const pack = JSON.parse(buffer.toString());
const dependencies = { ...pack.dependencies, ...pack.devDependencies };
Object.keys(dependencies).forEach((key) => {
dependencies[key] = {
version: dependencies[key],
};
});
return dependencies;
}
displayNestVersions(dependencies) {
const nestDependencies = this.buildNestVersionsMessage(dependencies);
nestDependencies.forEach((dependency) => console.info(dependency.name, chalk.blue(dependency.value)));
this.displayWarningMessage(nestDependencies);
}
displayWarningMessage(nestDependencies) {
try {
const warnings = this.buildNestVersionsWarningMessage(nestDependencies);
const majorVersions = Object.keys(warnings);
if (majorVersions.length > 0) {
console.info('\r');
console.info(chalk.yellow('[Warnings]'));
console.info('The following packages are not in the same major version');
console.info('This could lead to runtime errors');
majorVersions.forEach((version) => {
console.info(chalk.bold(`* Under version ${version}`));
warnings[version].forEach(({ packageName, value }) => {
console.info(`- ${packageName} ${value}`);
});
});
}
}
catch {
console.info('\t');
console.error(chalk.red(ui_1.MESSAGES.NEST_INFORMATION_PACKAGE_WARNING_FAILED(this.warningMessageDependenciesWhiteList)));
}
}
buildNestVersionsWarningMessage(nestDependencies) {
const unsortedWarnings = nestDependencies.reduce((depWarningsGroup, { name, packageName, value }) => {
if (!this.warningMessageDependenciesWhiteList.includes(packageName)) {
return depWarningsGroup;
}
const [major] = value.replace(/[^\d.]/g, '').split('.', 1);
const minimumVersion = major;
depWarningsGroup[minimumVersion] = [
...(depWarningsGroup[minimumVersion] || []),
{ name, packageName, value },
];
return depWarningsGroup;
}, Object.create(null));
const unsortedMinorVersions = Object.keys(unsortedWarnings);
if (unsortedMinorVersions.length <= 1) {
return {};
}
const sortedMinorVersions = unsortedMinorVersions.sort((versionA, versionB) => {
const numA = parseFloat(versionA);
const numB = parseFloat(versionB);
if (isNaN(numA) && isNaN(numB)) {
// If both are not valid numbers, maintain the current order.
return 0;
}
// NaN is considered greater than any number, so if numA is NaN, place it later.
return isNaN(numA) ? 1 : isNaN(numB) ? -1 : numB - numA;
});
return sortedMinorVersions.reduce((warnings, minorVersion) => {
warnings[minorVersion] = unsortedWarnings[minorVersion];
return warnings;
}, Object.create(null));
}
buildNestVersionsMessage(dependencies) {
const nestDependencies = this.collectNestDependencies(dependencies);
return this.format(nestDependencies);
}
collectNestDependencies(dependencies) {
const nestDependencies = [];
Object.keys(dependencies).forEach((key) => {
if (key.indexOf('@nestjs') > -1) {
const depPackagePath = require.resolve(key + '/package.json', {
paths: [process.cwd()],
});
const depPackage = (0, fs_1.readFileSync)(depPackagePath).toString();
const value = JSON.parse(depPackage).version;
nestDependencies.push({
name: `${key.replace(/@nestjs\//, '').replace(/@.*/, '')} version`,
value: value || dependencies[key].version,
packageName: key,
});
}
});
return nestDependencies;
}
format(dependencies) {
const sorted = dependencies.sort((dependencyA, dependencyB) => dependencyB.name.length - dependencyA.name.length);
const length = sorted[0].name.length;
sorted.forEach((dependency) => {
if (dependency.name.length < length) {
dependency.name = this.rightPad(dependency.name, length);
}
dependency.name = dependency.name.concat(' :');
dependency.value = dependency.value.replace(/(\^|\~)/, '');
});
return sorted;
}
rightPad(name, length) {
while (name.length < length) {
name = name.concat(' ');
}
return name;
}
}
exports.InfoAction = InfoAction;

View File

@@ -0,0 +1,7 @@
import { Input } from '../commands';
import { AbstractAction } from './abstract.action';
export declare class NewAction extends AbstractAction {
handle(inputs: Input[], options: Input[]): Promise<void>;
}
export declare const retrieveCols: () => number;
export declare const exit: () => never;

186
backend/node_modules/@nestjs/cli/actions/new.action.js generated vendored Normal file
View File

@@ -0,0 +1,186 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.exit = exports.retrieveCols = exports.NewAction = void 0;
const chalk = require("chalk");
const child_process_1 = require("child_process");
const fs = require("fs");
const inquirer = require("inquirer");
const path_1 = require("path");
const defaults_1 = require("../lib/configuration/defaults");
const package_managers_1 = require("../lib/package-managers");
const questions_1 = require("../lib/questions/questions");
const git_runner_1 = require("../lib/runners/git.runner");
const schematics_1 = require("../lib/schematics");
const ui_1 = require("../lib/ui");
const formatting_1 = require("../lib/utils/formatting");
const abstract_action_1 = require("./abstract.action");
class NewAction extends abstract_action_1.AbstractAction {
async handle(inputs, options) {
const directoryOption = options.find((option) => option.name === 'directory');
const dryRunOption = options.find((option) => option.name === 'dry-run');
const isDryRunEnabled = dryRunOption && dryRunOption.value;
await askForMissingInformation(inputs, options);
await generateApplicationFiles(inputs, options).catch(exports.exit);
const shouldSkipInstall = options.some((option) => option.name === 'skip-install' && option.value === true);
const shouldSkipGit = options.some((option) => option.name === 'skip-git' && option.value === true);
const projectDirectory = getProjectDirectory(getApplicationNameInput(inputs), directoryOption);
if (!shouldSkipInstall) {
await installPackages(options, isDryRunEnabled, projectDirectory);
}
if (!isDryRunEnabled) {
if (!shouldSkipGit) {
await initializeGitRepository(projectDirectory);
await createGitIgnoreFile(projectDirectory);
}
printCollective();
}
process.exit(0);
}
}
exports.NewAction = NewAction;
const getApplicationNameInput = (inputs) => inputs.find((input) => input.name === 'name');
const getPackageManagerInput = (inputs) => inputs.find((options) => options.name === 'packageManager');
const getProjectDirectory = (applicationName, directoryOption) => {
return ((directoryOption && directoryOption.value) ||
(0, formatting_1.normalizeToKebabOrSnakeCase)(applicationName.value));
};
const askForMissingInformation = async (inputs, options) => {
console.info(ui_1.MESSAGES.PROJECT_INFORMATION_START);
console.info();
const prompt = inquirer.createPromptModule();
const nameInput = getApplicationNameInput(inputs);
if (!nameInput.value) {
const message = 'What name would you like to use for the new project?';
const questions = [(0, questions_1.generateInput)('name', message)('nest-app')];
const answers = await prompt(questions);
replaceInputMissingInformation(inputs, answers);
}
const packageManagerInput = getPackageManagerInput(options);
if (!packageManagerInput.value) {
const answers = await askForPackageManager();
replaceInputMissingInformation(options, answers);
}
};
const replaceInputMissingInformation = (inputs, answers) => {
return inputs.map((input) => (input.value =
input.value !== undefined ? input.value : answers[input.name]));
};
const generateApplicationFiles = async (args, options) => {
const collectionName = options.find((option) => option.name === 'collection' && option.value != null).value;
const collection = schematics_1.CollectionFactory.create(collectionName || schematics_1.Collection.NESTJS);
const schematicOptions = mapSchematicOptions(args.concat(options));
await collection.execute('application', schematicOptions);
console.info();
};
const mapSchematicOptions = (options) => {
return options.reduce((schematicOptions, option) => {
if (option.name !== 'skip-install') {
schematicOptions.push(new schematics_1.SchematicOption(option.name, option.value));
}
return schematicOptions;
}, []);
};
const installPackages = async (options, dryRunMode, installDirectory) => {
const inputPackageManager = getPackageManagerInput(options).value;
let packageManager;
if (dryRunMode) {
console.info();
console.info(chalk.green(ui_1.MESSAGES.DRY_RUN_MODE));
console.info();
return;
}
try {
packageManager = package_managers_1.PackageManagerFactory.create(inputPackageManager);
await packageManager.install(installDirectory, inputPackageManager);
}
catch (error) {
if (error && error.message) {
console.error(chalk.red(error.message));
}
}
};
const askForPackageManager = async () => {
const questions = [
(0, questions_1.generateSelect)('packageManager')(ui_1.MESSAGES.PACKAGE_MANAGER_QUESTION)([
package_managers_1.PackageManager.NPM,
package_managers_1.PackageManager.YARN,
package_managers_1.PackageManager.PNPM,
]),
];
const prompt = inquirer.createPromptModule();
return await prompt(questions);
};
const initializeGitRepository = async (dir) => {
const runner = new git_runner_1.GitRunner();
await runner.run('init', true, (0, path_1.join)(process.cwd(), dir)).catch(() => {
console.error(chalk.red(ui_1.MESSAGES.GIT_INITIALIZATION_ERROR));
});
};
/**
* Write a file `.gitignore` in the root of the newly created project.
* `.gitignore` available in `@nestjs/schematics` cannot be published to
* NPM (needs to be investigated).
*
* @param dir Relative path to the project.
* @param content (optional) Content written in the `.gitignore`.
*
* @return Resolves when succeeds, or rejects with any error from `fn.writeFile`.
*/
const createGitIgnoreFile = (dir, content) => {
const fileContent = content || defaults_1.defaultGitIgnore;
const filePath = (0, path_1.join)(process.cwd(), dir, '.gitignore');
if (fileExists(filePath)) {
return;
}
return fs.promises.writeFile(filePath, fileContent);
};
const printCollective = () => {
const dim = print('dim');
const yellow = print('yellow');
const emptyLine = print();
emptyLine();
yellow(`Thanks for installing Nest ${ui_1.EMOJIS.PRAY}`);
dim('Please consider donating to our open collective');
dim('to help us maintain this package.');
emptyLine();
emptyLine();
print()(`${chalk.bold(`${ui_1.EMOJIS.WINE} Donate:`)} ${chalk.underline('https://opencollective.com/nest')}`);
emptyLine();
};
const print = (color = null) => (str = '') => {
const terminalCols = (0, exports.retrieveCols)();
const strLength = str.replace(/\u001b\[[0-9]{2}m/g, '').length;
const leftPaddingLength = Math.floor((terminalCols - strLength) / 2);
const leftPadding = ' '.repeat(Math.max(leftPaddingLength, 0));
if (color) {
str = chalk[color](str);
}
console.log(leftPadding, str);
};
const retrieveCols = () => {
const defaultCols = 80;
try {
const terminalCols = (0, child_process_1.execSync)('tput cols', {
stdio: ['pipe', 'pipe', 'ignore'],
});
return parseInt(terminalCols.toString(), 10) || defaultCols;
}
catch {
return defaultCols;
}
};
exports.retrieveCols = retrieveCols;
const fileExists = (path) => {
try {
fs.accessSync(path);
return true;
}
catch (err) {
if (err.code === 'ENOENT') {
return false;
}
throw err;
}
};
const exit = () => process.exit(1);
exports.exit = exit;

View File

@@ -0,0 +1,7 @@
import { Input } from '../commands';
import { BuildAction } from './build.action';
export declare class StartAction extends BuildAction {
handle(commandInputs: Input[], commandOptions: Input[]): Promise<void>;
createOnSuccessHook(entryFile: string, sourceRoot: string, debugFlag: boolean | string | undefined, outDirName: string, binaryToRun: string): () => void;
private spawnChildProcess;
}

View File

@@ -0,0 +1,99 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StartAction = void 0;
const chalk = require("chalk");
const child_process_1 = require("child_process");
const fs = require("fs");
const path_1 = require("path");
const killProcess = require("tree-kill");
const get_tsc_config_path_1 = require("../lib/compiler/helpers/get-tsc-config.path");
const get_value_or_default_1 = require("../lib/compiler/helpers/get-value-or-default");
const defaults_1 = require("../lib/configuration/defaults");
const ui_1 = require("../lib/ui");
const tree_kill_1 = require("../lib/utils/tree-kill");
const build_action_1 = require("./build.action");
class StartAction extends build_action_1.BuildAction {
async handle(commandInputs, commandOptions) {
try {
const configFileName = commandOptions.find((option) => option.name === 'config').value;
const configuration = await this.loader.load(configFileName);
const appName = commandInputs.find((input) => input.name === 'app')
.value;
const pathToTsconfig = (0, get_tsc_config_path_1.getTscConfigPath)(configuration, commandOptions, appName);
const debugModeOption = commandOptions.find((option) => option.name === 'debug');
const watchModeOption = commandOptions.find((option) => option.name === 'watch');
const isWatchEnabled = !!(watchModeOption && watchModeOption.value);
const watchAssetsModeOption = commandOptions.find((option) => option.name === 'watchAssets');
const isWatchAssetsEnabled = !!(watchAssetsModeOption && watchAssetsModeOption.value);
const debugFlag = debugModeOption && debugModeOption.value;
const binaryToRun = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'exec', appName, 'exec', commandOptions, defaults_1.defaultConfiguration.exec);
const { options: tsOptions } = this.tsConfigProvider.getByConfigFilename(pathToTsconfig);
const outDir = tsOptions.outDir || defaults_1.defaultOutDir;
const entryFile = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'entryFile', appName, 'entryFile', commandOptions, defaults_1.defaultConfiguration.entryFile);
const sourceRoot = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'sourceRoot', appName, 'sourceRoot', commandOptions, defaults_1.defaultConfiguration.sourceRoot);
const onSuccess = this.createOnSuccessHook(entryFile, sourceRoot, debugFlag, outDir, binaryToRun);
await this.runBuild(commandInputs, commandOptions, isWatchEnabled, isWatchAssetsEnabled, !!debugFlag, onSuccess);
}
catch (err) {
if (err instanceof Error) {
console.log(`\n${ui_1.ERROR_PREFIX} ${err.message}\n`);
}
else {
console.error(`\n${chalk.red(err)}\n`);
}
}
}
createOnSuccessHook(entryFile, sourceRoot, debugFlag, outDirName, binaryToRun) {
let childProcessRef;
process.on('exit', () => childProcessRef && (0, tree_kill_1.treeKillSync)(childProcessRef.pid));
return () => {
if (childProcessRef) {
childProcessRef.removeAllListeners('exit');
childProcessRef.on('exit', () => {
childProcessRef = this.spawnChildProcess(entryFile, sourceRoot, debugFlag, outDirName, binaryToRun);
childProcessRef.on('exit', () => (childProcessRef = undefined));
});
childProcessRef.stdin && childProcessRef.stdin.pause();
killProcess(childProcessRef.pid);
}
else {
childProcessRef = this.spawnChildProcess(entryFile, sourceRoot, debugFlag, outDirName, binaryToRun);
childProcessRef.on('exit', (code) => {
process.exitCode = code;
childProcessRef = undefined;
});
}
};
}
spawnChildProcess(entryFile, sourceRoot, debug, outDirName, binaryToRun) {
let outputFilePath = (0, path_1.join)(outDirName, sourceRoot, entryFile);
if (!fs.existsSync(outputFilePath + '.js')) {
outputFilePath = (0, path_1.join)(outDirName, entryFile);
}
let childProcessArgs = [];
const argsStartIndex = process.argv.indexOf('--');
if (argsStartIndex >= 0) {
// Prevents the need for users to double escape strings
// i.e. I can run the more natural
// nest start -- '{"foo": "bar"}'
// instead of
// nest start -- '\'{"foo": "bar"}\''
childProcessArgs = process.argv
.slice(argsStartIndex + 1)
.map((arg) => JSON.stringify(arg));
}
outputFilePath =
outputFilePath.indexOf(' ') >= 0 ? `"${outputFilePath}"` : outputFilePath;
const processArgs = [outputFilePath, ...childProcessArgs];
if (debug) {
const inspectFlag = typeof debug === 'string' ? `--inspect=${debug}` : '--inspect';
processArgs.unshift(inspectFlag);
}
processArgs.unshift('--enable-source-maps');
return (0, child_process_1.spawn)(binaryToRun, processArgs, {
stdio: 'inherit',
shell: true,
});
}
}
exports.StartAction = StartAction;

2
backend/node_modules/@nestjs/cli/bin/nest.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
#!/usr/bin/env node
export {};

25
backend/node_modules/@nestjs/cli/bin/nest.js generated vendored Executable file
View File

@@ -0,0 +1,25 @@
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const commander = require("commander");
const commands_1 = require("../commands");
const local_binaries_1 = require("../lib/utils/local-binaries");
const bootstrap = async () => {
const program = commander;
program
.version(require('../package.json').version, '-v, --version', 'Output the current version.')
.usage('<command> [options]')
.helpOption('-h, --help', 'Output usage information.');
if ((0, local_binaries_1.localBinExists)()) {
const localCommandLoader = (0, local_binaries_1.loadLocalBinCommandLoader)();
await localCommandLoader.load(program);
}
else {
await commands_1.CommandLoader.load(program);
}
await commander.parseAsync(process.argv);
if (!process.argv.slice(2).length) {
program.outputHelp();
}
};
bootstrap();

View File

@@ -0,0 +1,7 @@
import { CommanderStatic } from 'commander';
import { AbstractAction } from '../actions/abstract.action';
export declare abstract class AbstractCommand {
protected action: AbstractAction;
constructor(action: AbstractAction);
abstract load(program: CommanderStatic): void;
}

View File

@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AbstractCommand = void 0;
class AbstractCommand {
constructor(action) {
this.action = action;
}
}
exports.AbstractCommand = AbstractCommand;

View File

@@ -0,0 +1,5 @@
import { CommanderStatic } from 'commander';
import { AbstractCommand } from './abstract.command';
export declare class AddCommand extends AbstractCommand {
load(program: CommanderStatic): void;
}

View File

@@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AddCommand = void 0;
const remaining_flags_1 = require("../lib/utils/remaining-flags");
const abstract_command_1 = require("./abstract.command");
class AddCommand extends abstract_command_1.AbstractCommand {
load(program) {
program
.command('add <library>')
.allowUnknownOption()
.description('Adds support for an external library to your project.')
.option('-d, --dry-run', 'Report actions that would be performed without writing out results.')
.option('-s, --skip-install', 'Skip package installation.', false)
.option('-p, --project [project]', 'Project in which to generate files.')
.usage('<library> [options] [library-specific-options]')
.action(async (library, command) => {
const options = [];
options.push({ name: 'dry-run', value: !!command.dryRun });
options.push({ name: 'skip-install', value: command.skipInstall });
options.push({
name: 'project',
value: command.project,
});
const inputs = [];
inputs.push({ name: 'library', value: library });
const flags = (0, remaining_flags_1.getRemainingFlags)(program);
try {
await this.action.handle(inputs, options, flags);
}
catch (err) {
process.exit(1);
}
});
}
}
exports.AddCommand = AddCommand;

View File

@@ -0,0 +1,5 @@
import { CommanderStatic } from 'commander';
import { AbstractCommand } from './abstract.command';
export declare class BuildCommand extends AbstractCommand {
load(program: CommanderStatic): void;
}

View File

@@ -0,0 +1,65 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BuildCommand = void 0;
const ui_1 = require("../lib/ui");
const abstract_command_1 = require("./abstract.command");
class BuildCommand extends abstract_command_1.AbstractCommand {
load(program) {
program
.command('build [app]')
.option('-c, --config [path]', 'Path to nest-cli configuration file.')
.option('-p, --path [path]', 'Path to tsconfig file.')
.option('-w, --watch', 'Run in watch mode (live-reload).')
.option('-b, --builder [name]', 'Builder to be used (tsc, webpack, swc).')
.option('--watchAssets', 'Watch non-ts (e.g., .graphql) files mode.')
.option('--webpack', 'Use webpack for compilation (deprecated option, use --builder instead).')
.option('--type-check', 'Enable type checking (when SWC is used).')
.option('--webpackPath [path]', 'Path to webpack configuration.')
.option('--tsc', 'Use typescript compiler for compilation.')
.option('--preserveWatchOutput', 'Use "preserveWatchOutput" option when using tsc watch mode.')
.description('Build Nest application.')
.action(async (app, command) => {
const options = [];
options.push({
name: 'config',
value: command.config,
});
const isWebpackEnabled = command.tsc ? false : command.webpack;
options.push({ name: 'webpack', value: isWebpackEnabled });
options.push({ name: 'watch', value: !!command.watch });
options.push({ name: 'watchAssets', value: !!command.watchAssets });
options.push({
name: 'path',
value: command.path,
});
options.push({
name: 'webpackPath',
value: command.webpackPath,
});
const availableBuilders = ['tsc', 'webpack', 'swc'];
if (command.builder && !availableBuilders.includes(command.builder)) {
console.error(ui_1.ERROR_PREFIX +
` Invalid builder option: ${command.builder}. Available builders: ${availableBuilders.join(', ')}`);
return;
}
options.push({
name: 'builder',
value: command.builder,
});
options.push({
name: 'typeCheck',
value: command.typeCheck,
});
options.push({
name: 'preserveWatchOutput',
value: !!command.preserveWatchOutput &&
!!command.watch &&
!isWebpackEnabled,
});
const inputs = [];
inputs.push({ name: 'app', value: app });
await this.action.handle(inputs, options);
});
}
}
exports.BuildCommand = BuildCommand;

View File

@@ -0,0 +1,5 @@
export interface Input {
name: string;
value: boolean | string;
options?: any;
}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,5 @@
import { CommanderStatic } from 'commander';
export declare class CommandLoader {
static load(program: CommanderStatic): Promise<void>;
private static handleInvalidCommand;
}

View File

@@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommandLoader = void 0;
const chalk = require("chalk");
const actions_1 = require("../actions");
const ui_1 = require("../lib/ui");
const add_command_1 = require("./add.command");
const build_command_1 = require("./build.command");
const generate_command_1 = require("./generate.command");
const info_command_1 = require("./info.command");
const new_command_1 = require("./new.command");
const start_command_1 = require("./start.command");
class CommandLoader {
static async load(program) {
new new_command_1.NewCommand(new actions_1.NewAction()).load(program);
new build_command_1.BuildCommand(new actions_1.BuildAction()).load(program);
new start_command_1.StartCommand(new actions_1.StartAction()).load(program);
new info_command_1.InfoCommand(new actions_1.InfoAction()).load(program);
new add_command_1.AddCommand(new actions_1.AddAction()).load(program);
await new generate_command_1.GenerateCommand(new actions_1.GenerateAction()).load(program);
this.handleInvalidCommand(program);
}
static handleInvalidCommand(program) {
program.on('command:*', () => {
console.error(`\n${ui_1.ERROR_PREFIX} Invalid command: ${chalk.red('%s')}`, program.args.join(' '));
console.log(`See ${chalk.red('--help')} for a list of available commands.\n`);
process.exit(1);
});
}
}
exports.CommandLoader = CommandLoader;

View File

@@ -0,0 +1,9 @@
import { CommanderStatic } from 'commander';
import { AbstractCommand } from './abstract.command';
export declare class GenerateCommand extends AbstractCommand {
load(program: CommanderStatic): Promise<void>;
private buildDescription;
private buildSchematicsListAsTable;
private getCollection;
private getSchematics;
}

View File

@@ -0,0 +1,107 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GenerateCommand = void 0;
const chalk = require("chalk");
const Table = require("cli-table3");
const schematics_1 = require("../lib/schematics");
const load_configuration_1 = require("../lib/utils/load-configuration");
const abstract_command_1 = require("./abstract.command");
class GenerateCommand extends abstract_command_1.AbstractCommand {
async load(program) {
program
.command('generate <schematic> [name] [path]')
.alias('g')
.description(await this.buildDescription())
.option('-d, --dry-run', 'Report actions that would be taken without writing out results.')
.option('-p, --project [project]', 'Project in which to generate files.')
.option('--flat', 'Enforce flat structure of generated element.', () => true)
.option('--no-flat', 'Enforce that directories are generated.', () => false)
.option('--spec', 'Enforce spec files generation.', () => {
return { value: true, passedAsInput: true };
}, true)
.option('--spec-file-suffix [suffix]', 'Use a custom suffix for spec files.')
.option('--skip-import', 'Skip importing', () => true, false)
.option('--no-spec', 'Disable spec files generation.', () => {
return { value: false, passedAsInput: true };
})
.option('-c, --collection [collectionName]', 'Schematics collection to use.')
.action(async (schematic, name, path, command) => {
const options = [];
options.push({ name: 'dry-run', value: !!command.dryRun });
if (command.flat !== undefined) {
options.push({ name: 'flat', value: command.flat });
}
options.push({
name: 'spec',
value: typeof command.spec === 'boolean'
? command.spec
: command.spec.value,
options: {
passedAsInput: typeof command.spec === 'boolean'
? false
: command.spec.passedAsInput,
},
});
options.push({
name: 'specFileSuffix',
value: command.specFileSuffix,
});
options.push({
name: 'collection',
value: command.collection,
});
options.push({
name: 'project',
value: command.project,
});
options.push({
name: 'skipImport',
value: command.skipImport,
});
const inputs = [];
inputs.push({ name: 'schematic', value: schematic });
inputs.push({ name: 'name', value: name });
inputs.push({ name: 'path', value: path });
await this.action.handle(inputs, options);
});
}
async buildDescription() {
const collection = await this.getCollection();
return ('Generate a Nest element.\n' +
` Schematics available on ${chalk.bold(collection)} collection:\n` +
this.buildSchematicsListAsTable(await this.getSchematics(collection)));
}
buildSchematicsListAsTable(schematics) {
const leftMargin = ' ';
const tableConfig = {
head: ['name', 'alias', 'description'],
chars: {
'left': leftMargin.concat('│'),
'top-left': leftMargin.concat('┌'),
'bottom-left': leftMargin.concat('└'),
'mid': '',
'left-mid': '',
'mid-mid': '',
'right-mid': '',
},
};
const table = new Table(tableConfig);
for (const schematic of schematics) {
table.push([
chalk.green(schematic.name),
chalk.cyan(schematic.alias),
schematic.description,
]);
}
return table.toString();
}
async getCollection() {
const configuration = await (0, load_configuration_1.loadConfiguration)();
return configuration.collection;
}
async getSchematics(collection) {
const abstractCollection = schematics_1.CollectionFactory.create(collection);
return abstractCollection.getSchematics();
}
}
exports.GenerateCommand = GenerateCommand;

2
backend/node_modules/@nestjs/cli/commands/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
export * from './command.loader';
export * from './command.input';

18
backend/node_modules/@nestjs/cli/commands/index.js generated vendored Normal file
View File

@@ -0,0 +1,18 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./command.loader"), exports);
__exportStar(require("./command.input"), exports);

View File

@@ -0,0 +1,5 @@
import { CommanderStatic } from 'commander';
import { AbstractCommand } from './abstract.command';
export declare class InfoCommand extends AbstractCommand {
load(program: CommanderStatic): void;
}

View File

@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.InfoCommand = void 0;
const abstract_command_1 = require("./abstract.command");
class InfoCommand extends abstract_command_1.AbstractCommand {
load(program) {
program
.command('info')
.alias('i')
.description('Display Nest project details.')
.action(async () => {
await this.action.handle();
});
}
}
exports.InfoCommand = InfoCommand;

View File

@@ -0,0 +1,5 @@
import { CommanderStatic } from 'commander';
import { AbstractCommand } from './abstract.command';
export declare class NewCommand extends AbstractCommand {
load(program: CommanderStatic): void;
}

View File

@@ -0,0 +1,61 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NewCommand = void 0;
const schematics_1 = require("../lib/schematics");
const abstract_command_1 = require("./abstract.command");
class NewCommand extends abstract_command_1.AbstractCommand {
load(program) {
program
.command('new [name]')
.alias('n')
.description('Generate Nest application.')
.option('--directory [directory]', 'Specify the destination directory')
.option('-d, --dry-run', 'Report actions that would be performed without writing out results.', false)
.option('-g, --skip-git', 'Skip git repository initialization.', false)
.option('-s, --skip-install', 'Skip package installation.', false)
.option('-p, --package-manager [packageManager]', 'Specify package manager.')
.option('-l, --language [language]', 'Programming language to be used (TypeScript or JavaScript)', 'TypeScript')
.option('-c, --collection [collectionName]', 'Schematics collection to use', schematics_1.Collection.NESTJS)
.option('--strict', 'Enables strict mode in TypeScript.', false)
.action(async (name, command) => {
const options = [];
const availableLanguages = ['js', 'ts', 'javascript', 'typescript'];
options.push({ name: 'directory', value: command.directory });
options.push({ name: 'dry-run', value: command.dryRun });
options.push({ name: 'skip-git', value: command.skipGit });
options.push({ name: 'skip-install', value: command.skipInstall });
options.push({ name: 'strict', value: command.strict });
options.push({
name: 'packageManager',
value: command.packageManager,
});
options.push({ name: 'collection', value: command.collection });
if (!!command.language) {
const lowercasedLanguage = command.language.toLowerCase();
const langMatch = availableLanguages.includes(lowercasedLanguage);
if (!langMatch) {
throw new Error(`Invalid language "${command.language}" selected. Available languages are "typescript" or "javascript"`);
}
switch (lowercasedLanguage) {
case 'javascript':
command.language = 'js';
break;
case 'typescript':
command.language = 'ts';
break;
default:
command.language = lowercasedLanguage;
break;
}
}
options.push({
name: 'language',
value: command.language,
});
const inputs = [];
inputs.push({ name: 'name', value: name });
await this.action.handle(inputs, options);
});
}
}
exports.NewCommand = NewCommand;

View File

@@ -0,0 +1,5 @@
import { CommanderStatic } from 'commander';
import { AbstractCommand } from './abstract.command';
export declare class StartCommand extends AbstractCommand {
load(program: CommanderStatic): void;
}

View File

@@ -0,0 +1,90 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StartCommand = void 0;
const ui_1 = require("../lib/ui");
const remaining_flags_1 = require("../lib/utils/remaining-flags");
const abstract_command_1 = require("./abstract.command");
class StartCommand extends abstract_command_1.AbstractCommand {
load(program) {
program
.command('start [app]')
.allowUnknownOption()
.option('-c, --config [path]', 'Path to nest-cli configuration file.')
.option('-p, --path [path]', 'Path to tsconfig file.')
.option('-w, --watch', 'Run in watch mode (live-reload).')
.option('-b, --builder [name]', 'Builder to be used (tsc, webpack, swc).')
.option('--watchAssets', 'Watch non-ts (e.g., .graphql) files mode.')
.option('-d, --debug [hostport] ', 'Run in debug mode (with --inspect flag).')
.option('--webpack', 'Use webpack for compilation (deprecated option, use --builder instead).')
.option('--webpackPath [path]', 'Path to webpack configuration.')
.option('--type-check', 'Enable type checking (when SWC is used).')
.option('--tsc', 'Use typescript compiler for compilation.')
.option('--sourceRoot [sourceRoot]', 'Points at the root of the source code for the single project in standard mode structures, or the default project in monorepo mode structures.')
.option('--entryFile [entryFile]', "Path to the entry file where this command will work with. Defaults to the one defined at your Nest's CLI config file.")
.option('-e, --exec [binary]', 'Binary to run (default: "node").')
.option('--preserveWatchOutput', 'Use "preserveWatchOutput" option when using tsc watch mode.')
.description('Run Nest application.')
.action(async (app, command) => {
const options = [];
options.push({
name: 'config',
value: command.config,
});
const isWebpackEnabled = command.tsc ? false : command.webpack;
options.push({ name: 'webpack', value: isWebpackEnabled });
options.push({ name: 'debug', value: command.debug });
options.push({ name: 'watch', value: !!command.watch });
options.push({ name: 'watchAssets', value: !!command.watchAssets });
options.push({
name: 'path',
value: command.path,
});
options.push({
name: 'webpackPath',
value: command.webpackPath,
});
options.push({
name: 'exec',
value: command.exec,
});
options.push({
name: 'sourceRoot',
value: command.sourceRoot,
});
options.push({
name: 'entryFile',
value: command.entryFile,
});
options.push({
name: 'preserveWatchOutput',
value: !!command.preserveWatchOutput &&
!!command.watch &&
!isWebpackEnabled,
});
const availableBuilders = ['tsc', 'webpack', 'swc'];
if (command.builder && !availableBuilders.includes(command.builder)) {
console.error(ui_1.ERROR_PREFIX +
` Invalid builder option: ${command.builder}. Available builders: ${availableBuilders.join(', ')}`);
return;
}
options.push({
name: 'builder',
value: command.builder,
});
options.push({
name: 'typeCheck',
value: command.typeCheck,
});
const inputs = [];
inputs.push({ name: 'app', value: app });
const flags = (0, remaining_flags_1.getRemainingFlags)(program);
try {
await this.action.handle(inputs, options, flags);
}
catch (err) {
process.exit(1);
}
});
}
}
exports.StartCommand = StartCommand;

View File

@@ -0,0 +1,15 @@
import { Configuration } from '../configuration';
export declare class AssetsManager {
private watchAssetsKeyValue;
private watchers;
private actionInProgress;
/**
* Using on `nest build` to close file watch or the build process will not end
* Interval like process
* If no action has been taken recently close watchers
* If action has been taken recently flag and try again
*/
closeWatchers(): void;
copyAssets(configuration: Required<Configuration>, appName: string, outDir: string, watchAssetsMode: boolean): void;
private actionOnFile;
}

View File

@@ -0,0 +1,126 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AssetsManager = void 0;
const chokidar = require("chokidar");
const fs_1 = require("fs");
const glob_1 = require("glob");
const path_1 = require("path");
const copy_path_resolve_1 = require("./helpers/copy-path-resolve");
const get_value_or_default_1 = require("./helpers/get-value-or-default");
class AssetsManager {
constructor() {
this.watchAssetsKeyValue = {};
this.watchers = [];
this.actionInProgress = false;
}
/**
* Using on `nest build` to close file watch or the build process will not end
* Interval like process
* If no action has been taken recently close watchers
* If action has been taken recently flag and try again
*/
closeWatchers() {
// Consider adjusting this for larger files
const timeoutMs = 500;
const closeFn = () => {
if (this.actionInProgress) {
this.actionInProgress = false;
setTimeout(closeFn, timeoutMs);
}
else {
this.watchers.forEach((watcher) => watcher.close());
}
};
setTimeout(closeFn, timeoutMs);
}
copyAssets(configuration, appName, outDir, watchAssetsMode) {
const assets = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'compilerOptions.assets', appName) || [];
if (assets.length <= 0) {
return;
}
try {
let sourceRoot = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'sourceRoot', appName);
sourceRoot = (0, path_1.join)(process.cwd(), sourceRoot);
const filesToCopy = assets.map((item) => {
let includePath = typeof item === 'string' ? item : item.include;
let excludePath = typeof item !== 'string' && item.exclude ? item.exclude : undefined;
includePath = (0, path_1.join)(sourceRoot, includePath).replace(/\\/g, '/');
excludePath = excludePath
? (0, path_1.join)(sourceRoot, excludePath).replace(/\\/g, '/')
: undefined;
return {
outDir: typeof item !== 'string' ? item.outDir || outDir : outDir,
glob: includePath,
exclude: excludePath,
flat: typeof item !== 'string' ? item.flat : undefined, // deprecated field
watchAssets: typeof item !== 'string' ? item.watchAssets : undefined,
};
});
const isWatchEnabled = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'compilerOptions.watchAssets', appName) || watchAssetsMode;
for (const item of filesToCopy) {
const option = {
action: 'change',
item,
path: '',
sourceRoot,
watchAssetsMode: isWatchEnabled,
};
if (isWatchEnabled || item.watchAssets) {
// prettier-ignore
const watcher = chokidar
.watch(item.glob, { ignored: item.exclude })
.on('add', (path) => this.actionOnFile({ ...option, path, action: 'change' }))
.on('change', (path) => this.actionOnFile({ ...option, path, action: 'change' }))
.on('unlink', (path) => this.actionOnFile({ ...option, path, action: 'unlink' }));
this.watchers.push(watcher);
}
else {
const matchedPaths = (0, glob_1.sync)(item.glob, {
ignore: item.exclude,
dot: true,
});
const files = item.glob.endsWith('*')
? matchedPaths.filter((matched) => (0, fs_1.statSync)(matched).isFile())
: matchedPaths.flatMap((matched) => {
if ((0, fs_1.statSync)(matched).isDirectory()) {
return (0, glob_1.sync)(`${matched}/**/*`, {
ignore: item.exclude,
}).filter((file) => (0, fs_1.statSync)(file).isFile());
}
return matched;
});
for (const path of files) {
this.actionOnFile({ ...option, path, action: 'change' });
}
}
}
}
catch (err) {
throw new Error(`An error occurred during the assets copying process. ${err.message}`);
}
}
actionOnFile(option) {
const { action, item, path, sourceRoot, watchAssetsMode } = option;
const isWatchEnabled = watchAssetsMode || item.watchAssets;
const assetCheckKey = path + (item.outDir ?? '');
// Allow to do action for the first time before check watchMode
if (!isWatchEnabled && this.watchAssetsKeyValue[assetCheckKey]) {
return;
}
// Set path value to true for watching the first time
this.watchAssetsKeyValue[assetCheckKey] = true;
// Set action to true to avoid watches getting cutoff
this.actionInProgress = true;
const dest = (0, copy_path_resolve_1.copyPathResolve)(path, item.outDir, sourceRoot.split(path_1.sep).length);
// Copy to output dir if file is changed or added
if (action === 'change') {
(0, fs_1.mkdirSync)((0, path_1.dirname)(dest), { recursive: true });
(0, fs_1.copyFileSync)(path, dest);
}
else if (action === 'unlink') {
// Remove from output dir if file is deleted
(0, fs_1.rmSync)(dest, { force: true });
}
}
}
exports.AssetsManager = AssetsManager;

View File

@@ -0,0 +1,9 @@
import { Configuration } from '../configuration';
import { PluginsLoader } from './plugins/plugins-loader';
export declare abstract class BaseCompiler<T = Record<string, any>> {
private readonly pluginsLoader;
constructor(pluginsLoader: PluginsLoader);
abstract run(configuration: Required<Configuration>, tsConfigPath: string, appName: string | undefined, extras?: T, onSuccess?: () => void): any;
loadPlugins(configuration: Required<Configuration>, tsConfigPath: string, appName: string | undefined): import("./plugins/plugins-loader").MultiNestCompilerPlugins;
getPathToSource(configuration: Required<Configuration>, tsConfigPath: string, appName: string | undefined): string;
}

View File

@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseCompiler = void 0;
const path_1 = require("path");
const get_value_or_default_1 = require("./helpers/get-value-or-default");
class BaseCompiler {
constructor(pluginsLoader) {
this.pluginsLoader = pluginsLoader;
}
loadPlugins(configuration, tsConfigPath, appName) {
const pluginsConfig = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'compilerOptions.plugins', appName);
const pathToSource = this.getPathToSource(configuration, tsConfigPath, appName);
const plugins = this.pluginsLoader.load(pluginsConfig, { pathToSource });
return plugins;
}
getPathToSource(configuration, tsConfigPath, appName) {
const sourceRoot = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'sourceRoot', appName, 'sourceRoot');
const cwd = process.cwd();
const relativeRootPath = (0, path_1.dirname)((0, path_1.relative)(cwd, tsConfigPath));
const pathToSource = (0, path_1.normalize)(sourceRoot).indexOf((0, path_1.normalize)(relativeRootPath)) >= 0
? (0, path_1.join)(cwd, sourceRoot)
: (0, path_1.join)(cwd, relativeRootPath, sourceRoot);
return pathToSource;
}
}
exports.BaseCompiler = BaseCompiler;

View File

@@ -0,0 +1,12 @@
import { Configuration } from '../configuration';
import { BaseCompiler } from './base-compiler';
import { TsConfigProvider } from './helpers/tsconfig-provider';
import { PluginsLoader } from './plugins/plugins-loader';
import { TypeScriptBinaryLoader } from './typescript-loader';
export declare class Compiler extends BaseCompiler {
private readonly tsConfigProvider;
private readonly typescriptLoader;
constructor(pluginsLoader: PluginsLoader, tsConfigProvider: TsConfigProvider, typescriptLoader: TypeScriptBinaryLoader);
run(configuration: Required<Configuration>, tsConfigPath: string, appName: string, _extras: any, onSuccess?: () => void): void;
private reportAfterCompilationDiagnostic;
}

View File

@@ -0,0 +1,61 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Compiler = void 0;
const ts = require("typescript");
const base_compiler_1 = require("./base-compiler");
const tsconfig_paths_hook_1 = require("./hooks/tsconfig-paths.hook");
class Compiler extends base_compiler_1.BaseCompiler {
constructor(pluginsLoader, tsConfigProvider, typescriptLoader) {
super(pluginsLoader);
this.tsConfigProvider = tsConfigProvider;
this.typescriptLoader = typescriptLoader;
}
run(configuration, tsConfigPath, appName, _extras, onSuccess) {
const tsBinary = this.typescriptLoader.load();
const formatHost = {
getCanonicalFileName: (path) => path,
getCurrentDirectory: tsBinary.sys.getCurrentDirectory,
getNewLine: () => tsBinary.sys.newLine,
};
const { options, fileNames, projectReferences } = this.tsConfigProvider.getByConfigFilename(tsConfigPath);
const createProgram = tsBinary.createIncrementalProgram || tsBinary.createProgram;
const program = createProgram.call(ts, {
rootNames: fileNames,
projectReferences,
options,
});
const plugins = this.loadPlugins(configuration, tsConfigPath, appName);
const tsconfigPathsPlugin = (0, tsconfig_paths_hook_1.tsconfigPathsBeforeHookFactory)(options);
const programRef = program.getProgram
? program.getProgram()
: program;
const before = plugins.beforeHooks.map((hook) => hook(programRef));
const after = plugins.afterHooks.map((hook) => hook(programRef));
const afterDeclarations = plugins.afterDeclarationsHooks.map((hook) => hook(programRef));
const emitResult = program.emit(undefined, undefined, undefined, undefined, {
before: tsconfigPathsPlugin
? before.concat(tsconfigPathsPlugin)
: before,
after,
afterDeclarations,
});
const errorsCount = this.reportAfterCompilationDiagnostic(program, emitResult, tsBinary, formatHost);
if (errorsCount) {
process.exit(1);
}
else if (!errorsCount && onSuccess) {
onSuccess();
}
}
reportAfterCompilationDiagnostic(program, emitResult, tsBinary, formatHost) {
const diagnostics = tsBinary
.getPreEmitDiagnostics(program)
.concat(emitResult.diagnostics);
if (diagnostics.length > 0) {
console.error(tsBinary.formatDiagnosticsWithColorAndContext(diagnostics, formatHost));
console.info(`Found ${diagnostics.length} error(s).` + tsBinary.sys.newLine);
}
return diagnostics.length;
}
}
exports.Compiler = Compiler;

View File

@@ -0,0 +1,61 @@
import * as ts from 'typescript';
import { Configuration } from '../../configuration';
export declare const swcDefaultsFactory: (tsOptions?: ts.CompilerOptions, configuration?: Configuration) => {
swcOptions: {
sourceMaps: string | boolean | undefined;
module: {
type: string;
};
jsc: {
target: string;
parser: {
syntax: string;
decorators: boolean;
dynamicImport: boolean;
};
transform: {
legacyDecorator: boolean;
decoratorMetadata: boolean;
useDefineForClassFields: boolean;
};
keepClassNames: boolean;
baseUrl: string | undefined;
paths: ts.MapLike<string[]> | undefined;
};
minify: boolean;
swcrc: boolean;
};
cliOptions: {
outDir: string;
filenames: string[];
sync: boolean;
extensions: string[];
copyFiles: boolean;
includeDotfiles: boolean;
quiet: boolean;
watch: boolean;
stripLeadingPaths: boolean;
} | {
swcrcPath?: string;
outDir: string;
filenames: string[];
sync: boolean;
extensions: string[];
copyFiles: boolean;
includeDotfiles: boolean;
quiet: boolean;
watch: boolean;
stripLeadingPaths: boolean;
} | {
configPath?: string;
outDir: string;
filenames: string[];
sync: boolean;
extensions: string[];
copyFiles: boolean;
includeDotfiles: boolean;
quiet: boolean;
watch: boolean;
stripLeadingPaths: boolean;
};
};

View File

@@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.swcDefaultsFactory = void 0;
const swcDefaultsFactory = (tsOptions, configuration) => {
const builderOptions = typeof configuration?.compilerOptions?.builder !== 'string'
? configuration?.compilerOptions?.builder?.options
: {};
return {
swcOptions: {
sourceMaps: tsOptions?.sourceMap || (tsOptions?.inlineSourceMap && 'inline'),
module: {
type: 'commonjs',
},
jsc: {
target: 'es2021',
parser: {
syntax: 'typescript',
decorators: true,
dynamicImport: true,
},
transform: {
legacyDecorator: true,
decoratorMetadata: true,
useDefineForClassFields: false,
},
keepClassNames: true,
baseUrl: tsOptions?.baseUrl,
paths: tsOptions?.paths,
},
minify: false,
swcrc: true,
},
cliOptions: {
outDir: tsOptions?.outDir ? convertPath(tsOptions.outDir) : 'dist',
filenames: [configuration?.sourceRoot ?? 'src'],
sync: false,
extensions: ['.js', '.ts'],
copyFiles: false,
includeDotfiles: false,
quiet: false,
watch: false,
stripLeadingPaths: true,
...builderOptions,
},
};
};
exports.swcDefaultsFactory = swcDefaultsFactory;
/**
* Converts Windows specific file paths to posix
* @param windowsPath
*/
function convertPath(windowsPath) {
return windowsPath
.replace(/^\\\\\?\\/, '')
.replace(/\\/g, '/')
.replace(/\/\/+/g, '/');
}

View File

@@ -0,0 +1,3 @@
import { MultiNestCompilerPlugins } from '../plugins/plugins-loader';
import webpack = require('webpack');
export declare const webpackDefaultsFactory: (sourceRoot: string, relativeSourceRoot: string, entryFilename: string, isDebugEnabled: boolean | undefined, tsConfigFile: string | undefined, plugins: MultiNestCompilerPlugins) => webpack.Configuration;

View File

@@ -0,0 +1,104 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.webpackDefaultsFactory = void 0;
const path_1 = require("path");
const tsconfig_paths_webpack_plugin_1 = require("tsconfig-paths-webpack-plugin");
const defaults_1 = require("../../configuration/defaults");
const append_extension_1 = require("../helpers/append-extension");
const webpack = require("webpack");
const nodeExternals = require("webpack-node-externals");
const webpackDefaultsFactory = (sourceRoot, relativeSourceRoot, entryFilename, isDebugEnabled = false, tsConfigFile = defaults_1.defaultTsconfigFilename, plugins) => {
const isPluginRegistered = isAnyPluginRegistered(plugins);
const webpackConfiguration = {
entry: (0, append_extension_1.appendTsExtension)((0, path_1.join)(sourceRoot, entryFilename)),
devtool: isDebugEnabled ? 'inline-source-map' : false,
target: 'node',
output: {
filename: (0, path_1.join)(relativeSourceRoot, `${entryFilename}.js`),
},
ignoreWarnings: [/^(?!CriticalDependenciesWarning$)/],
externals: [nodeExternals()],
externalsPresets: { node: true },
module: {
rules: [
{
test: /.tsx?$/,
use: [
{
loader: 'ts-loader',
options: {
transpileOnly: !isPluginRegistered,
configFile: tsConfigFile,
getCustomTransformers: (program) => ({
before: plugins.beforeHooks.map((hook) => hook(program)),
after: plugins.afterHooks.map((hook) => hook(program)),
afterDeclarations: plugins.afterDeclarationsHooks.map((hook) => hook(program)),
}),
},
},
],
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
plugins: [
new tsconfig_paths_webpack_plugin_1.TsconfigPathsPlugin({
configFile: tsConfigFile,
}),
],
},
mode: 'none',
optimization: {
nodeEnv: false,
},
node: {
__filename: false,
__dirname: false,
},
plugins: [
new webpack.IgnorePlugin({
checkResource(resource) {
const lazyImports = [
'@nestjs/microservices',
'@nestjs/microservices/microservices-module',
'@nestjs/websockets/socket-module',
'class-validator',
'class-transformer',
'class-transformer/storage',
];
if (!lazyImports.includes(resource)) {
return false;
}
try {
require.resolve(resource, {
paths: [process.cwd()],
});
}
catch (err) {
return true;
}
return false;
},
}),
],
};
if (!isPluginRegistered) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
webpackConfiguration.plugins.push(new ForkTsCheckerWebpackPlugin({
typescript: {
configFile: tsConfigFile,
},
}));
}
return webpackConfiguration;
};
exports.webpackDefaultsFactory = webpackDefaultsFactory;
function isAnyPluginRegistered(plugins) {
return ((plugins.afterHooks && plugins.afterHooks.length > 0) ||
(plugins.beforeHooks && plugins.beforeHooks.length > 0) ||
(plugins.afterDeclarationsHooks &&
plugins.afterDeclarationsHooks.length > 0));
}

View File

@@ -0,0 +1 @@
export declare function appendTsExtension(path: string): string;

View File

@@ -0,0 +1,7 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.appendTsExtension = appendTsExtension;
const path_1 = require("path");
function appendTsExtension(path) {
return (0, path_1.extname)(path) === '.ts' ? path : path + '.ts';
}

View File

@@ -0,0 +1,7 @@
/**
* Helper function for returning a copy destination filename
*
* @description used in `assets-manager.ts` (copy from `copyfiles`)
* @see https://github.com/calvinmetcalf/copyfiles/blob/master/index.js#L22
*/
export declare function copyPathResolve(filePath: string, outDir: string, up: number): string;

View File

@@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.copyPathResolve = copyPathResolve;
const path = require("path");
/**
* Helper function for returning a copy destination filename
*
* @description used in `assets-manager.ts` (copy from `copyfiles`)
* @see https://github.com/calvinmetcalf/copyfiles/blob/master/index.js#L22
*/
function copyPathResolve(filePath, outDir, up) {
return path.join(outDir, dealWith(filePath, up));
}
function dealWith(inPath, up) {
if (!up) {
return inPath;
}
if (depth(inPath) < up - 1) {
throw new Error('Path outside of project folder is not allowed');
}
return path.join(...path.normalize(inPath).split(path.sep).slice(up));
}
function depth(string) {
return path.normalize(string).split(path.sep).length - 1;
}

View File

@@ -0,0 +1,2 @@
import { Configuration } from '../../configuration';
export declare function deleteOutDirIfEnabled(configuration: Required<Configuration>, appName: string, dirPath: string): Promise<void>;

View File

@@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.deleteOutDirIfEnabled = deleteOutDirIfEnabled;
const promises_1 = require("fs/promises");
const get_value_or_default_1 = require("./get-value-or-default");
async function deleteOutDirIfEnabled(configuration, appName, dirPath) {
const isDeleteEnabled = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'compilerOptions.deleteOutDir', appName);
if (!isDeleteEnabled) {
return;
}
await (0, promises_1.rm)(dirPath, { recursive: true, force: true });
}

View File

@@ -0,0 +1,21 @@
import { Input } from '../../../commands';
import { Configuration } from '../../configuration';
/**
* Returns the builder to use for the given application.
* @param configuration Configuration object.
* @param cmdOptions Command line options.
* @param appName Application name.
* @returns The builder to use.
*/
export declare function getBuilder(configuration: Required<Configuration>, cmdOptions: Input[], appName: string): {
type: "webpack";
options?: import("../../configuration").WebpackBuilderOptions;
} | {
type: "swc";
options?: import("../../configuration").SwcBuilderOptions;
} | {
type: "tsc";
options?: import("../../configuration").TscBuilderOptions;
} | {
type: import("../../configuration").BuilderVariant;
};

View File

@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getBuilder = getBuilder;
const get_value_or_default_1 = require("./get-value-or-default");
/**
* Returns the builder to use for the given application.
* @param configuration Configuration object.
* @param cmdOptions Command line options.
* @param appName Application name.
* @returns The builder to use.
*/
function getBuilder(configuration, cmdOptions, appName) {
const builderValue = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'compilerOptions.builder', appName, 'builder', cmdOptions, 'tsc');
return typeof builderValue === 'string'
? {
type: builderValue,
}
: builderValue;
}

View File

@@ -0,0 +1,10 @@
import { Input } from '../../../commands';
import { Configuration } from '../../configuration';
/**
* Returns the path to the tsc configuration file to use for the given application.
* @param configuration Configuration object.
* @param cmdOptions Command line options.
* @param appName Application name.
* @returns The path to the tsc configuration file to use.
*/
export declare function getTscConfigPath(configuration: Required<Configuration>, cmdOptions: Input[], appName: string): string;

View File

@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTscConfigPath = getTscConfigPath;
const get_default_tsconfig_path_1 = require("../../utils/get-default-tsconfig-path");
const get_value_or_default_1 = require("./get-value-or-default");
/**
* Returns the path to the tsc configuration file to use for the given application.
* @param configuration Configuration object.
* @param cmdOptions Command line options.
* @param appName Application name.
* @returns The path to the tsc configuration file to use.
*/
function getTscConfigPath(configuration, cmdOptions, appName) {
let tsconfigPath = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'compilerOptions.tsConfigPath', appName, 'path', cmdOptions);
if (tsconfigPath) {
return tsconfigPath;
}
const builder = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'compilerOptions.builder', appName);
tsconfigPath =
typeof builder === 'object' && builder?.type === 'tsc'
? builder.options?.configPath
: undefined;
return tsconfigPath ?? (0, get_default_tsconfig_path_1.getDefaultTsconfigPath)();
}

View File

@@ -0,0 +1,4 @@
import { Input } from '../../../commands';
import { Configuration } from '../../configuration';
export declare function getValueOrDefault<T = any>(configuration: Required<Configuration>, propertyPath: string, appName: string | undefined, key?: 'path' | 'webpack' | 'webpackPath' | 'entryFile' | 'sourceRoot' | 'exec' | 'builder' | 'typeCheck', options?: Input[], defaultValue?: T): T;
export declare function getValueOfPath<T = any>(object: Record<string, any>, propertyPath: string): T;

View File

@@ -0,0 +1,66 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getValueOrDefault = getValueOrDefault;
exports.getValueOfPath = getValueOfPath;
function getValueOrDefault(configuration, propertyPath, appName, key, options = [], defaultValue) {
const item = options.find((option) => option.name === key);
const origValue = item && item.value;
if (origValue !== undefined && origValue !== null) {
return origValue;
}
if (configuration.projects && configuration.projects[appName]) {
// Wrap the application name in double-quotes to prevent splitting it
// into separate chunks
appName = appName && !appName.includes('"') ? `"${appName}"` : appName;
const perAppValue = getValueOfPath(configuration, `projects.${appName}.`.concat(propertyPath));
if (perAppValue !== undefined) {
return perAppValue;
}
}
let value = getValueOfPath(configuration, propertyPath);
if (value === undefined) {
value = defaultValue;
}
return value;
}
function getValueOfPath(object, propertyPath) {
const fragments = propertyPath.split('.');
let propertyValue = object;
let isConcatInProgress = false;
let path = '';
for (const fragment of fragments) {
if (!propertyValue) {
break;
}
/**
* When path is escaped with "" double quotes,
* concatenate the property path.
* Reference: https://github.com/nestjs/nest-cli/issues/947
*/
if (fragment.startsWith('"') && fragment.endsWith('"')) {
path = stripDoubleQuotes(fragment);
}
else if (fragment.startsWith('"')) {
path += stripDoubleQuotes(fragment) + '.';
isConcatInProgress = true;
continue;
}
else if (isConcatInProgress && !fragment.endsWith('"')) {
path += fragment + '.';
continue;
}
else if (fragment.endsWith('"')) {
path += stripDoubleQuotes(fragment);
isConcatInProgress = false;
}
else {
path = fragment;
}
propertyValue = propertyValue[path];
path = '';
}
return propertyValue;
}
function stripDoubleQuotes(text) {
return text.replace(/"/g, '');
}

View File

@@ -0,0 +1,10 @@
import { Input } from '../../../commands';
import { Configuration } from '../../configuration';
/**
* Returns the path to the webpack configuration file to use for the given application.
* @param configuration Configuration object.
* @param cmdOptions Command line options.
* @param appName Application name.
* @returns The path to the webpack configuration file to use.
*/
export declare function getWebpackConfigPath(configuration: Required<Configuration>, cmdOptions: Input[], appName: string): string | undefined;

View File

@@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getWebpackConfigPath = getWebpackConfigPath;
const get_value_or_default_1 = require("./get-value-or-default");
/**
* Returns the path to the webpack configuration file to use for the given application.
* @param configuration Configuration object.
* @param cmdOptions Command line options.
* @param appName Application name.
* @returns The path to the webpack configuration file to use.
*/
function getWebpackConfigPath(configuration, cmdOptions, appName) {
let webpackPath = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'compilerOptions.webpackConfigPath', appName, 'webpackPath', cmdOptions);
if (webpackPath) {
return webpackPath;
}
const builder = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'compilerOptions.builder', appName);
webpackPath =
typeof builder === 'object' && builder?.type === 'webpack'
? builder.options?.configPath
: undefined;
return webpackPath;
}

View File

@@ -0,0 +1,2 @@
export declare function listenForManualRestart(callback: () => void): void;
export declare function displayManualRestartTip(): void;

View File

@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.listenForManualRestart = listenForManualRestart;
exports.displayManualRestartTip = displayManualRestartTip;
const chalk = require("chalk");
function listenForManualRestart(callback) {
const stdinListener = (data) => {
if (data.toString().trim() === 'rs') {
process.stdin.removeListener('data', stdinListener);
callback();
}
};
process.stdin.on('data', stdinListener);
}
function displayManualRestartTip() {
console.log(`To restart at any time, enter ${chalk.gray('rs')}.\n`);
}

View File

@@ -0,0 +1,11 @@
import * as ts from 'typescript';
import { TypeScriptBinaryLoader } from '../typescript-loader';
export declare class TsConfigProvider {
private readonly typescriptLoader;
constructor(typescriptLoader: TypeScriptBinaryLoader);
getByConfigFilename(configFilename: string): {
options: ts.CompilerOptions;
fileNames: string[];
projectReferences: readonly ts.ProjectReference[] | undefined;
};
}

View File

@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TsConfigProvider = void 0;
const fs_1 = require("fs");
const path_1 = require("path");
const ui_1 = require("../../ui");
class TsConfigProvider {
constructor(typescriptLoader) {
this.typescriptLoader = typescriptLoader;
}
getByConfigFilename(configFilename) {
const configPath = (0, path_1.join)(process.cwd(), configFilename);
if (!(0, fs_1.existsSync)(configPath)) {
throw new Error(ui_1.CLI_ERRORS.MISSING_TYPESCRIPT(configFilename));
}
const tsBinary = this.typescriptLoader.load();
const parsedCmd = tsBinary.getParsedCommandLineOfConfigFile(configPath, undefined, tsBinary.sys);
const { options, fileNames, projectReferences } = parsedCmd;
return { options, fileNames, projectReferences };
}
}
exports.TsConfigProvider = TsConfigProvider;

View File

@@ -0,0 +1,2 @@
import * as ts from 'typescript';
export declare function tsconfigPathsBeforeHookFactory(compilerOptions: ts.CompilerOptions): (ctx: ts.TransformationContext) => ts.Transformer<any>;

View File

@@ -0,0 +1,76 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.tsconfigPathsBeforeHookFactory = tsconfigPathsBeforeHookFactory;
const os = require("os");
const path_1 = require("path");
const typescript_loader_1 = require("../typescript-loader");
const tsPaths = require("tsconfig-paths");
function tsconfigPathsBeforeHookFactory(compilerOptions) {
const tsBinary = new typescript_loader_1.TypeScriptBinaryLoader().load();
const { paths = {}, baseUrl = './' } = compilerOptions;
const matcher = tsPaths.createMatchPath(baseUrl, paths, ['main']);
return (ctx) => {
return (sf) => {
const visitNode = (node) => {
if (tsBinary.isImportDeclaration(node) ||
(tsBinary.isExportDeclaration(node) && node.moduleSpecifier)) {
try {
const importPathWithQuotes = node.moduleSpecifier && node.moduleSpecifier.getText();
if (!importPathWithQuotes) {
return node;
}
const text = importPathWithQuotes.substring(1, importPathWithQuotes.length - 1);
const result = getNotAliasedPath(sf, matcher, text);
if (!result) {
return node;
}
const moduleSpecifier = tsBinary.factory.createStringLiteral(result);
moduleSpecifier.parent = node.moduleSpecifier.parent;
if (tsBinary.isImportDeclaration(node)) {
const updatedNode = tsBinary.factory.updateImportDeclaration(node, node.modifiers, node.importClause, moduleSpecifier, node.assertClause);
updatedNode.flags = node.flags;
return updatedNode;
}
else {
const updatedNode = tsBinary.factory.updateExportDeclaration(node, node.modifiers, node.isTypeOnly, node.exportClause, moduleSpecifier, node.assertClause);
updatedNode.flags = node.flags;
return updatedNode;
}
}
catch {
return node;
}
}
return tsBinary.visitEachChild(node, visitNode, ctx);
};
return tsBinary.visitNode(sf, visitNode);
};
};
}
function getNotAliasedPath(sf, matcher, text) {
let result = matcher(text, undefined, undefined, [
'.ts',
'.tsx',
'.js',
'.jsx',
]);
if (!result) {
return;
}
if (os.platform() === 'win32') {
result = result.replace(/\\/g, '/');
}
try {
// Installed packages (node modules) should take precedence over root files with the same name.
// Ref: https://github.com/nestjs/nest-cli/issues/838
const packagePath = require.resolve(text, {
paths: [process.cwd(), ...module.paths],
});
if (packagePath) {
return text;
}
}
catch { }
const resolvedPath = path_1.posix.relative((0, path_1.dirname)(sf.fileName), result) || './';
return resolvedPath[0] === '.' ? resolvedPath : './' + resolvedPath;
}

View File

@@ -0,0 +1,10 @@
import * as ts from 'typescript';
export type DeepPluginMeta = ts.ObjectLiteralExpression | {
[key: string]: DeepPluginMeta;
};
export interface ReadonlyVisitor {
key: string;
typeImports: Record<string, string>;
visit(program: unknown, sf: unknown): unknown;
collect(): Record<string, Array<unknown>>;
}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,58 @@
import * as ts from 'typescript';
import { ReadonlyVisitor } from '../interfaces/readonly-visitor.interface';
export interface PluginMetadataGenerateOptions {
/**
* The visitors to use to generate the metadata.
*/
visitors: ReadonlyVisitor[];
/**
* The output directory to write the metadata to.
*/
outputDir: string;
/**
* Whether to watch the project for changes.
*/
watch?: boolean;
/**
* The path to the tsconfig file.
* Relative to the current working directory (process.cwd()).
*/
tsconfigPath?: string;
/**
* The filename to write the metadata to.
*/
filename?: string;
/**
* A reference to an existing ts.Program instance.
*/
tsProgramRef?: ts.Program;
/**
* Whether to print diagnostics to the console.
* @default true
*/
printDiagnostics?: boolean;
}
/**
* Generates plugins metadata by traversing the AST of the project.
* @example
* ```ts
* const generator = new PluginMetadataGenerator();
* generator.generate({
* visitors: [
* new ReadonlyVisitor({ introspectComments: true, pathToSource: __dirname }),
* ],
* outputDir: __dirname,
* watch: true,
* tsconfigPath: 'tsconfig.build.json',
* });
* ```
*/
export declare class PluginMetadataGenerator {
private readonly pluginMetadataPrinter;
private readonly typeCheckerHost;
private readonly typescriptLoader;
private readonly tsBinary;
constructor();
generate(options: PluginMetadataGenerateOptions): void;
private traverseAndPrintMetadata;
}

View File

@@ -0,0 +1,84 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PluginMetadataGenerator = void 0;
const constants_1 = require("../swc/constants");
const type_checker_host_1 = require("../swc/type-checker-host");
const typescript_loader_1 = require("../typescript-loader");
const plugin_metadata_printer_1 = require("./plugin-metadata-printer");
/**
* Generates plugins metadata by traversing the AST of the project.
* @example
* ```ts
* const generator = new PluginMetadataGenerator();
* generator.generate({
* visitors: [
* new ReadonlyVisitor({ introspectComments: true, pathToSource: __dirname }),
* ],
* outputDir: __dirname,
* watch: true,
* tsconfigPath: 'tsconfig.build.json',
* });
* ```
*/
class PluginMetadataGenerator {
constructor() {
this.pluginMetadataPrinter = new plugin_metadata_printer_1.PluginMetadataPrinter();
this.typeCheckerHost = new type_checker_host_1.TypeCheckerHost();
this.typescriptLoader = new typescript_loader_1.TypeScriptBinaryLoader();
this.tsBinary = this.typescriptLoader.load();
}
generate(options) {
const { tsconfigPath, visitors, tsProgramRef, outputDir, watch, filename, printDiagnostics = true, } = options;
if (visitors.length === 0) {
return;
}
if (tsProgramRef) {
return this.traverseAndPrintMetadata(tsProgramRef, visitors, outputDir, filename);
}
const onTypeCheckOrProgramInit = (program) => {
this.traverseAndPrintMetadata(program, visitors, outputDir, filename);
if (printDiagnostics) {
const tsBinary = this.typescriptLoader.load();
const diagnostics = tsBinary.getPreEmitDiagnostics(program);
if (diagnostics.length > 0) {
const formatDiagnosticsHost = {
getCanonicalFileName: (path) => path,
getCurrentDirectory: tsBinary.sys.getCurrentDirectory,
getNewLine: () => tsBinary.sys.newLine,
};
console.log();
console.log(tsBinary.formatDiagnosticsWithColorAndContext(diagnostics, formatDiagnosticsHost));
}
else {
console.log(constants_1.FOUND_NO_ISSUES_GENERATING_METADATA);
}
}
};
this.typeCheckerHost.run(tsconfigPath, {
watch,
onTypeCheck: onTypeCheckOrProgramInit,
onProgramInit: onTypeCheckOrProgramInit,
});
}
traverseAndPrintMetadata(programRef, visitors, outputDir, filename) {
for (const sourceFile of programRef.getSourceFiles()) {
if (!sourceFile.isDeclarationFile) {
visitors.forEach((visitor) => visitor.visit(programRef, sourceFile));
}
}
let typeImports = {};
const collectedMetadata = {};
visitors.forEach((visitor) => {
collectedMetadata[visitor.key] = visitor.collect();
typeImports = {
...typeImports,
...visitor.typeImports,
};
});
this.pluginMetadataPrinter.print(collectedMetadata, typeImports, {
outputDir,
filename,
}, this.tsBinary);
}
}
exports.PluginMetadataGenerator = PluginMetadataGenerator;

View File

@@ -0,0 +1,17 @@
import * as ts from 'typescript';
import { DeepPluginMeta } from '../interfaces/readonly-visitor.interface';
export interface PluginMetadataPrintOptions {
outputDir: string;
filename?: string;
}
type ComposedPluginMeta = Record<string, Record<string, Array<[ts.CallExpression, DeepPluginMeta]>>>;
/**
* Prints the metadata to a file.
*/
export declare class PluginMetadataPrinter {
print(metadata: ComposedPluginMeta, typeImports: Record<string, string>, options: PluginMetadataPrintOptions, tsBinary: typeof ts): void;
private recursivelyCreatePropertyAssignment;
private createTypeImportVariableStatement;
private createPropertyAssignment;
}
export {};

View File

@@ -0,0 +1,51 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PluginMetadataPrinter = void 0;
const fs_1 = require("fs");
const path_1 = require("path");
const SERIALIZED_METADATA_FILENAME = 'metadata.ts';
const TYPE_IMPORT_VARIABLE_NAME = 't';
/**
* Prints the metadata to a file.
*/
class PluginMetadataPrinter {
print(metadata, typeImports, options, tsBinary) {
const objectLiteralExpr = tsBinary.factory.createObjectLiteralExpression(Object.keys(metadata).map((key) => this.recursivelyCreatePropertyAssignment(key, metadata[key], tsBinary)));
const exportAssignment = tsBinary.factory.createExportAssignment(undefined, undefined, tsBinary.factory.createArrowFunction([tsBinary.factory.createToken(tsBinary.SyntaxKind.AsyncKeyword)], undefined, [], undefined, tsBinary.factory.createToken(tsBinary.SyntaxKind.EqualsGreaterThanToken), tsBinary.factory.createBlock([
this.createTypeImportVariableStatement(typeImports, tsBinary),
tsBinary.factory.createReturnStatement(objectLiteralExpr),
], true)));
const printer = tsBinary.createPrinter({
newLine: tsBinary.NewLineKind.LineFeed,
});
const resultFile = tsBinary.createSourceFile('file.ts', '', tsBinary.ScriptTarget.Latest,
/*setParentNodes*/ false, tsBinary.ScriptKind.TS);
const filename = (0, path_1.join)(options.outputDir, options.filename ?? SERIALIZED_METADATA_FILENAME);
const eslintPrefix = `/* eslint-disable */\n`;
(0, fs_1.writeFileSync)(filename, eslintPrefix +
printer.printNode(tsBinary.EmitHint.Unspecified, exportAssignment, resultFile));
}
recursivelyCreatePropertyAssignment(identifier, meta, tsBinary) {
if (Array.isArray(meta)) {
return tsBinary.factory.createPropertyAssignment(tsBinary.factory.createStringLiteral(identifier), tsBinary.factory.createArrayLiteralExpression(meta.map(([importExpr, meta]) => tsBinary.factory.createArrayLiteralExpression([
importExpr,
tsBinary.factory.createObjectLiteralExpression(Object.keys(meta).map((key) => this.recursivelyCreatePropertyAssignment(key, meta[key], tsBinary))),
]))));
}
return tsBinary.factory.createPropertyAssignment(tsBinary.factory.createStringLiteral(identifier), tsBinary.isObjectLiteralExpression(meta)
? meta
: tsBinary.factory.createObjectLiteralExpression(Object.keys(meta).map((key) => this.recursivelyCreatePropertyAssignment(key, meta[key], tsBinary))));
}
createTypeImportVariableStatement(typeImports, tsBinary) {
return tsBinary.factory.createVariableStatement(undefined, tsBinary.factory.createVariableDeclarationList([
tsBinary.factory.createVariableDeclaration(tsBinary.factory.createIdentifier(TYPE_IMPORT_VARIABLE_NAME), undefined, undefined, tsBinary.factory.createObjectLiteralExpression(Object.keys(typeImports).map((ti) => this.createPropertyAssignment(ti, typeImports[ti], tsBinary)), true)),
], tsBinary.NodeFlags.Const |
tsBinary.NodeFlags.AwaitContext |
tsBinary.NodeFlags.ContextFlags |
tsBinary.NodeFlags.TypeExcludesFlags));
}
createPropertyAssignment(identifier, target, tsBinary) {
return tsBinary.factory.createPropertyAssignment(tsBinary.factory.createComputedPropertyName(tsBinary.factory.createStringLiteral(identifier)), tsBinary.factory.createIdentifier(target));
}
}
exports.PluginMetadataPrinter = PluginMetadataPrinter;

View File

@@ -0,0 +1,30 @@
import * as ts from 'typescript';
import { ReadonlyVisitor } from '../interfaces/readonly-visitor.interface';
type Transformer = ts.TransformerFactory<any> | ts.CustomTransformerFactory;
type PluginEntry = string | PluginAndOptions;
type PluginOptions = Record<string, any>;
interface PluginAndOptions {
name: 'string';
options: PluginOptions;
}
export interface NestCompilerPlugin {
before?: (options?: PluginOptions, program?: ts.Program) => Transformer;
after?: (options?: PluginOptions, program?: ts.Program) => Transformer;
afterDeclarations?: (options?: PluginOptions, program?: ts.Program) => Transformer;
ReadonlyVisitor?: {
new (options: PluginOptions): ReadonlyVisitor;
};
}
export interface MultiNestCompilerPlugins {
beforeHooks: Array<(program?: ts.Program) => Transformer>;
afterHooks: Array<(program?: ts.Program) => Transformer>;
afterDeclarationsHooks: Array<(program?: ts.Program) => Transformer>;
readonlyVisitors: Array<ReadonlyVisitor>;
}
export declare class PluginsLoader {
load(plugins?: PluginEntry[], extras?: {
pathToSource?: string;
}): MultiNestCompilerPlugins;
private resolvePluginReferences;
}
export {};

View File

@@ -0,0 +1,70 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PluginsLoader = void 0;
const path_1 = require("path");
const ui_1 = require("../../ui");
const PLUGIN_ENTRY_FILENAME = 'plugin';
class PluginsLoader {
load(plugins = [], extras = {}) {
const pluginNames = plugins.map((entry) => typeof entry === 'object'
? entry.name
: entry);
const pluginRefs = this.resolvePluginReferences(pluginNames);
const multiCompilerPlugins = {
afterHooks: [],
afterDeclarationsHooks: [],
beforeHooks: [],
readonlyVisitors: [],
};
pluginRefs.forEach((plugin, index) => {
if (!plugin.before && !plugin.after && !plugin.afterDeclarations) {
throw new Error(ui_1.CLI_ERRORS.WRONG_PLUGIN(pluginNames[index]));
}
const options = typeof plugins[index] === 'object'
? plugins[index].options || {}
: {};
if (plugin.before) {
multiCompilerPlugins.beforeHooks.push(plugin.before.bind(plugin.before, options));
}
if (plugin.after) {
multiCompilerPlugins.afterHooks.push(plugin.after.bind(plugin.after, options));
}
if (plugin.afterDeclarations) {
multiCompilerPlugins.afterDeclarationsHooks.push(plugin.afterDeclarations.bind(plugin.afterDeclarations, options));
}
if (plugin.ReadonlyVisitor) {
const instance = new plugin.ReadonlyVisitor({
...options,
...extras,
readonly: true,
});
instance.key = pluginNames[index];
multiCompilerPlugins.readonlyVisitors.push(instance);
}
});
return multiCompilerPlugins;
}
resolvePluginReferences(pluginNames) {
const nodeModulePaths = [
(0, path_1.join)(process.cwd(), 'node_modules'),
...module.paths,
];
return pluginNames.map((item) => {
try {
try {
const binaryPath = require.resolve((0, path_1.join)(item, PLUGIN_ENTRY_FILENAME), {
paths: nodeModulePaths,
});
return require(binaryPath);
}
catch { }
const binaryPath = require.resolve(item, { paths: nodeModulePaths });
return require(binaryPath);
}
catch (e) {
throw new Error(`"${item}" plugin is not installed.`);
}
});
}
}
exports.PluginsLoader = PluginsLoader;

View File

@@ -0,0 +1,9 @@
export declare const TSC_NO_ERRORS_MESSAGE = "Found 0 errors. Watching for file changes.";
export declare const TSC_COMPILATION_STARTED_MESSAGE = "Starting compilation in watch mode...";
export declare const SWC_LOG_PREFIX: string;
export declare const TSC_LOG_PREFIX: string;
export declare const TSC_LOG_ERROR_PREFIX: string;
export declare const TSC_LOG_SUCCESS_PREFIX: string;
export declare const INITIALIZING_TYPE_CHECKER: string;
export declare const FOUND_NO_ISSUES_METADATA_GENERATION_SKIPPED: string;
export declare const FOUND_NO_ISSUES_GENERATING_METADATA: string;

View File

@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FOUND_NO_ISSUES_GENERATING_METADATA = exports.FOUND_NO_ISSUES_METADATA_GENERATION_SKIPPED = exports.INITIALIZING_TYPE_CHECKER = exports.TSC_LOG_SUCCESS_PREFIX = exports.TSC_LOG_ERROR_PREFIX = exports.TSC_LOG_PREFIX = exports.SWC_LOG_PREFIX = exports.TSC_COMPILATION_STARTED_MESSAGE = exports.TSC_NO_ERRORS_MESSAGE = void 0;
const chalk = require("chalk");
exports.TSC_NO_ERRORS_MESSAGE = 'Found 0 errors. Watching for file changes.';
exports.TSC_COMPILATION_STARTED_MESSAGE = 'Starting compilation in watch mode...';
exports.SWC_LOG_PREFIX = chalk.cyan('> ') + chalk.bgCyan.bold(' SWC ');
exports.TSC_LOG_PREFIX = chalk.cyan('> ') + chalk.bgCyan.bold(' TSC ');
exports.TSC_LOG_ERROR_PREFIX = chalk.red('> ') + chalk.bgRed.bold(' TSC ');
exports.TSC_LOG_SUCCESS_PREFIX = chalk.green('> ') + chalk.bgGreen.bold(' TSC ');
exports.INITIALIZING_TYPE_CHECKER = chalk.bgCyan.bold(' TSC ') + chalk.cyan(' Initializing type checker...');
exports.FOUND_NO_ISSUES_METADATA_GENERATION_SKIPPED = exports.TSC_LOG_SUCCESS_PREFIX + chalk.green(' Found 0 issues.');
exports.FOUND_NO_ISSUES_GENERATING_METADATA = exports.TSC_LOG_SUCCESS_PREFIX +
chalk.green(' Found 0 issues. Generating metadata...');

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,63 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const ui_1 = require("../../ui");
const base_compiler_1 = require("../base-compiler");
const plugin_metadata_generator_1 = require("../plugins/plugin-metadata-generator");
const plugins_loader_1 = require("../plugins/plugins-loader");
const constants_1 = require("./constants");
const type_checker_host_1 = require("./type-checker-host");
const [tsConfigPath, appName, sourceRoot, plugins] = process.argv.slice(2);
class ForkedTypeChecker extends base_compiler_1.BaseCompiler {
constructor() {
super(...arguments);
this.pluginMetadataGenerator = new plugin_metadata_generator_1.PluginMetadataGenerator();
this.typeCheckerHost = new type_checker_host_1.TypeCheckerHost();
}
async run(configuration, tsConfigPath, appName, extras) {
const { readonlyVisitors } = this.loadPlugins(configuration, tsConfigPath, appName);
const outputDir = this.getPathToSource(configuration, tsConfigPath, appName);
try {
const onTypeCheckOrProgramInit = (program) => {
if (readonlyVisitors.length > 0) {
console.log(constants_1.FOUND_NO_ISSUES_GENERATING_METADATA);
this.pluginMetadataGenerator.generate({
outputDir,
visitors: readonlyVisitors,
tsProgramRef: program,
});
}
else {
console.log(constants_1.FOUND_NO_ISSUES_METADATA_GENERATION_SKIPPED);
}
};
this.typeCheckerHost.run(tsConfigPath, {
watch: extras.watch,
onTypeCheck: onTypeCheckOrProgramInit,
onProgramInit: onTypeCheckOrProgramInit,
});
}
catch (err) {
console.log(ui_1.ERROR_PREFIX, err.message);
}
}
}
const pluginsLoader = new plugins_loader_1.PluginsLoader();
const forkedTypeChecker = new ForkedTypeChecker(pluginsLoader);
const applicationName = appName === 'undefined' ? '' : appName;
const options = {
sourceRoot,
};
if (applicationName) {
options.projects = {};
options.projects[applicationName] = {
compilerOptions: {
plugins: JSON.parse(plugins),
},
};
}
else {
options.compilerOptions = {
plugins: JSON.parse(plugins),
};
}
forkedTypeChecker.run(options, tsConfigPath, applicationName, { watch: true, typeCheck: true });

View File

@@ -0,0 +1,24 @@
import * as ts from 'typescript';
import { Configuration } from '../../configuration';
import { AssetsManager } from '../assets-manager';
import { BaseCompiler } from '../base-compiler';
import { PluginsLoader } from '../plugins/plugins-loader';
export type SwcCompilerExtras = {
watch: boolean;
typeCheck: boolean;
assetsManager: AssetsManager;
tsOptions: ts.CompilerOptions;
};
export declare class SwcCompiler extends BaseCompiler {
private readonly pluginMetadataGenerator;
private readonly typeCheckerHost;
constructor(pluginsLoader: PluginsLoader);
run(configuration: Required<Configuration>, tsConfigPath: string, appName: string, extras: SwcCompilerExtras, onSuccess?: () => void): Promise<void>;
private runTypeChecker;
private runSwc;
private loadSwcCliBinary;
private getSwcRcFileContentIfExists;
private deepMerge;
private debounce;
private watchFilesInOutDir;
}

View File

@@ -0,0 +1,192 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SwcCompiler = void 0;
const chalk = require("chalk");
const child_process_1 = require("child_process");
const chokidar = require("chokidar");
const fs_1 = require("fs");
const path = require("path");
const path_1 = require("path");
const ui_1 = require("../../ui");
const tree_kill_1 = require("../../utils/tree-kill");
const base_compiler_1 = require("../base-compiler");
const swc_defaults_1 = require("../defaults/swc-defaults");
const get_value_or_default_1 = require("../helpers/get-value-or-default");
const plugin_metadata_generator_1 = require("../plugins/plugin-metadata-generator");
const constants_1 = require("./constants");
const type_checker_host_1 = require("./type-checker-host");
class SwcCompiler extends base_compiler_1.BaseCompiler {
constructor(pluginsLoader) {
super(pluginsLoader);
this.pluginMetadataGenerator = new plugin_metadata_generator_1.PluginMetadataGenerator();
this.typeCheckerHost = new type_checker_host_1.TypeCheckerHost();
}
async run(configuration, tsConfigPath, appName, extras, onSuccess) {
const swcOptions = (0, swc_defaults_1.swcDefaultsFactory)(extras.tsOptions, configuration);
const swcrcFilePath = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'compilerOptions.builder.options.swcrcPath', appName);
if (extras.watch) {
if (extras.typeCheck) {
this.runTypeChecker(configuration, tsConfigPath, appName, extras);
}
await this.runSwc(swcOptions, extras, swcrcFilePath);
if (onSuccess) {
onSuccess();
const debounceTime = 150;
const callback = this.debounce(onSuccess, debounceTime);
this.watchFilesInOutDir(swcOptions, callback);
}
}
else {
if (extras.typeCheck) {
await this.runTypeChecker(configuration, tsConfigPath, appName, extras);
}
await this.runSwc(swcOptions, extras, swcrcFilePath);
if (onSuccess) {
onSuccess();
}
extras.assetsManager?.closeWatchers();
}
}
runTypeChecker(configuration, tsConfigPath, appName, extras) {
if (extras.watch) {
const args = [
tsConfigPath,
appName,
configuration.sourceRoot ?? 'src',
JSON.stringify(configuration.compilerOptions.plugins ?? []),
];
const childProcessRef = (0, child_process_1.fork)((0, path_1.join)(__dirname, 'forked-type-checker.js'), args, {
cwd: process.cwd(),
});
process.on('exit', () => childProcessRef && (0, tree_kill_1.treeKillSync)(childProcessRef.pid));
}
else {
const { readonlyVisitors } = this.loadPlugins(configuration, tsConfigPath, appName);
const outputDir = this.getPathToSource(configuration, tsConfigPath, appName);
let fulfilled = false;
return new Promise((resolve, reject) => {
try {
this.typeCheckerHost.run(tsConfigPath, {
watch: extras.watch,
onTypeCheck: (program) => {
if (!fulfilled) {
fulfilled = true;
resolve();
}
if (readonlyVisitors.length > 0) {
process.nextTick(() => console.log(constants_1.FOUND_NO_ISSUES_GENERATING_METADATA));
this.pluginMetadataGenerator.generate({
outputDir,
visitors: readonlyVisitors,
tsProgramRef: program,
});
}
else {
process.nextTick(() => console.log(constants_1.FOUND_NO_ISSUES_METADATA_GENERATION_SKIPPED));
}
},
});
}
catch (err) {
if (!fulfilled) {
fulfilled = true;
reject(err);
}
}
});
}
}
async runSwc(options, extras, swcrcFilePath) {
process.nextTick(() => console.log(constants_1.SWC_LOG_PREFIX, chalk.cyan('Running...')));
const swcCli = this.loadSwcCliBinary();
const swcRcFile = await this.getSwcRcFileContentIfExists(swcrcFilePath);
const swcOptions = this.deepMerge(options.swcOptions, swcRcFile);
if (swcOptions?.jsc?.baseUrl && !(0, path_1.isAbsolute)(swcOptions?.jsc?.baseUrl)) {
// jsc.baseUrl should be resolved by the caller, if it's passed as an object.
// https://github.com/swc-project/swc/pull/7827
const rootDir = process.cwd();
swcOptions.jsc.baseUrl = path.join(rootDir, swcOptions.jsc.baseUrl);
}
await swcCli.default({
...options,
swcOptions,
cliOptions: {
...options.cliOptions,
watch: extras.watch,
},
});
}
loadSwcCliBinary() {
try {
return require('@swc/cli/lib/swc/dir');
}
catch (err) {
console.error(ui_1.ERROR_PREFIX +
' Failed to load "@swc/cli" and/or "@swc/core" required packages. Please, make sure to install them as development dependencies.');
process.exit(1);
}
}
getSwcRcFileContentIfExists(swcrcFilePath) {
try {
return JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(process.cwd(), swcrcFilePath ?? '.swcrc'), 'utf8'));
}
catch (err) {
if (swcrcFilePath !== undefined) {
console.error(ui_1.ERROR_PREFIX +
` Failed to load "${swcrcFilePath}". Please, check if the file exists and is valid JSON.`);
process.exit(1);
}
return {};
}
}
deepMerge(target, source) {
if (typeof target !== 'object' ||
target === null ||
typeof source !== 'object' ||
source === null) {
return source;
}
if (Array.isArray(target) && Array.isArray(source)) {
return source.reduce((acc, value, index) => {
acc[index] = this.deepMerge(target[index], value);
return acc;
}, target);
}
const merged = { ...target };
for (const key in source) {
if (source.hasOwnProperty(key)) {
if (key in target) {
merged[key] = this.deepMerge(target[key], source[key]);
}
else {
merged[key] = source[key];
}
}
}
return merged;
}
debounce(callback, wait) {
let timeout;
return () => {
clearTimeout(timeout);
timeout = setTimeout(callback, wait);
};
}
watchFilesInOutDir(options, onChange) {
const dir = (0, path_1.isAbsolute)(options.cliOptions.outDir)
? options.cliOptions.outDir
: (0, path_1.join)(process.cwd(), options.cliOptions.outDir);
const paths = (0, path_1.join)(dir, '**/*.js');
const watcher = chokidar.watch(paths, {
ignoreInitial: true,
awaitWriteFinish: {
stabilityThreshold: 50,
pollInterval: 10,
},
});
for (const type of ['add', 'change']) {
watcher.on(type, async () => onChange());
}
}
}
exports.SwcCompiler = SwcCompiler;

View File

@@ -0,0 +1,14 @@
import * as ts from 'typescript';
export interface TypeCheckerHostRunOptions {
watch?: boolean;
onTypeCheck?: (program: ts.Program) => void;
onProgramInit?: (program: ts.Program) => void;
}
export declare class TypeCheckerHost {
private readonly typescriptLoader;
private readonly tsConfigProvider;
run(tsconfigPath: string | undefined, options: TypeCheckerHostRunOptions): void;
private runInWatchMode;
private runOnce;
private createWatchCompilerHost;
}

View File

@@ -0,0 +1,90 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TypeCheckerHost = void 0;
const chalk = require("chalk");
const ora = require("ora");
const ts = require("typescript");
const tsconfig_provider_1 = require("../helpers/tsconfig-provider");
const typescript_loader_1 = require("../typescript-loader");
const constants_1 = require("./constants");
class TypeCheckerHost {
constructor() {
this.typescriptLoader = new typescript_loader_1.TypeScriptBinaryLoader();
this.tsConfigProvider = new tsconfig_provider_1.TsConfigProvider(this.typescriptLoader);
}
run(tsconfigPath, options) {
if (!tsconfigPath) {
throw new Error('"tsconfigPath" is required when "tsProgramRef" is not provided.');
}
const tsBinary = this.typescriptLoader.load();
const spinner = ora({
text: constants_1.INITIALIZING_TYPE_CHECKER,
});
if (options.watch) {
console.log();
spinner.start();
this.runInWatchMode(tsconfigPath, tsBinary, options);
spinner.succeed();
return;
}
spinner.start();
this.runOnce(tsconfigPath, tsBinary, options);
spinner.succeed();
}
runInWatchMode(tsconfigPath, tsBinary, options) {
const { options: tsOptions } = this.tsConfigProvider.getByConfigFilename(tsconfigPath);
let builderProgram = undefined;
const reportWatchStatusCallback = (diagnostic) => {
if (diagnostic.messageText !== constants_1.TSC_NO_ERRORS_MESSAGE) {
if (diagnostic.messageText?.includes('Found')) {
console.log(constants_1.TSC_LOG_ERROR_PREFIX, chalk.red(diagnostic.messageText));
}
return;
}
if (!builderProgram) {
return;
}
const tsProgram = builderProgram.getProgram().getProgram();
options.onTypeCheck?.(tsProgram);
};
const host = this.createWatchCompilerHost(tsBinary, tsconfigPath, tsOptions, reportWatchStatusCallback);
builderProgram = tsBinary.createWatchProgram(host);
process.nextTick(() => {
options.onProgramInit?.(builderProgram.getProgram().getProgram());
});
}
runOnce(tsconfigPath, tsBinary, options) {
const { options: tsOptions, fileNames, projectReferences, } = this.tsConfigProvider.getByConfigFilename(tsconfigPath);
const createProgram = tsBinary.createIncrementalProgram ?? tsBinary.createProgram;
const program = createProgram.call(ts, {
rootNames: fileNames,
projectReferences,
options: tsOptions,
});
const programRef = program.getProgram
? program.getProgram()
: program;
const diagnostics = tsBinary.getPreEmitDiagnostics(programRef);
if (diagnostics.length > 0) {
const formatDiagnosticsHost = {
getCanonicalFileName: (path) => path,
getCurrentDirectory: tsBinary.sys.getCurrentDirectory,
getNewLine: () => tsBinary.sys.newLine,
};
console.log();
console.log(tsBinary.formatDiagnosticsWithColorAndContext(diagnostics, formatDiagnosticsHost));
process.exit(1);
}
options.onTypeCheck?.(programRef);
}
createWatchCompilerHost(tsBinary, tsConfigPath, options, reportWatchStatusCallback) {
const origDiagnosticReporter = tsBinary.createDiagnosticReporter(tsBinary.sys, true);
const tsOptions = {
...options,
preserveWatchOutput: true,
noEmit: true,
};
return tsBinary.createWatchCompilerHost(tsConfigPath, tsOptions, tsBinary.sys, undefined, origDiagnosticReporter, reportWatchStatusCallback);
}
}
exports.TypeCheckerHost = TypeCheckerHost;

View File

@@ -0,0 +1,6 @@
import * as ts from 'typescript';
export declare class TypeScriptBinaryLoader {
private tsBinary?;
load(): typeof ts;
getModulePaths(): string[];
}

View File

@@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TypeScriptBinaryLoader = void 0;
class TypeScriptBinaryLoader {
load() {
if (this.tsBinary) {
return this.tsBinary;
}
try {
const tsBinaryPath = require.resolve('typescript', {
paths: [process.cwd(), ...this.getModulePaths()],
});
// eslint-disable-next-line @typescript-eslint/no-var-requires
const tsBinary = require(tsBinaryPath);
this.tsBinary = tsBinary;
return tsBinary;
}
catch {
throw new Error('TypeScript could not be found! Please, install "typescript" package.');
}
}
getModulePaths() {
const modulePaths = module.paths.slice(2, module.paths.length);
const packageDeps = modulePaths.slice(0, 3);
return [
...packageDeps.reverse(),
...modulePaths.slice(3, modulePaths.length).reverse(),
];
}
}
exports.TypeScriptBinaryLoader = TypeScriptBinaryLoader;

View File

@@ -0,0 +1,22 @@
import { Configuration } from '../configuration';
import { BaseCompiler } from './base-compiler';
import { TsConfigProvider } from './helpers/tsconfig-provider';
import { PluginsLoader } from './plugins/plugins-loader';
import { TypeScriptBinaryLoader } from './typescript-loader';
type TypescriptWatchCompilerExtras = {
/**
* If `undefined`, the value of 'preserveWatchOutput' option from tsconfig
* file will be used instead.
*/
preserveWatchOutput: boolean | undefined;
};
export declare class WatchCompiler extends BaseCompiler<TypescriptWatchCompilerExtras> {
private readonly tsConfigProvider;
private readonly typescriptLoader;
constructor(pluginsLoader: PluginsLoader, tsConfigProvider: TsConfigProvider, typescriptLoader: TypeScriptBinaryLoader);
run(configuration: Required<Configuration>, tsConfigPath: string, appName: string, extras: TypescriptWatchCompilerExtras, onSuccess?: () => void): void;
private overrideCreateProgramFn;
private createDiagnosticReporter;
private createWatchStatusChanged;
}
export {};

View File

@@ -0,0 +1,89 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WatchCompiler = void 0;
const errors_1 = require("../ui/errors");
const base_compiler_1 = require("./base-compiler");
const get_value_or_default_1 = require("./helpers/get-value-or-default");
const manual_restart_1 = require("./helpers/manual-restart");
const tsconfig_paths_hook_1 = require("./hooks/tsconfig-paths.hook");
class WatchCompiler extends base_compiler_1.BaseCompiler {
constructor(pluginsLoader, tsConfigProvider, typescriptLoader) {
super(pluginsLoader);
this.tsConfigProvider = tsConfigProvider;
this.typescriptLoader = typescriptLoader;
}
run(configuration, tsConfigPath, appName, extras, onSuccess) {
const tsBin = this.typescriptLoader.load();
const configPath = tsBin.findConfigFile(process.cwd(), tsBin.sys.fileExists, tsConfigPath);
if (!configPath) {
throw new Error(errors_1.CLI_ERRORS.MISSING_TYPESCRIPT(tsConfigPath));
}
const { options, projectReferences } = this.tsConfigProvider.getByConfigFilename(tsConfigPath);
const createProgram = tsBin.createEmitAndSemanticDiagnosticsBuilderProgram;
const origDiagnosticReporter = tsBin.createDiagnosticReporter(tsBin.sys, true);
const origWatchStatusReporter = tsBin.createWatchStatusReporter(tsBin.sys, true);
const host = tsBin.createWatchCompilerHost(configPath, {
...options,
preserveWatchOutput: extras.preserveWatchOutput ?? options.preserveWatchOutput,
}, tsBin.sys, createProgram, this.createDiagnosticReporter(origDiagnosticReporter), this.createWatchStatusChanged(origWatchStatusReporter, onSuccess));
const manualRestart = (0, get_value_or_default_1.getValueOrDefault)(configuration, 'compilerOptions.manualRestart', appName);
const plugins = this.loadPlugins(configuration, tsConfigPath, appName);
this.overrideCreateProgramFn(host, manualRestart, projectReferences, plugins);
const watchProgram = tsBin.createWatchProgram(host);
if (manualRestart) {
(0, manual_restart_1.listenForManualRestart)(() => {
watchProgram.close();
this.run(configuration, tsConfigPath, appName, extras, onSuccess);
});
}
}
overrideCreateProgramFn(host, manualRestart, projectReferences, plugins) {
const origCreateProgram = host.createProgram;
host.createProgram = (rootNames, options,
// tslint:disable-next-line:no-shadowed-variable
host, oldProgram) => {
if (manualRestart) {
(0, manual_restart_1.displayManualRestartTip)();
}
const tsconfigPathsPlugin = options
? (0, tsconfig_paths_hook_1.tsconfigPathsBeforeHookFactory)(options)
: null;
const program = origCreateProgram(rootNames, options, host, oldProgram, undefined, projectReferences);
const origProgramEmit = program.emit;
program.emit = (targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) => {
let transforms = customTransformers;
transforms = typeof transforms !== 'object' ? {} : transforms;
const before = plugins.beforeHooks.map((hook) => hook(program.getProgram()));
const after = plugins.afterHooks.map((hook) => hook(program.getProgram()));
const afterDeclarations = plugins.afterDeclarationsHooks.map((hook) => hook(program.getProgram()));
if (tsconfigPathsPlugin) {
before.unshift(tsconfigPathsPlugin);
}
transforms.before = before.concat(transforms.before || []);
transforms.after = after.concat(transforms.after || []);
transforms.afterDeclarations = afterDeclarations.concat(transforms.afterDeclarations || []);
return origProgramEmit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, transforms);
};
return program;
};
}
createDiagnosticReporter(diagnosticReporter) {
return function (diagnostic, ...args) {
return diagnosticReporter.call(this, diagnostic, ...args);
};
}
createWatchStatusChanged(watchStatusReporter, onSuccess) {
return function (diagnostic, ...args) {
const messageText = diagnostic && diagnostic.messageText;
const noErrorsMessage = '0 errors';
if (messageText &&
messageText.includes &&
messageText.includes(noErrorsMessage) &&
onSuccess) {
onSuccess();
}
return watchStatusReporter.call(this, diagnostic, ...args);
};
}
}
exports.WatchCompiler = WatchCompiler;

View File

@@ -0,0 +1,21 @@
import { Input } from '../../commands';
import { Configuration } from '../configuration';
import { AssetsManager } from './assets-manager';
import { BaseCompiler } from './base-compiler';
import { PluginsLoader } from './plugins/plugins-loader';
import webpack = require('webpack');
type WebpackConfigFactory = (config: webpack.Configuration, webpackRef: typeof webpack) => webpack.Configuration;
type WebpackConfigFactoryOrConfig = WebpackConfigFactory | webpack.Configuration;
type WebpackCompilerExtras = {
inputs: Input[];
assetsManager: AssetsManager;
webpackConfigFactoryOrConfig: WebpackConfigFactoryOrConfig | WebpackConfigFactoryOrConfig[];
debug?: boolean;
watchMode?: boolean;
};
export declare class WebpackCompiler extends BaseCompiler<WebpackCompilerExtras> {
constructor(pluginsLoader: PluginsLoader);
run(configuration: Required<Configuration>, tsConfigPath: string, appName: string, extras: WebpackCompilerExtras, onSuccess?: () => void): void;
private createAfterCallback;
}
export {};

Some files were not shown because too many files have changed in this diff Show More