generated from nhcarrigan/template
feat: initial scaffolding
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
# Editor configuration, see http://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
max_line_length = off
|
||||||
|
trim_trailing_whitespace = false
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
# See https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
|
||||||
|
|
||||||
|
# compiled output
|
||||||
|
dist
|
||||||
|
tmp
|
||||||
|
out-tsc
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# IDEs and editors
|
||||||
|
/.idea
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.c9/
|
||||||
|
*.launch
|
||||||
|
.settings/
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# IDE - VSCode
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
|
||||||
|
# misc
|
||||||
|
/.sass-cache
|
||||||
|
/connect.lock
|
||||||
|
/coverage
|
||||||
|
/libpeerconnection.log
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
testem.log
|
||||||
|
/typings
|
||||||
|
|
||||||
|
# System Files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
.nx/cache
|
||||||
|
.nx/workspace-data
|
||||||
|
|
||||||
|
.angular
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"nrwl.angular-console",
|
||||||
|
"esbenp.prettier-vscode",
|
||||||
|
"dbaeumer.vscode-eslint",
|
||||||
|
"firsttris.vscode-jest-runner"
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+23
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Debug api with Nx",
|
||||||
|
"runtimeExecutable": "pnpm exec",
|
||||||
|
"runtimeArgs": ["nx", "serve", "api"],
|
||||||
|
"env": {
|
||||||
|
"NODE_OPTIONS": "--inspect=9229"
|
||||||
|
},
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"internalConsoleOptions": "neverOpen",
|
||||||
|
"skipFiles": ["<node_internals>/**"],
|
||||||
|
"sourceMaps": true,
|
||||||
|
"outFiles": [
|
||||||
|
"${workspaceFolder}/api/dist/**/*.(m|c|)js",
|
||||||
|
"!**/node_modules/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
# Library App Planning Document 📚🎮🎵
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
A personal library tracking website where Naomi can catalogue and display her games, music, and books across different status categories.
|
||||||
|
|
||||||
|
## Core Features
|
||||||
|
|
||||||
|
### 1. Multi-Media Library Support
|
||||||
|
- **Games**: Currently Playing, Completed, Backlog
|
||||||
|
- **Music**: Currently Listening, Completed Albums, Want to Listen
|
||||||
|
- **Books**: Currently Reading, Finished, To Read
|
||||||
|
|
||||||
|
### 2. Authentication & Permissions
|
||||||
|
- Public viewing for everyone (read-only)
|
||||||
|
- Admin authentication for Naomi only (full CRUD operations)
|
||||||
|
- OAuth integration (GitHub? Discord? Both?)
|
||||||
|
|
||||||
|
### 3. User Interface
|
||||||
|
- Clean, responsive design
|
||||||
|
- Easy navigation between media types
|
||||||
|
- Search and filter functionality
|
||||||
|
- Statistics/summary view
|
||||||
|
|
||||||
|
## Technical Stack Considerations
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
- **Framework**: Angular
|
||||||
|
- Excellent TypeScript support (built with TS in mind!)
|
||||||
|
- Powerful CLI and tooling
|
||||||
|
- Great for building robust SPAs
|
||||||
|
- Built-in RxJS for reactive programming
|
||||||
|
- Standalone components in newer versions
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
- **Framework**: Fastify
|
||||||
|
- Extremely fast Node.js framework
|
||||||
|
- First-class TypeScript support
|
||||||
|
- Built-in schema validation
|
||||||
|
- Great plugin ecosystem
|
||||||
|
- Excellent error handling
|
||||||
|
|
||||||
|
### Database
|
||||||
|
- **Database**: MongoDB (Atlas - existing instance)
|
||||||
|
- Perfect for flexible schema (games, books, music have different fields)
|
||||||
|
- Easy to add new fields without migrations
|
||||||
|
- Great performance for document queries
|
||||||
|
- **ORM**: Prisma
|
||||||
|
- Excellent TypeScript support
|
||||||
|
- Type-safe database queries
|
||||||
|
- Great MongoDB support
|
||||||
|
- Auto-generated types from schema
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
- **OAuth Provider**: Discord only
|
||||||
|
- Single OAuth provider for simplicity
|
||||||
|
- You already have Discord OAuth experience with Hikari bot
|
||||||
|
- JWT for session management
|
||||||
|
|
||||||
|
### Project Structure
|
||||||
|
- **Monorepo Tool**: Nx
|
||||||
|
- Excellent TypeScript support
|
||||||
|
- Great caching and build optimization
|
||||||
|
- Powerful generators
|
||||||
|
- Shared dependencies
|
||||||
|
- Integrated testing and linting
|
||||||
|
- **Linting**: @nhcarrigan/eslint-config
|
||||||
|
- Your custom ESLint configuration
|
||||||
|
- ESLint 9 flat config
|
||||||
|
- No Prettier needed!
|
||||||
|
|
||||||
|
### Hosting
|
||||||
|
- **Options**:
|
||||||
|
- Self-hosted on your infrastructure (full control!)
|
||||||
|
- Netlify (Good alternative, better ethics)
|
||||||
|
- Railway (Developer-friendly, good values)
|
||||||
|
- Fly.io (Great for full-stack apps)
|
||||||
|
- DigitalOcean App Platform
|
||||||
|
|
||||||
|
## Data Models (Initial Thoughts)
|
||||||
|
|
||||||
|
### MongoDB Collections Structure
|
||||||
|
We'll have three main collections: `games`, `books`, and `music`, each with their specific schema.
|
||||||
|
|
||||||
|
### Game
|
||||||
|
```typescript
|
||||||
|
interface Game {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
platform?: string;
|
||||||
|
status: 'playing' | 'completed' | 'backlog';
|
||||||
|
dateAdded: Date;
|
||||||
|
dateCompleted?: Date;
|
||||||
|
rating?: number;
|
||||||
|
notes?: string;
|
||||||
|
coverImage?: string;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Book
|
||||||
|
```typescript
|
||||||
|
interface Book {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
author: string;
|
||||||
|
isbn?: string;
|
||||||
|
status: 'reading' | 'finished' | 'toRead';
|
||||||
|
dateAdded: Date;
|
||||||
|
dateFinished?: Date;
|
||||||
|
rating?: number;
|
||||||
|
notes?: string;
|
||||||
|
coverImage?: string;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Music
|
||||||
|
```typescript
|
||||||
|
interface Music {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
artist: string;
|
||||||
|
type: 'album' | 'single' | 'ep';
|
||||||
|
status: 'listening' | 'completed' | 'wantToListen';
|
||||||
|
dateAdded: Date;
|
||||||
|
dateCompleted?: Date;
|
||||||
|
rating?: number;
|
||||||
|
notes?: string;
|
||||||
|
coverArt?: string;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Feature Roadmap
|
||||||
|
|
||||||
|
### Phase 1: MVP
|
||||||
|
- [ ] Basic CRUD for all three media types
|
||||||
|
- [ ] Simple authentication (single admin user)
|
||||||
|
- [ ] Public read-only view
|
||||||
|
- [ ] Basic responsive UI
|
||||||
|
|
||||||
|
### Phase 2: Enhancements
|
||||||
|
- [ ] Search and filtering
|
||||||
|
- [ ] Statistics dashboard
|
||||||
|
- [ ] Cover image fetching from APIs
|
||||||
|
- [ ] Import/export functionality
|
||||||
|
|
||||||
|
### Phase 3: Advanced Features
|
||||||
|
- [ ] Recommendations system
|
||||||
|
- [ ] Progress tracking (% complete for books/games)
|
||||||
|
- [ ] Tags/categories
|
||||||
|
- [ ] Public API for integrations
|
||||||
|
|
||||||
|
## Questions to Consider
|
||||||
|
|
||||||
|
1. **Design Aesthetic**: What vibe are you going for? Minimalist? Colourful? Dark theme?
|
||||||
|
|
||||||
|
2. **API Integrations**: Should we fetch metadata from external APIs?
|
||||||
|
- Games: IGDB, Steam API
|
||||||
|
- Books: Open Library, Google Books
|
||||||
|
- Music: Spotify, Last.fm, MusicBrainz
|
||||||
|
|
||||||
|
3. **URL Structure**: How should we organize routes?
|
||||||
|
- `/games`, `/books`, `/music`?
|
||||||
|
- `/library/games`, `/library/books`?
|
||||||
|
- Something else?
|
||||||
|
|
||||||
|
4. **Data Entry**: Manual entry only, or barcode scanning/search integration?
|
||||||
|
|
||||||
|
5. **Privacy**: Any items you'd want to keep private even from public view?
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
1. Choose technical stack
|
||||||
|
2. Set up project structure
|
||||||
|
3. Design database schema
|
||||||
|
4. Create authentication flow
|
||||||
|
5. Build first media type (games?) as proof of concept
|
||||||
|
6. Iterate and add remaining media types
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*✨ This planning document was created with love by Hikari and Naomi! 🌸*
|
||||||
@@ -1,39 +1,101 @@
|
|||||||
# New Repository Template
|
# Library
|
||||||
|
|
||||||
This template contains all of our basic files for a new GitHub repository. There is also a handy workflow that will create an issue on a new repository made from this template, with a checklist for the steps we usually take in setting up a new repository.
|
<a alt="Nx logo" href="https://nx.dev" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.png" width="45"></a>
|
||||||
|
|
||||||
If you're starting a Node.JS project with TypeScript, we have a [specific template](https://github.com/naomi-lgbt/nodejs-typescript-template) for that purpose.
|
✨ Your new, shiny [Nx workspace](https://nx.dev) is ready ✨.
|
||||||
|
|
||||||
## Readme
|
[Learn more about this workspace setup and its capabilities](https://nx.dev/getting-started/tutorials/angular-monorepo-tutorial?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or run `npx nx graph` to visually explore what was created. Now, let's get you up to speed!
|
||||||
|
|
||||||
Delete all of the above text (including this line), and uncomment the below text to use our standard readme template.
|
## Run tasks
|
||||||
|
|
||||||
<!-- # Project Name
|
To run the dev server for your app, use:
|
||||||
|
|
||||||
Project Description
|
```sh
|
||||||
|
npx nx serve frontend
|
||||||
|
```
|
||||||
|
|
||||||
## Live Version
|
To create a production bundle:
|
||||||
|
|
||||||
This page is currently deployed. [View the live website.]
|
```sh
|
||||||
|
npx nx build frontend
|
||||||
|
```
|
||||||
|
|
||||||
## Feedback and Bugs
|
To see all available targets to run for a project, run:
|
||||||
|
|
||||||
If you have feedback or a bug report, please [log a ticket on our forum](https://support.nhcarrigan.com).
|
```sh
|
||||||
|
npx nx show project frontend
|
||||||
|
```
|
||||||
|
|
||||||
## Contributing
|
These targets are either [inferred automatically](https://nx.dev/concepts/inferred-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or defined in the `project.json` or `package.json` files.
|
||||||
|
|
||||||
If you would like to contribute to the project, you may create a Pull Request containing your proposed changes and we will review it as soon as we are able! Please review our [contributing guidelines](CONTRIBUTING.md) first.
|
[More about running tasks in the docs »](https://nx.dev/features/run-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
|
|
||||||
## Code of Conduct
|
## Add new projects
|
||||||
|
|
||||||
Before interacting with our community, please read our [Code of Conduct](CODE_OF_CONDUCT.md).
|
While you could add new projects to your workspace manually, you might want to leverage [Nx plugins](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) and their [code generation](https://nx.dev/features/generate-code?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) feature.
|
||||||
|
|
||||||
## License
|
Use the plugin's generator to create new projects.
|
||||||
|
|
||||||
This software is licensed under our [global software license](https://docs.nhcarrigan.com/#/license).
|
To generate a new application, use:
|
||||||
|
|
||||||
Copyright held by Naomi Carrigan.
|
```sh
|
||||||
|
npx nx g @nx/angular:app demo
|
||||||
|
```
|
||||||
|
|
||||||
## Contact
|
To generate a new library, use:
|
||||||
|
|
||||||
We may be contacted through our [Chat Server](http://chat.nhcarrigan.com) or via email at `contact@nhcarrigan.com`. -->
|
```sh
|
||||||
|
npx nx g @nx/angular:lib mylib
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use `npx nx list` to get a list of installed plugins. Then, run `npx nx list <plugin-name>` to learn about more specific capabilities of a particular plugin. Alternatively, [install Nx Console](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) to browse plugins and generators in your IDE.
|
||||||
|
|
||||||
|
[Learn more about Nx plugins »](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) | [Browse the plugin registry »](https://nx.dev/plugin-registry?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
|
|
||||||
|
## Set up CI!
|
||||||
|
|
||||||
|
### Step 1
|
||||||
|
|
||||||
|
To connect to Nx Cloud, run the following command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npx nx connect
|
||||||
|
```
|
||||||
|
|
||||||
|
Connecting to Nx Cloud ensures a [fast and scalable CI](https://nx.dev/ci/intro/why-nx-cloud?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) pipeline. It includes features such as:
|
||||||
|
|
||||||
|
- [Remote caching](https://nx.dev/ci/features/remote-cache?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
|
- [Task distribution across multiple machines](https://nx.dev/ci/features/distribute-task-execution?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
|
- [Automated e2e test splitting](https://nx.dev/ci/features/split-e2e-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
|
- [Task flakiness detection and rerunning](https://nx.dev/ci/features/flaky-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
|
|
||||||
|
### Step 2
|
||||||
|
|
||||||
|
Use the following command to configure a CI workflow for your workspace:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npx nx g ci-workflow
|
||||||
|
```
|
||||||
|
|
||||||
|
[Learn more about Nx on CI](https://nx.dev/ci/intro/ci-with-nx#ready-get-started-with-your-provider?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
|
|
||||||
|
## Install Nx Console
|
||||||
|
|
||||||
|
Nx Console is an editor extension that enriches your developer experience. It lets you run tasks, generate code, and improves code autocompletion in your IDE. It is available for VSCode and IntelliJ.
|
||||||
|
|
||||||
|
[Install Nx Console »](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
|
|
||||||
|
## Useful links
|
||||||
|
|
||||||
|
Learn more:
|
||||||
|
|
||||||
|
- [Learn more about this workspace setup](https://nx.dev/getting-started/tutorials/angular-monorepo-tutorial?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
|
- [Learn about Nx on CI](https://nx.dev/ci/intro/ci-with-nx?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
|
- [Releasing Packages with Nx release](https://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
|
- [What are Nx plugins?](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
|
|
||||||
|
And join the Nx community:
|
||||||
|
- [Discord](https://go.nx.dev/community)
|
||||||
|
- [Follow us on X](https://twitter.com/nxdevtools) or [LinkedIn](https://www.linkedin.com/company/nrwl)
|
||||||
|
- [Our Youtube channel](https://www.youtube.com/@nxdevtools)
|
||||||
|
- [Our blog](https://nx.dev/blog?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
node_modules
|
||||||
|
# Keep environment variables out of version control
|
||||||
|
.env
|
||||||
|
|
||||||
|
/generated/prisma
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
module.exports = {
|
||||||
|
displayName: 'api',
|
||||||
|
preset: '../jest.preset.js',
|
||||||
|
testEnvironment: 'node',
|
||||||
|
transform: {
|
||||||
|
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
|
||||||
|
},
|
||||||
|
moduleFileExtensions: ['ts', 'js', 'html'],
|
||||||
|
coverageDirectory: '../coverage/api',
|
||||||
|
};
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// This file was generated by Prisma, and assumes you have installed the following:
|
||||||
|
// npm install --save-dev prisma dotenv
|
||||||
|
import "dotenv/config";
|
||||||
|
import { defineConfig } from "prisma/config";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
schema: "prisma/schema.prisma",
|
||||||
|
migrations: {
|
||||||
|
path: "prisma/migrations",
|
||||||
|
},
|
||||||
|
datasource: {
|
||||||
|
url: process.env["DATABASE_URL"],
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
// This is your Prisma schema file,
|
||||||
|
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||||
|
|
||||||
|
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
|
||||||
|
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
|
||||||
|
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client"
|
||||||
|
output = "../generated/prisma"
|
||||||
|
}
|
||||||
|
|
||||||
|
datasource db {
|
||||||
|
provider = "mongodb"
|
||||||
|
}
|
||||||
|
|
||||||
|
model Game {
|
||||||
|
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||||
|
title String
|
||||||
|
platform String?
|
||||||
|
status GameStatus
|
||||||
|
dateAdded DateTime @default(now())
|
||||||
|
dateCompleted DateTime?
|
||||||
|
rating Int? @db.Int @default(0)
|
||||||
|
notes String?
|
||||||
|
coverImage String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
}
|
||||||
|
|
||||||
|
enum GameStatus {
|
||||||
|
PLAYING
|
||||||
|
COMPLETED
|
||||||
|
BACKLOG
|
||||||
|
}
|
||||||
|
|
||||||
|
model Book {
|
||||||
|
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||||
|
title String
|
||||||
|
author String
|
||||||
|
isbn String?
|
||||||
|
status BookStatus
|
||||||
|
dateAdded DateTime @default(now())
|
||||||
|
dateFinished DateTime?
|
||||||
|
rating Int? @db.Int @default(0)
|
||||||
|
notes String?
|
||||||
|
coverImage String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
}
|
||||||
|
|
||||||
|
enum BookStatus {
|
||||||
|
READING
|
||||||
|
FINISHED
|
||||||
|
TO_READ
|
||||||
|
}
|
||||||
|
|
||||||
|
model Music {
|
||||||
|
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||||
|
title String
|
||||||
|
artist String
|
||||||
|
type MusicType
|
||||||
|
status MusicStatus
|
||||||
|
dateAdded DateTime @default(now())
|
||||||
|
dateCompleted DateTime?
|
||||||
|
rating Int? @db.Int @default(0)
|
||||||
|
notes String?
|
||||||
|
coverArt String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MusicType {
|
||||||
|
ALBUM
|
||||||
|
SINGLE
|
||||||
|
EP
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MusicStatus {
|
||||||
|
LISTENING
|
||||||
|
COMPLETED
|
||||||
|
WANT_TO_LISTEN
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
{
|
||||||
|
"name": "api",
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"sourceRoot": "api/src",
|
||||||
|
"projectType": "application",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {
|
||||||
|
"build": {
|
||||||
|
"executor": "@nx/esbuild:esbuild",
|
||||||
|
"outputs": ["{options.outputPath}"],
|
||||||
|
"defaultConfiguration": "production",
|
||||||
|
"options": {
|
||||||
|
"platform": "node",
|
||||||
|
"outputPath": "dist/api",
|
||||||
|
"format": ["cjs"],
|
||||||
|
"bundle": false,
|
||||||
|
"main": "api/src/main.ts",
|
||||||
|
"tsConfig": "api/tsconfig.app.json",
|
||||||
|
"assets": ["api/src/assets"],
|
||||||
|
"generatePackageJson": true,
|
||||||
|
"esbuildOptions": {
|
||||||
|
"sourcemap": true,
|
||||||
|
"outExtension": {
|
||||||
|
".js": ".js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"development": {},
|
||||||
|
"production": {
|
||||||
|
"esbuildOptions": {
|
||||||
|
"sourcemap": false,
|
||||||
|
"outExtension": {
|
||||||
|
".js": ".js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"prune-lockfile": {
|
||||||
|
"dependsOn": ["build"],
|
||||||
|
"cache": true,
|
||||||
|
"executor": "@nx/js:prune-lockfile",
|
||||||
|
"outputs": [
|
||||||
|
"{workspaceRoot}/dist/api/package.json",
|
||||||
|
"{workspaceRoot}/dist/api/pnpm-lock.yaml"
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"buildTarget": "build"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"copy-workspace-modules": {
|
||||||
|
"dependsOn": ["build"],
|
||||||
|
"cache": true,
|
||||||
|
"outputs": ["{workspaceRoot}/dist/api/workspace_modules"],
|
||||||
|
"executor": "@nx/js:copy-workspace-modules",
|
||||||
|
"options": {
|
||||||
|
"buildTarget": "build"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"prune": {
|
||||||
|
"dependsOn": ["prune-lockfile", "copy-workspace-modules"],
|
||||||
|
"executor": "nx:noop"
|
||||||
|
},
|
||||||
|
"serve": {
|
||||||
|
"continuous": true,
|
||||||
|
"executor": "@nx/js:node",
|
||||||
|
"defaultConfiguration": "development",
|
||||||
|
"dependsOn": ["build"],
|
||||||
|
"options": {
|
||||||
|
"buildTarget": "api:build",
|
||||||
|
"runBuildTargetDependencies": false
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"development": {
|
||||||
|
"buildTarget": "api:build:development"
|
||||||
|
},
|
||||||
|
"production": {
|
||||||
|
"buildTarget": "api:build:production"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"options": {
|
||||||
|
"passWithNoTests": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import Fastify, { FastifyInstance } from 'fastify';
|
||||||
|
import { app } from './app';
|
||||||
|
|
||||||
|
describe('GET /', () => {
|
||||||
|
let server: FastifyInstance;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
server = Fastify();
|
||||||
|
server.register(app);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should respond with a message', async () => {
|
||||||
|
const response = await server.inject({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(response.json()).toEqual({ message: 'Hello API' });
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import * as path from 'path';
|
||||||
|
import { FastifyInstance } from 'fastify';
|
||||||
|
import AutoLoad from '@fastify/autoload';
|
||||||
|
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
export interface AppOptions {}
|
||||||
|
|
||||||
|
export async function app(fastify: FastifyInstance, opts: AppOptions) {
|
||||||
|
// Place here your custom code!
|
||||||
|
|
||||||
|
// Do not touch the following lines
|
||||||
|
|
||||||
|
// This loads all plugins defined in plugins
|
||||||
|
// those should be support plugins that are reused
|
||||||
|
// through your application
|
||||||
|
fastify.register(AutoLoad, {
|
||||||
|
dir: path.join(__dirname, 'plugins'),
|
||||||
|
options: { ...opts },
|
||||||
|
});
|
||||||
|
|
||||||
|
// This loads all plugins defined in routes
|
||||||
|
// define your routes in one of these
|
||||||
|
fastify.register(AutoLoad, {
|
||||||
|
dir: path.join(__dirname, 'routes'),
|
||||||
|
options: { ...opts },
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { FastifyInstance } from 'fastify';
|
||||||
|
import fp from 'fastify-plugin';
|
||||||
|
import sensible from '@fastify/sensible';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This plugins adds some utilities to handle http errors
|
||||||
|
*
|
||||||
|
* @see https://github.com/fastify/fastify-sensible
|
||||||
|
*/
|
||||||
|
export default fp(async function (fastify: FastifyInstance) {
|
||||||
|
fastify.register(sensible);
|
||||||
|
});
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { FastifyInstance } from 'fastify';
|
||||||
|
|
||||||
|
export default async function (fastify: FastifyInstance) {
|
||||||
|
fastify.get('/', async function () {
|
||||||
|
return { message: 'Hello API' };
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import Fastify from 'fastify';
|
||||||
|
import { app } from './app/app';
|
||||||
|
|
||||||
|
const host = process.env.HOST ?? 'localhost';
|
||||||
|
const port = process.env.PORT ? Number(process.env.PORT) : 3000;
|
||||||
|
|
||||||
|
// Instantiate Fastify with some config
|
||||||
|
const server = Fastify({
|
||||||
|
logger: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Register your application as a normal plugin.
|
||||||
|
server.register(app);
|
||||||
|
|
||||||
|
// Start listening.
|
||||||
|
server.listen({ port, host }, (err) => {
|
||||||
|
if (err) {
|
||||||
|
server.log.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
} else {
|
||||||
|
console.log(`[ ready ] http://${host}:${port}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../dist/out-tsc",
|
||||||
|
"module": "commonjs",
|
||||||
|
"types": ["node"]
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts"],
|
||||||
|
"exclude": [
|
||||||
|
"jest.config.ts",
|
||||||
|
"jest.config.cts",
|
||||||
|
"src/**/*.spec.ts",
|
||||||
|
"src/**/*.test.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"extends": "../tsconfig.base.json",
|
||||||
|
"files": [],
|
||||||
|
"include": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.app.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.spec.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"compilerOptions": {
|
||||||
|
"esModuleInterop": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../dist/out-tsc",
|
||||||
|
"module": "commonjs",
|
||||||
|
"moduleResolution": "node10",
|
||||||
|
"types": ["jest", "node"]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"jest.config.ts",
|
||||||
|
"jest.config.cts",
|
||||||
|
"src/**/*.test.ts",
|
||||||
|
"src/**/*.spec.ts",
|
||||||
|
"src/**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset';
|
||||||
|
import { defineConfig } from 'cypress';
|
||||||
|
export default defineConfig({
|
||||||
|
e2e: {
|
||||||
|
...nxE2EPreset(__filename, {
|
||||||
|
cypressDir: 'src',
|
||||||
|
webServerCommands: {
|
||||||
|
default: 'pnpm exec nx run frontend:serve',
|
||||||
|
production: 'pnpm exec nx run frontend:serve-static',
|
||||||
|
},
|
||||||
|
ciWebServerCommand: 'pnpm exec nx run frontend:serve-static',
|
||||||
|
ciBaseUrl: 'http://localhost:4200',
|
||||||
|
}),
|
||||||
|
baseUrl: 'http://localhost:4200',
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import cypress from 'eslint-plugin-cypress/flat';
|
||||||
|
import baseConfig from '../../eslint.config.mjs';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
cypress.configs['recommended'],
|
||||||
|
...baseConfig,
|
||||||
|
{
|
||||||
|
// Override or add rules here
|
||||||
|
rules: {},
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"name": "frontend-e2e",
|
||||||
|
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"projectType": "application",
|
||||||
|
"sourceRoot": "apps/frontend-e2e/src",
|
||||||
|
"tags": [],
|
||||||
|
"implicitDependencies": ["frontend"],
|
||||||
|
"// targets": "to see all targets run: nx show project frontend-e2e --web",
|
||||||
|
"targets": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { getGreeting } from '../support/app.po';
|
||||||
|
|
||||||
|
describe('frontend-e2e', () => {
|
||||||
|
beforeEach(() => cy.visit('/'));
|
||||||
|
|
||||||
|
it('should display welcome message', () => {
|
||||||
|
// Custom command example, see `../support/commands.ts` file
|
||||||
|
cy.login('my-email@something.com', 'myPassword');
|
||||||
|
|
||||||
|
// Function helper example, see `../support/app.po.ts` file
|
||||||
|
getGreeting().contains(/Welcome/);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"name": "Using fixtures to represent data",
|
||||||
|
"email": "hello@cypress.io",
|
||||||
|
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const getGreeting = () => cy.get('h1');
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/// <reference types="cypress" />
|
||||||
|
|
||||||
|
// ***********************************************
|
||||||
|
// This example commands.ts shows you how to
|
||||||
|
// create various custom commands and overwrite
|
||||||
|
// existing commands.
|
||||||
|
//
|
||||||
|
// For more comprehensive examples of custom
|
||||||
|
// commands please read more here:
|
||||||
|
// https://on.cypress.io/custom-commands
|
||||||
|
// ***********************************************
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
|
declare namespace Cypress {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
interface Chainable<Subject> {
|
||||||
|
login(email: string, password: string): void;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- This is a parent command --
|
||||||
|
Cypress.Commands.add('login', (email, password) => {
|
||||||
|
console.log('Custom command example: Login', email, password);
|
||||||
|
});
|
||||||
|
//
|
||||||
|
// -- This is a child command --
|
||||||
|
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This is a dual command --
|
||||||
|
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This will overwrite an existing command --
|
||||||
|
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// ***********************************************************
|
||||||
|
// This example support/e2e.ts is processed and
|
||||||
|
// loaded automatically before your test files.
|
||||||
|
//
|
||||||
|
// This is a great place to put global configuration and
|
||||||
|
// behavior that modifies Cypress.
|
||||||
|
//
|
||||||
|
// You can change the location of this file or turn off
|
||||||
|
// automatically serving support files with the
|
||||||
|
// 'supportFile' configuration option.
|
||||||
|
//
|
||||||
|
// You can read more here:
|
||||||
|
// https://on.cypress.io/configuration
|
||||||
|
// ***********************************************************
|
||||||
|
|
||||||
|
// Import commands.ts using ES2015 syntax:
|
||||||
|
import './commands';
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"moduleResolution": "node10",
|
||||||
|
"allowJs": true,
|
||||||
|
"outDir": "../../dist/out-tsc",
|
||||||
|
"module": "commonjs",
|
||||||
|
"types": ["cypress", "node"],
|
||||||
|
"sourceMap": false,
|
||||||
|
"strict": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"noPropertyAccessFromIndexSignature": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noFallthroughCasesInSwitch": true
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.js",
|
||||||
|
"cypress.config.ts",
|
||||||
|
"**/*.cy.ts",
|
||||||
|
"**/*.cy.js",
|
||||||
|
"**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import nx from '@nx/eslint-plugin';
|
||||||
|
import baseConfig from '../../eslint.config.mjs';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
...baseConfig,
|
||||||
|
...nx.configs['flat/angular'],
|
||||||
|
...nx.configs['flat/angular-template'],
|
||||||
|
{
|
||||||
|
files: ['**/*.ts'],
|
||||||
|
rules: {
|
||||||
|
'@angular-eslint/directive-selector': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
type: 'attribute',
|
||||||
|
prefix: 'app',
|
||||||
|
style: 'camelCase',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@angular-eslint/component-selector': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
type: 'element',
|
||||||
|
prefix: 'app',
|
||||||
|
style: 'kebab-case',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['**/*.html'],
|
||||||
|
// Override or add rules here
|
||||||
|
rules: {},
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
{
|
||||||
|
"name": "frontend",
|
||||||
|
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"projectType": "application",
|
||||||
|
"prefix": "app",
|
||||||
|
"sourceRoot": "apps/frontend/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {
|
||||||
|
"build": {
|
||||||
|
"executor": "@angular-devkit/build-angular:browser",
|
||||||
|
"outputs": ["{options.outputPath}"],
|
||||||
|
"options": {
|
||||||
|
"outputPath": "dist/apps/frontend",
|
||||||
|
"index": "apps/frontend/src/index.html",
|
||||||
|
"main": "apps/frontend/src/main.ts",
|
||||||
|
"tsConfig": "apps/frontend/tsconfig.app.json",
|
||||||
|
"inlineStyleLanguage": "scss",
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"glob": "**/*",
|
||||||
|
"input": "apps/frontend/public"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"styles": ["apps/frontend/src/styles.scss"]
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"budgets": [
|
||||||
|
{
|
||||||
|
"type": "initial",
|
||||||
|
"maximumWarning": "500kb",
|
||||||
|
"maximumError": "1mb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "anyComponentStyle",
|
||||||
|
"maximumWarning": "4kb",
|
||||||
|
"maximumError": "8kb"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputHashing": "all"
|
||||||
|
},
|
||||||
|
"development": {
|
||||||
|
"buildOptimizer": false,
|
||||||
|
"optimization": false,
|
||||||
|
"vendorChunk": true,
|
||||||
|
"extractLicenses": false,
|
||||||
|
"sourceMap": true,
|
||||||
|
"namedChunks": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "production"
|
||||||
|
},
|
||||||
|
"serve": {
|
||||||
|
"continuous": true,
|
||||||
|
"executor": "@angular-devkit/build-angular:dev-server",
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"buildTarget": "frontend:build:production"
|
||||||
|
},
|
||||||
|
"development": {
|
||||||
|
"buildTarget": "frontend:build:development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "development"
|
||||||
|
},
|
||||||
|
"extract-i18n": {
|
||||||
|
"executor": "@angular-devkit/build-angular:extract-i18n",
|
||||||
|
"options": {
|
||||||
|
"buildTarget": "frontend:build"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"executor": "@nx/eslint:lint"
|
||||||
|
},
|
||||||
|
"serve-static": {
|
||||||
|
"continuous": true,
|
||||||
|
"executor": "@nx/web:file-server",
|
||||||
|
"options": {
|
||||||
|
"buildTarget": "frontend:build",
|
||||||
|
"port": 4200,
|
||||||
|
"spa": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,10 @@
|
|||||||
|
import {
|
||||||
|
ApplicationConfig,
|
||||||
|
provideBrowserGlobalErrorListeners,
|
||||||
|
} from '@angular/core';
|
||||||
|
import { provideRouter } from '@angular/router';
|
||||||
|
import { appRoutes } from './app.routes';
|
||||||
|
|
||||||
|
export const appConfig: ApplicationConfig = {
|
||||||
|
providers: [provideBrowserGlobalErrorListeners(), provideRouter(appRoutes)],
|
||||||
|
};
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<app-nx-welcome></app-nx-welcome>
|
||||||
|
<router-outlet></router-outlet>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { Route } from '@angular/router';
|
||||||
|
|
||||||
|
export const appRoutes: Route[] = [];
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { App } from './app';
|
||||||
|
import { NxWelcome } from './nx-welcome';
|
||||||
|
|
||||||
|
describe('App', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [App, NxWelcome],
|
||||||
|
}).compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render title', async () => {
|
||||||
|
const fixture = TestBed.createComponent(App);
|
||||||
|
await fixture.whenStable();
|
||||||
|
const compiled = fixture.nativeElement as HTMLElement;
|
||||||
|
expect(compiled.querySelector('h1')?.textContent).toContain(
|
||||||
|
'Welcome frontend',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { NxWelcome } from './nx-welcome';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
imports: [NxWelcome, RouterModule],
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.html',
|
||||||
|
styleUrl: './app.scss',
|
||||||
|
})
|
||||||
|
export class App {
|
||||||
|
protected title = 'frontend';
|
||||||
|
}
|
||||||
@@ -0,0 +1,951 @@
|
|||||||
|
import { Component, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-nx-welcome',
|
||||||
|
imports: [CommonModule],
|
||||||
|
template: `
|
||||||
|
<!--
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
This is a starter component and can be deleted.
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
Delete this file and get started with your project!
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
-->
|
||||||
|
<style>
|
||||||
|
html {
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
font-family:
|
||||||
|
ui-sans-serif,
|
||||||
|
system-ui,
|
||||||
|
-apple-system,
|
||||||
|
BlinkMacSystemFont,
|
||||||
|
'Segoe UI',
|
||||||
|
Roboto,
|
||||||
|
'Helvetica Neue',
|
||||||
|
Arial,
|
||||||
|
'Noto Sans',
|
||||||
|
sans-serif,
|
||||||
|
'Apple Color Emoji',
|
||||||
|
'Segoe UI Emoji',
|
||||||
|
'Segoe UI Symbol',
|
||||||
|
'Noto Color Emoji';
|
||||||
|
line-height: 1.5;
|
||||||
|
tab-size: 4;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
p,
|
||||||
|
pre {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
*,
|
||||||
|
::before,
|
||||||
|
::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-width: 0;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: currentColor;
|
||||||
|
}
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
font-size: inherit;
|
||||||
|
font-weight: inherit;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: inherit;
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
font-family:
|
||||||
|
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
||||||
|
'Liberation Mono', 'Courier New', monospace;
|
||||||
|
}
|
||||||
|
svg {
|
||||||
|
display: block;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
svg {
|
||||||
|
shape-rendering: auto;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
background-color: rgba(55, 65, 81, 1);
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
color: rgba(229, 231, 235, 1);
|
||||||
|
font-family:
|
||||||
|
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
||||||
|
'Liberation Mono', 'Courier New', monospace;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
}
|
||||||
|
.shadow {
|
||||||
|
box-shadow:
|
||||||
|
0 0 #0000,
|
||||||
|
0 0 #0000,
|
||||||
|
0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
||||||
|
0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
.rounded {
|
||||||
|
border-radius: 1.5rem;
|
||||||
|
}
|
||||||
|
.wrapper {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
max-width: 768px;
|
||||||
|
padding-bottom: 3rem;
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
color: rgba(55, 65, 81, 1);
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
#welcome {
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
}
|
||||||
|
#welcome h1 {
|
||||||
|
font-size: 3rem;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: -0.025em;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
#welcome span {
|
||||||
|
display: block;
|
||||||
|
font-size: 1.875rem;
|
||||||
|
font-weight: 300;
|
||||||
|
line-height: 2.25rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
#hero {
|
||||||
|
align-items: center;
|
||||||
|
background-color: hsla(214, 62%, 21%, 1);
|
||||||
|
border: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: rgba(55, 65, 81, 1);
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
}
|
||||||
|
#hero .text-container {
|
||||||
|
color: rgba(255, 255, 255, 1);
|
||||||
|
padding: 3rem 2rem;
|
||||||
|
}
|
||||||
|
#hero .text-container h2 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: 2rem;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
#hero .text-container h2 svg {
|
||||||
|
color: hsla(162, 47%, 50%, 1);
|
||||||
|
height: 2rem;
|
||||||
|
left: -0.25rem;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 2rem;
|
||||||
|
}
|
||||||
|
#hero .text-container h2 span {
|
||||||
|
margin-left: 2.5rem;
|
||||||
|
}
|
||||||
|
#hero .text-container a {
|
||||||
|
background-color: rgba(255, 255, 255, 1);
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
color: rgba(55, 65, 81, 1);
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
text-decoration: inherit;
|
||||||
|
}
|
||||||
|
#hero .logo-container {
|
||||||
|
display: none;
|
||||||
|
justify-content: center;
|
||||||
|
padding-left: 2rem;
|
||||||
|
padding-right: 2rem;
|
||||||
|
}
|
||||||
|
#hero .logo-container svg {
|
||||||
|
color: rgba(255, 255, 255, 1);
|
||||||
|
width: 66.666667%;
|
||||||
|
}
|
||||||
|
#middle-content {
|
||||||
|
align-items: flex-start;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
}
|
||||||
|
#middle-content #middle-left-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
#learning-materials {
|
||||||
|
padding: 2.5rem 2rem;
|
||||||
|
}
|
||||||
|
#learning-materials h2 {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
letter-spacing: -0.025em;
|
||||||
|
line-height: 1.75rem;
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
.list-item-link {
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
display: flex;
|
||||||
|
margin-top: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
transition-property:
|
||||||
|
background-color,
|
||||||
|
border-color,
|
||||||
|
color,
|
||||||
|
fill,
|
||||||
|
stroke,
|
||||||
|
opacity,
|
||||||
|
box-shadow,
|
||||||
|
transform,
|
||||||
|
filter,
|
||||||
|
backdrop-filter,
|
||||||
|
-webkit-backdrop-filter;
|
||||||
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
transition-duration: 150ms;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.list-item-link svg:first-child {
|
||||||
|
margin-right: 1rem;
|
||||||
|
height: 1.5rem;
|
||||||
|
transition-property:
|
||||||
|
background-color,
|
||||||
|
border-color,
|
||||||
|
color,
|
||||||
|
fill,
|
||||||
|
stroke,
|
||||||
|
opacity,
|
||||||
|
box-shadow,
|
||||||
|
transform,
|
||||||
|
filter,
|
||||||
|
backdrop-filter,
|
||||||
|
-webkit-backdrop-filter;
|
||||||
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
transition-duration: 150ms;
|
||||||
|
width: 1.5rem;
|
||||||
|
}
|
||||||
|
.list-item-link > span {
|
||||||
|
flex-grow: 1;
|
||||||
|
font-weight: 400;
|
||||||
|
transition-property:
|
||||||
|
background-color,
|
||||||
|
border-color,
|
||||||
|
color,
|
||||||
|
fill,
|
||||||
|
stroke,
|
||||||
|
opacity,
|
||||||
|
box-shadow,
|
||||||
|
transform,
|
||||||
|
filter,
|
||||||
|
backdrop-filter,
|
||||||
|
-webkit-backdrop-filter;
|
||||||
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
.list-item-link > span > span {
|
||||||
|
color: rgba(107, 114, 128, 1);
|
||||||
|
display: block;
|
||||||
|
flex-grow: 1;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 300;
|
||||||
|
line-height: 1rem;
|
||||||
|
transition-property:
|
||||||
|
background-color,
|
||||||
|
border-color,
|
||||||
|
color,
|
||||||
|
fill,
|
||||||
|
stroke,
|
||||||
|
opacity,
|
||||||
|
box-shadow,
|
||||||
|
transform,
|
||||||
|
filter,
|
||||||
|
backdrop-filter,
|
||||||
|
-webkit-backdrop-filter;
|
||||||
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
.list-item-link svg:last-child {
|
||||||
|
height: 1rem;
|
||||||
|
transition-property: all;
|
||||||
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
transition-duration: 150ms;
|
||||||
|
width: 1rem;
|
||||||
|
}
|
||||||
|
.list-item-link:hover {
|
||||||
|
color: rgba(255, 255, 255, 1);
|
||||||
|
background-color: hsla(162, 55%, 33%, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-item-link:hover > span > span {
|
||||||
|
color: rgba(243, 244, 246, 1);
|
||||||
|
}
|
||||||
|
.list-item-link:hover svg:last-child {
|
||||||
|
transform: translateX(0.25rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-pill {
|
||||||
|
padding: 1.5rem 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
transition-duration: 300ms;
|
||||||
|
transition-property:
|
||||||
|
background-color,
|
||||||
|
border-color,
|
||||||
|
color,
|
||||||
|
fill,
|
||||||
|
stroke,
|
||||||
|
opacity,
|
||||||
|
box-shadow,
|
||||||
|
transform,
|
||||||
|
filter,
|
||||||
|
backdrop-filter,
|
||||||
|
-webkit-backdrop-filter;
|
||||||
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.button-pill svg {
|
||||||
|
transition-property:
|
||||||
|
background-color,
|
||||||
|
border-color,
|
||||||
|
color,
|
||||||
|
fill,
|
||||||
|
stroke,
|
||||||
|
opacity,
|
||||||
|
box-shadow,
|
||||||
|
transform,
|
||||||
|
filter,
|
||||||
|
backdrop-filter,
|
||||||
|
-webkit-backdrop-filter;
|
||||||
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
transition-duration: 150ms;
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 3rem;
|
||||||
|
}
|
||||||
|
.button-pill > span {
|
||||||
|
letter-spacing: -0.025em;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 1.125rem;
|
||||||
|
line-height: 1.75rem;
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
.button-pill span span {
|
||||||
|
display: block;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 300;
|
||||||
|
line-height: 1.25rem;
|
||||||
|
}
|
||||||
|
.button-pill:hover svg,
|
||||||
|
.button-pill:hover {
|
||||||
|
color: rgba(255, 255, 255, 1) !important;
|
||||||
|
}
|
||||||
|
.nx-console:hover {
|
||||||
|
background-color: rgba(0, 122, 204, 1);
|
||||||
|
}
|
||||||
|
.nx-console svg {
|
||||||
|
color: rgba(0, 122, 204, 1);
|
||||||
|
}
|
||||||
|
.nx-console-jetbrains {
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
.nx-console-jetbrains:hover {
|
||||||
|
background-color: rgba(255, 49, 140, 1);
|
||||||
|
}
|
||||||
|
.nx-console-jetbrains svg {
|
||||||
|
color: rgba(255, 49, 140, 1);
|
||||||
|
}
|
||||||
|
#nx-repo:hover {
|
||||||
|
background-color: rgba(24, 23, 23, 1);
|
||||||
|
}
|
||||||
|
#nx-repo svg {
|
||||||
|
color: rgba(24, 23, 23, 1);
|
||||||
|
}
|
||||||
|
#nx-cloud {
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
margin-top: 2rem;
|
||||||
|
padding: 2.5rem 2rem;
|
||||||
|
}
|
||||||
|
#nx-cloud > div {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
#nx-cloud > div svg {
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 3rem;
|
||||||
|
}
|
||||||
|
#nx-cloud > div h2 {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
font-weight: 400;
|
||||||
|
letter-spacing: -0.025em;
|
||||||
|
line-height: 1.75rem;
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
#nx-cloud > div h2 span {
|
||||||
|
display: block;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 300;
|
||||||
|
line-height: 1.25rem;
|
||||||
|
}
|
||||||
|
#nx-cloud p {
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
#nx-cloud pre {
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
#nx-cloud a {
|
||||||
|
color: rgba(107, 114, 128, 1);
|
||||||
|
display: block;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.25rem;
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
#nx-cloud a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
#commands {
|
||||||
|
padding: 2.5rem 2rem;
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
}
|
||||||
|
#commands h2 {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: 400;
|
||||||
|
letter-spacing: -0.025em;
|
||||||
|
line-height: 1.75rem;
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
#commands p {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 300;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
details {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
margin-top: 1rem;
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
details pre > span {
|
||||||
|
color: rgba(181, 181, 181, 1);
|
||||||
|
}
|
||||||
|
summary {
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
font-weight: 400;
|
||||||
|
padding: 0.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition-property:
|
||||||
|
background-color,
|
||||||
|
border-color,
|
||||||
|
color,
|
||||||
|
fill,
|
||||||
|
stroke,
|
||||||
|
opacity,
|
||||||
|
box-shadow,
|
||||||
|
transform,
|
||||||
|
filter,
|
||||||
|
backdrop-filter,
|
||||||
|
-webkit-backdrop-filter;
|
||||||
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
transition-duration: 150ms;
|
||||||
|
}
|
||||||
|
summary:hover {
|
||||||
|
background-color: rgba(243, 244, 246, 1);
|
||||||
|
}
|
||||||
|
summary svg {
|
||||||
|
height: 1.5rem;
|
||||||
|
margin-right: 1rem;
|
||||||
|
width: 1.5rem;
|
||||||
|
}
|
||||||
|
#love {
|
||||||
|
color: rgba(107, 114, 128, 1);
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.25rem;
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
opacity: 0.6;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
#love svg {
|
||||||
|
color: rgba(252, 165, 165, 1);
|
||||||
|
width: 1.25rem;
|
||||||
|
height: 1.25rem;
|
||||||
|
display: inline;
|
||||||
|
margin-top: -0.25rem;
|
||||||
|
}
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
#hero {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
#hero .logo-container {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
#middle-content {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
gap: 4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class="wrapper">
|
||||||
|
<div class="container">
|
||||||
|
<!-- WELCOME -->
|
||||||
|
<div id="welcome">
|
||||||
|
<h1>
|
||||||
|
<span> Hello there, </span>
|
||||||
|
Welcome frontend 👋
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<!-- HERO -->
|
||||||
|
<div id="hero" class="rounded">
|
||||||
|
<div class="text-container">
|
||||||
|
<h2>
|
||||||
|
<svg
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>You're up and running</span>
|
||||||
|
</h2>
|
||||||
|
<a href="#commands"> What's next? </a>
|
||||||
|
</div>
|
||||||
|
<div class="logo-container">
|
||||||
|
<svg
|
||||||
|
fill="currentColor"
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M11.987 14.138l-3.132 4.923-5.193-8.427-.012 8.822H0V4.544h3.691l5.247 8.833.005-3.998 3.044 4.759zm.601-5.761c.024-.048 0-3.784.008-3.833h-3.65c.002.059-.005 3.776-.003 3.833h3.645zm5.634 4.134a2.061 2.061 0 0 0-1.969 1.336 1.963 1.963 0 0 1 2.343-.739c.396.161.917.422 1.33.283a2.1 2.1 0 0 0-1.704-.88zm3.39 1.061c-.375-.13-.8-.277-1.109-.681-.06-.08-.116-.17-.176-.265a2.143 2.143 0 0 0-.533-.642c-.294-.216-.68-.322-1.18-.322a2.482 2.482 0 0 0-2.294 1.536 2.325 2.325 0 0 1 4.002.388.75.75 0 0 0 .836.334c.493-.105.46.36 1.203.518v-.133c-.003-.446-.246-.55-.75-.733zm2.024 1.266a.723.723 0 0 0 .347-.638c-.01-2.957-2.41-5.487-5.37-5.487a5.364 5.364 0 0 0-4.487 2.418c-.01-.026-1.522-2.39-1.538-2.418H8.943l3.463 5.423-3.379 5.32h3.54l1.54-2.366 1.568 2.366h3.541l-3.21-5.052a.7.7 0 0 1-.084-.32 2.69 2.69 0 0 1 2.69-2.691h.001c1.488 0 1.736.89 2.057 1.308.634.826 1.9.464 1.9 1.541a.707.707 0 0 0 1.066.596zm.35.133c-.173.372-.56.338-.755.639-.176.271.114.412.114.412s.337.156.538-.311c.104-.231.14-.488.103-.74z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- MIDDLE CONTENT -->
|
||||||
|
<div id="middle-content">
|
||||||
|
<div id="middle-left-content">
|
||||||
|
<div id="learning-materials" class="rounded shadow">
|
||||||
|
<h2>Learning materials</h2>
|
||||||
|
<a
|
||||||
|
href="https://nx.dev/getting-started/intro?utm_source=nx-project"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
class="list-item-link"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>
|
||||||
|
Documentation
|
||||||
|
<span> Everything is in there </span>
|
||||||
|
</span>
|
||||||
|
<svg
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M9 5l7 7-7 7"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="https://nx.dev/blog?utm_source=nx-project"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
class="list-item-link"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m2 13a2 2 0 01-2-2V7m2 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>
|
||||||
|
Blog
|
||||||
|
<span> Changelog, features & events </span>
|
||||||
|
</span>
|
||||||
|
<svg
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M9 5l7 7-7 7"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="https://www.youtube.com/@NxDevtools/videos?utm_source=nx-project&sub_confirmation=1"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
class="list-item-link"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<title>YouTube</title>
|
||||||
|
<path
|
||||||
|
d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>
|
||||||
|
YouTube channel
|
||||||
|
<span> Nx Show, talks & tutorials </span>
|
||||||
|
</span>
|
||||||
|
<svg
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M9 5l7 7-7 7"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="https://nx.dev/getting-started/tutorials/angular-standalone-tutorial?utm_source=nx-project"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
class="list-item-link"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M15 15l-2 5L9 9l11 4-5 2zm0 0l5 5M7.188 2.239l.777 2.897M5.136 7.965l-2.898-.777M13.95 4.05l-2.122 2.122m-5.657 5.656l-2.12 2.122"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>
|
||||||
|
Interactive tutorials
|
||||||
|
<span> Create an app, step-by-step </span>
|
||||||
|
</span>
|
||||||
|
<svg
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M9 5l7 7-7 7"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<a
|
||||||
|
id="nx-repo"
|
||||||
|
class="button-pill rounded shadow"
|
||||||
|
href="https://github.com/nrwl/nx?utm_source=nx-project"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
fill="currentColor"
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>
|
||||||
|
Nx is open source
|
||||||
|
<span> Love Nx? Give us a star! </span>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div id="other-links">
|
||||||
|
<a
|
||||||
|
class="button-pill rounded shadow nx-console"
|
||||||
|
href="https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console&utm_source=nx-project"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
fill="currentColor"
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<title>Visual Studio Code</title>
|
||||||
|
<path
|
||||||
|
d="M23.15 2.587L18.21.21a1.494 1.494 0 0 0-1.705.29l-9.46 8.63-4.12-3.128a.999.999 0 0 0-1.276.057L.327 7.261A1 1 0 0 0 .326 8.74L3.899 12 .326 15.26a1 1 0 0 0 .001 1.479L1.65 17.94a.999.999 0 0 0 1.276.057l4.12-3.128 9.46 8.63a1.492 1.492 0 0 0 1.704.29l4.942-2.377A1.5 1.5 0 0 0 24 20.06V3.939a1.5 1.5 0 0 0-.85-1.352zm-5.146 14.861L10.826 12l7.178-5.448v10.896z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>
|
||||||
|
Install Nx Console for VSCode
|
||||||
|
<span>The official VSCode extension for Nx.</span>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
class="button-pill rounded shadow nx-console-jetbrains"
|
||||||
|
href="https://plugins.jetbrains.com/plugin/21060-nx-console"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
height="48"
|
||||||
|
width="48"
|
||||||
|
viewBox="20 20 60 60"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path d="m22.5 22.5h60v60h-60z" />
|
||||||
|
<g fill="#fff">
|
||||||
|
<path d="m29.03 71.25h22.5v3.75h-22.5z" />
|
||||||
|
<path
|
||||||
|
d="m28.09 38 1.67-1.58a1.88 1.88 0 0 0 1.47.87c.64 0 1.06-.44 1.06-1.31v-5.98h2.58v6a3.48 3.48 0 0 1 -.87 2.6 3.56 3.56 0 0 1 -2.57.95 3.84 3.84 0 0 1 -3.34-1.55z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m36 30h7.53v2.19h-5v1.44h4.49v2h-4.42v1.49h5v2.21h-7.6z"
|
||||||
|
/>
|
||||||
|
<path d="m47.23 32.29h-2.8v-2.29h8.21v2.27h-2.81v7.1h-2.6z" />
|
||||||
|
<path
|
||||||
|
d="m29.13 43.08h4.42a3.53 3.53 0 0 1 2.55.83 2.09 2.09 0 0 1 .6 1.53 2.16 2.16 0 0 1 -1.44 2.09 2.27 2.27 0 0 1 1.86 2.29c0 1.61-1.31 2.59-3.55 2.59h-4.44zm5 2.89c0-.52-.42-.8-1.18-.8h-1.29v1.64h1.24c.79 0 1.25-.26 1.25-.81zm-.9 2.66h-1.57v1.73h1.62c.8 0 1.24-.31 1.24-.86 0-.5-.4-.87-1.27-.87z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m38 43.08h4.1a4.19 4.19 0 0 1 3 1 2.93 2.93 0 0 1 .9 2.19 3 3 0 0 1 -1.93 2.89l2.24 3.27h-3l-1.88-2.84h-.87v2.84h-2.56zm4 4.5c.87 0 1.39-.43 1.39-1.11 0-.75-.54-1.12-1.4-1.12h-1.44v2.26z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m49.59 43h2.5l4 9.44h-2.79l-.67-1.69h-3.63l-.67 1.69h-2.71zm2.27 5.73-1-2.65-1.06 2.65z"
|
||||||
|
/>
|
||||||
|
<path d="m56.46 43.05h2.6v9.37h-2.6z" />
|
||||||
|
<path
|
||||||
|
d="m60.06 43.05h2.42l3.37 5v-5h2.57v9.37h-2.26l-3.53-5.14v5.14h-2.57z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m68.86 51 1.45-1.73a4.84 4.84 0 0 0 3 1.13c.71 0 1.08-.24 1.08-.65 0-.4-.31-.6-1.59-.91-2-.46-3.53-1-3.53-2.93 0-1.74 1.37-3 3.62-3a5.89 5.89 0 0 1 3.86 1.25l-1.26 1.84a4.63 4.63 0 0 0 -2.62-.92c-.63 0-.94.25-.94.6 0 .42.32.61 1.63.91 2.14.46 3.44 1.16 3.44 2.91 0 1.91-1.51 3-3.79 3a6.58 6.58 0 0 1 -4.35-1.5z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
<span>
|
||||||
|
Install Nx Console for JetBrains
|
||||||
|
<span
|
||||||
|
>Available for WebStorm, Intellij IDEA Ultimate and
|
||||||
|
more!</span
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<div id="nx-cloud" class="rounded shadow">
|
||||||
|
<div>
|
||||||
|
<svg
|
||||||
|
id="nx-cloud-logo"
|
||||||
|
role="img"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
stroke="currentColor"
|
||||||
|
fill="transparent"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-width="2"
|
||||||
|
d="M23 3.75V6.5c-3.036 0-5.5 2.464-5.5 5.5s-2.464 5.5-5.5 5.5-5.5 2.464-5.5 5.5H3.75C2.232 23 1 21.768 1 20.25V3.75C1 2.232 2.232 1 3.75 1h16.5C21.768 1 23 2.232 23 3.75Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
stroke-width="2"
|
||||||
|
d="M23 6v14.1667C23 21.7307 21.7307 23 20.1667 23H6c0-3.128 2.53867-5.6667 5.6667-5.6667 3.128 0 5.6666-2.5386 5.6666-5.6666C17.3333 8.53867 19.872 6 23 6Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<h2>
|
||||||
|
Nx Cloud
|
||||||
|
<span> Enable faster CI & better DX </span>
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
You can activate distributed tasks executions and caching by
|
||||||
|
running:
|
||||||
|
</p>
|
||||||
|
<pre>nx connect</pre>
|
||||||
|
<a
|
||||||
|
href="https://nx.dev/nx-cloud?utm_source=nx-project"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
What is Nx Cloud?
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- COMMANDS -->
|
||||||
|
<div id="commands" class="rounded shadow">
|
||||||
|
<h2>Next steps</h2>
|
||||||
|
<p>Here are some things you can do with Nx:</p>
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<svg
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
Build, test and lint your app
|
||||||
|
</summary>
|
||||||
|
<pre><span># Build</span>
|
||||||
|
nx build
|
||||||
|
<span># Test</span>
|
||||||
|
nx test
|
||||||
|
<span># Lint</span>
|
||||||
|
nx lint
|
||||||
|
<span># Run them together!</span>
|
||||||
|
nx run-many -t build test lint</pre>
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<svg
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="2"
|
||||||
|
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
View project details
|
||||||
|
</summary>
|
||||||
|
<pre>nx show project frontend</pre>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<svg
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
View interactive project graph
|
||||||
|
</summary>
|
||||||
|
<pre>nx graph</pre>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<svg
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
Add UI library
|
||||||
|
</summary>
|
||||||
|
<pre><span># Generate UI lib</span>
|
||||||
|
nx g @nx/angular:lib ui
|
||||||
|
<span># Add a component</span>
|
||||||
|
nx g @nx/angular:component ui/src/lib/button</pre>
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
|
<p id="love">
|
||||||
|
Carefully crafted with
|
||||||
|
<svg
|
||||||
|
fill="currentColor"
|
||||||
|
stroke="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
styles: [],
|
||||||
|
encapsulation: ViewEncapsulation.None,
|
||||||
|
})
|
||||||
|
export class NxWelcome {}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>frontend</title>
|
||||||
|
<base href="/" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<app-root></app-root>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { bootstrapApplication } from '@angular/platform-browser';
|
||||||
|
import { appConfig } from './app/app.config';
|
||||||
|
import { App } from './app/app';
|
||||||
|
|
||||||
|
bootstrapApplication(App, appConfig).catch((err) => console.error(err));
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/* You can add global styles to this file, and also import other style files */
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../dist/out-tsc",
|
||||||
|
"types": []
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts"],
|
||||||
|
"exclude": ["src/**/*.spec.ts", "src/**/*.test.ts"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"strict": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"noPropertyAccessFromIndexSignature": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"target": "es2022",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"emitDecoratorMetadata": false,
|
||||||
|
"module": "preserve"
|
||||||
|
},
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"enableI18nLegacyMessageIdFormat": false,
|
||||||
|
"strictInjectionParameters": true,
|
||||||
|
"strictInputAccessModifiers": true,
|
||||||
|
"strictTemplates": true
|
||||||
|
},
|
||||||
|
"files": [],
|
||||||
|
"include": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.app.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import nhcarrigan from '@nhcarrigan/eslint-config';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
...nhcarrigan,
|
||||||
|
{
|
||||||
|
ignores: ['**/dist', '**/out-tsc', 'node_modules'],
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import type { Config } from 'jest';
|
||||||
|
import { getJestProjectsAsync } from '@nx/jest';
|
||||||
|
|
||||||
|
export default async (): Promise<Config> => ({
|
||||||
|
projects: await getJestProjectsAsync(),
|
||||||
|
});
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
const nxPreset = require('@nx/jest/preset').default;
|
||||||
|
|
||||||
|
module.exports = { ...nxPreset };
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"$schema": "./node_modules/nx/schemas/nx-schema.json",
|
||||||
|
"namedInputs": {
|
||||||
|
"default": ["{projectRoot}/**/*", "sharedGlobals"],
|
||||||
|
"production": [
|
||||||
|
"default",
|
||||||
|
"!{projectRoot}/.eslintrc.json",
|
||||||
|
"!{projectRoot}/eslint.config.mjs",
|
||||||
|
"!{projectRoot}/cypress/**/*",
|
||||||
|
"!{projectRoot}/**/*.cy.[jt]s?(x)",
|
||||||
|
"!{projectRoot}/cypress.config.[jt]s",
|
||||||
|
"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
|
||||||
|
"!{projectRoot}/tsconfig.spec.json",
|
||||||
|
"!{projectRoot}/jest.config.[jt]s",
|
||||||
|
"!{projectRoot}/src/test-setup.[jt]s",
|
||||||
|
"!{projectRoot}/test-setup.[jt]s"
|
||||||
|
],
|
||||||
|
"sharedGlobals": []
|
||||||
|
},
|
||||||
|
"targetDefaults": {
|
||||||
|
"@angular-devkit/build-angular:browser": {
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": ["^build"],
|
||||||
|
"inputs": ["production", "^production"]
|
||||||
|
},
|
||||||
|
"@nx/eslint:lint": {
|
||||||
|
"cache": true,
|
||||||
|
"inputs": [
|
||||||
|
"default",
|
||||||
|
"{workspaceRoot}/.eslintrc.json",
|
||||||
|
"{workspaceRoot}/.eslintignore",
|
||||||
|
"{workspaceRoot}/eslint.config.mjs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@nx/esbuild:esbuild": {
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": ["^build"],
|
||||||
|
"inputs": ["production", "^production"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"plugin": "@nx/cypress/plugin",
|
||||||
|
"options": {
|
||||||
|
"targetName": "e2e",
|
||||||
|
"openTargetName": "open-cypress",
|
||||||
|
"componentTestingTargetName": "component-test",
|
||||||
|
"ciTargetName": "e2e-ci"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"plugin": "@nx/eslint/plugin",
|
||||||
|
"options": {
|
||||||
|
"targetName": "lint"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"plugin": "@nx/jest/plugin",
|
||||||
|
"options": {
|
||||||
|
"targetName": "test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"generators": {
|
||||||
|
"@nx/angular:application": {
|
||||||
|
"e2eTestRunner": "cypress",
|
||||||
|
"linter": "eslint",
|
||||||
|
"style": "scss",
|
||||||
|
"unitTestRunner": "vitest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
{
|
||||||
|
"name": "@library/source",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {},
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@angular/common": "~21.1.0",
|
||||||
|
"@angular/compiler": "~21.1.0",
|
||||||
|
"@angular/core": "~21.1.0",
|
||||||
|
"@angular/forms": "~21.1.0",
|
||||||
|
"@angular/platform-browser": "~21.1.0",
|
||||||
|
"@angular/router": "~21.1.0",
|
||||||
|
"@fastify/autoload": "~6.0.3",
|
||||||
|
"@fastify/sensible": "~6.0.2",
|
||||||
|
"@prisma/client": "^7.3.0",
|
||||||
|
"fastify": "~5.2.1",
|
||||||
|
"fastify-plugin": "~5.0.1",
|
||||||
|
"rxjs": "~7.8.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@angular-devkit/build-angular": "~21.1.0",
|
||||||
|
"@angular-devkit/core": "~21.1.0",
|
||||||
|
"@angular-devkit/schematics": "~21.1.0",
|
||||||
|
"@angular/cli": "~21.1.0",
|
||||||
|
"@angular/compiler-cli": "~21.1.0",
|
||||||
|
"@angular/language-service": "~21.1.0",
|
||||||
|
"@eslint/js": "^9.8.0",
|
||||||
|
"@nhcarrigan/eslint-config": "^5.2.0",
|
||||||
|
"@nx/angular": "22.4.4",
|
||||||
|
"@nx/cypress": "22.4.4",
|
||||||
|
"@nx/esbuild": "22.4.4",
|
||||||
|
"@nx/eslint": "22.4.4",
|
||||||
|
"@nx/eslint-plugin": "22.4.4",
|
||||||
|
"@nx/jest": "22.4.4",
|
||||||
|
"@nx/js": "22.4.4",
|
||||||
|
"@nx/node": "^22.4.4",
|
||||||
|
"@nx/web": "22.4.4",
|
||||||
|
"@nx/workspace": "22.4.4",
|
||||||
|
"@schematics/angular": "~21.1.0",
|
||||||
|
"@swc-node/register": "~1.9.1",
|
||||||
|
"@swc/core": "~1.5.7",
|
||||||
|
"@swc/helpers": "~0.5.11",
|
||||||
|
"@types/jest": "^30.0.0",
|
||||||
|
"@types/node": "20.19.9",
|
||||||
|
"@typescript-eslint/utils": "^8.40.0",
|
||||||
|
"angular-eslint": "^21.0.1",
|
||||||
|
"cypress": "^15.8.0",
|
||||||
|
"esbuild": "^0.19.2",
|
||||||
|
"eslint": "^9.8.0",
|
||||||
|
"eslint-plugin-cypress": "^3.5.0",
|
||||||
|
"jest": "^30.0.2",
|
||||||
|
"jest-environment-node": "^30.0.2",
|
||||||
|
"jest-util": "^30.0.2",
|
||||||
|
"nx": "22.4.4",
|
||||||
|
"prisma": "^7.3.0",
|
||||||
|
"ts-jest": "^29.4.0",
|
||||||
|
"ts-node": "10.9.1",
|
||||||
|
"tslib": "^2.3.0",
|
||||||
|
"typescript": "~5.9.2",
|
||||||
|
"typescript-eslint": "^8.40.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+20641
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
|||||||
|
autoInstallPeers: true
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# MongoDB connection string from 1Password
|
||||||
|
DATABASE_URL="op://NHCarrigan/MongoDB Atlas Library/connection-string"
|
||||||
|
|
||||||
|
# Discord OAuth secrets
|
||||||
|
DISCORD_CLIENT_ID="op://NHCarrigan/Library OAuth Discord/client-id"
|
||||||
|
DISCORD_CLIENT_SECRET="op://NHCarrigan/Library OAuth Discord/client-secret"
|
||||||
|
|
||||||
|
# JWT secret for session management
|
||||||
|
JWT_SECRET="op://NHCarrigan/Library App/jwt-secret"
|
||||||
|
|
||||||
|
# Application URLs
|
||||||
|
FRONTEND_URL="http://localhost:4200"
|
||||||
|
API_URL="http://localhost:3000"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# shared-types
|
||||||
|
|
||||||
|
This library was generated with [Nx](https://nx.dev).
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import nhcarrigan from '@nhcarrigan/eslint-config';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
...nhcarrigan,
|
||||||
|
{
|
||||||
|
ignores: ['**/dist', '**/out-tsc', 'node_modules'],
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name": "shared-types",
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"sourceRoot": "shared-types/src",
|
||||||
|
"projectType": "library",
|
||||||
|
"tags": [],
|
||||||
|
"// targets": "to see all targets run: nx show project shared-types --web",
|
||||||
|
"targets": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export * from './lib/game.types';
|
||||||
|
export * from './lib/book.types';
|
||||||
|
export * from './lib/music.types';
|
||||||
|
export * from './lib/auth.types';
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export interface User {
|
||||||
|
id: string;
|
||||||
|
email: string;
|
||||||
|
username: string;
|
||||||
|
avatarUrl?: string;
|
||||||
|
discordId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface JwtPayload {
|
||||||
|
sub: string; // user id
|
||||||
|
email: string;
|
||||||
|
username: string;
|
||||||
|
iat?: number;
|
||||||
|
exp?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AuthResponse {
|
||||||
|
accessToken: string;
|
||||||
|
user: User;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
export enum BookStatus {
|
||||||
|
READING = 'READING',
|
||||||
|
FINISHED = 'FINISHED',
|
||||||
|
TO_READ = 'TO_READ',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Book {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
author: string;
|
||||||
|
isbn?: string;
|
||||||
|
status: BookStatus;
|
||||||
|
dateAdded: Date;
|
||||||
|
dateFinished?: Date;
|
||||||
|
rating?: number;
|
||||||
|
notes?: string;
|
||||||
|
coverImage?: string;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CreateBookDto {
|
||||||
|
title: string;
|
||||||
|
author: string;
|
||||||
|
isbn?: string;
|
||||||
|
status: BookStatus;
|
||||||
|
rating?: number;
|
||||||
|
notes?: string;
|
||||||
|
coverImage?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateBookDto extends Partial<CreateBookDto> {
|
||||||
|
dateFinished?: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
export enum GameStatus {
|
||||||
|
PLAYING = 'PLAYING',
|
||||||
|
COMPLETED = 'COMPLETED',
|
||||||
|
BACKLOG = 'BACKLOG',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Game {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
platform?: string;
|
||||||
|
status: GameStatus;
|
||||||
|
dateAdded: Date;
|
||||||
|
dateCompleted?: Date;
|
||||||
|
rating?: number;
|
||||||
|
notes?: string;
|
||||||
|
coverImage?: string;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CreateGameDto {
|
||||||
|
title: string;
|
||||||
|
platform?: string;
|
||||||
|
status: GameStatus;
|
||||||
|
rating?: number;
|
||||||
|
notes?: string;
|
||||||
|
coverImage?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateGameDto extends Partial<CreateGameDto> {
|
||||||
|
dateCompleted?: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
export enum MusicType {
|
||||||
|
ALBUM = 'ALBUM',
|
||||||
|
SINGLE = 'SINGLE',
|
||||||
|
EP = 'EP',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum MusicStatus {
|
||||||
|
LISTENING = 'LISTENING',
|
||||||
|
COMPLETED = 'COMPLETED',
|
||||||
|
WANT_TO_LISTEN = 'WANT_TO_LISTEN',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Music {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
artist: string;
|
||||||
|
type: MusicType;
|
||||||
|
status: MusicStatus;
|
||||||
|
dateAdded: Date;
|
||||||
|
dateCompleted?: Date;
|
||||||
|
rating?: number;
|
||||||
|
notes?: string;
|
||||||
|
coverArt?: string;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CreateMusicDto {
|
||||||
|
title: string;
|
||||||
|
artist: string;
|
||||||
|
type: MusicType;
|
||||||
|
status: MusicStatus;
|
||||||
|
rating?: number;
|
||||||
|
notes?: string;
|
||||||
|
coverArt?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateMusicDto extends Partial<CreateMusicDto> {
|
||||||
|
dateCompleted?: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"extends": "../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs",
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"strict": true,
|
||||||
|
"importHelpers": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noPropertyAccessFromIndexSignature": true
|
||||||
|
},
|
||||||
|
"files": [],
|
||||||
|
"include": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.lib.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../dist/out-tsc",
|
||||||
|
"declaration": true,
|
||||||
|
"types": ["node"]
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"compileOnSave": false,
|
||||||
|
"compilerOptions": {
|
||||||
|
"rootDir": ".",
|
||||||
|
"sourceMap": true,
|
||||||
|
"declaration": false,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"importHelpers": true,
|
||||||
|
"target": "es2015",
|
||||||
|
"module": "esnext",
|
||||||
|
"lib": ["es2020", "dom"],
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"skipDefaultLibCheck": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@library/shared-types": ["shared-types/src/index.ts"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"exclude": ["node_modules", "tmp"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user