From 572027ea01af28c91e312a55ce65bf3f093ef9f1 Mon Sep 17 00:00:00 2001 From: Willem van Heemstra Date: Mon, 24 Feb 2025 11:47:36 +0100 Subject: [PATCH] Initial commit --- .github/CODEOWNERS | 67 ++ .github/CODE_OF_CONDUCT.md | 79 ++ .github/CONTRIBUTING.md | 1 + .github/ISSUE_TEMPLATE/bug_report.md | 27 + .github/ISSUE_TEMPLATE/feature_request.md | 20 + .github/workflows/ci.yml | 27 + .github/workflows/deploy.yml | 145 +++ .github/workflows/documentation.yml | 36 + .github/workflows/readme.yml | 50 + .gitignore | 160 +++ .gitpod.yml | 4 + .readthedocs.yaml | 13 + .threagile/live-templates.txt | 265 +++++ .threagile/openapi.yaml | 321 ++++++ .threagile/schema.json | 1244 +++++++++++++++++++++ .vscode/extensions.json | 8 + 100/README.md | 1 + 200/README.md | 1 + 300/100/README.md | 15 + 300/200/README.md | 5 + 300/300/README.md | 501 +++++++++ 300/400/README.md | 59 + 300/500/README.md | 216 ++++ 300/README.md | 37 + 400/README.md | 1 + DNS.md | 2 + DOCUMENTATION.md | 3 + GLOSSARY.md | 3 + HATCH.md | 170 +++ HOSTS.md | 32 + IMAGES.md | 5 + LICENSE | 21 + NX.md | 23 + PODMAN.md | 120 ++ README.ar.md | 39 + README.de.md | 39 + README.es.md | 39 + README.fr.md | 39 + README.hi.md | 39 + README.md | 38 + README.nl.md | 39 + README.rst | 15 + README.zh-CN.md | 39 + README.zh-TW.md | 39 + REFERENCES.md | 5 + REQUIREMENTS.md | 13 + TELEMETRY.md | 13 + docs/Makefile | 20 + docs/make.bat | 35 + docs/requirements.txt | 2 + docs/source/api.rst | 7 + docs/source/conf.py | 35 + docs/source/index.rst | 22 + docs/source/usage.rst | 33 + nx.json | 78 ++ package.json | 24 + pyproject.toml | 8 + schemas/.schemastore | 1 + threagile.bat | 1 + threagile.sh | 3 + threagile.yaml | 3 + workspace.json | 10 + 62 files changed, 4360 insertions(+) create mode 100644 .github/CODEOWNERS create mode 100644 .github/CODE_OF_CONDUCT.md create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/deploy.yml create mode 100644 .github/workflows/documentation.yml create mode 100644 .github/workflows/readme.yml create mode 100644 .gitignore create mode 100644 .gitpod.yml create mode 100644 .readthedocs.yaml create mode 100644 .threagile/live-templates.txt create mode 100644 .threagile/openapi.yaml create mode 100644 .threagile/schema.json create mode 100644 .vscode/extensions.json create mode 100644 100/README.md create mode 100644 200/README.md create mode 100644 300/100/README.md create mode 100644 300/200/README.md create mode 100644 300/300/README.md create mode 100644 300/400/README.md create mode 100644 300/500/README.md create mode 100644 300/README.md create mode 100644 400/README.md create mode 100644 DNS.md create mode 100644 DOCUMENTATION.md create mode 100644 GLOSSARY.md create mode 100644 HATCH.md create mode 100644 HOSTS.md create mode 100644 IMAGES.md create mode 100644 LICENSE create mode 100644 NX.md create mode 100644 PODMAN.md create mode 100644 README.ar.md create mode 100644 README.de.md create mode 100644 README.es.md create mode 100644 README.fr.md create mode 100644 README.hi.md create mode 100644 README.md create mode 100644 README.nl.md create mode 100644 README.rst create mode 100644 README.zh-CN.md create mode 100644 README.zh-TW.md create mode 100644 REFERENCES.md create mode 100644 REQUIREMENTS.md create mode 100644 TELEMETRY.md create mode 100644 docs/Makefile create mode 100644 docs/make.bat create mode 100644 docs/requirements.txt create mode 100644 docs/source/api.rst create mode 100644 docs/source/conf.py create mode 100644 docs/source/index.rst create mode 100644 docs/source/usage.rst create mode 100644 nx.json create mode 100644 package.json create mode 100644 pyproject.toml create mode 100644 schemas/.schemastore create mode 100644 threagile.bat create mode 100644 threagile.sh create mode 100644 threagile.yaml create mode 100644 workspace.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..72a089b --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,67 @@ +# This is a comment. +# Each line is a file pattern followed by one or more owners. + +# These owners will be the default owners for everything in +# the repo. Unless a later match takes precedence, +# @vanHeemstraSystems/global-owners will be requested for +# review when someone opens a pull request. +* @vanHeemstraSystems/global-owners + +# Order is important; the last matching pattern takes the most +# precedence. When someone opens a pull request that only +# modifies JS files, only @vanHeemstraSystems/js-owners and not the global +# owner(s) will be requested for a review. +*.js @vanHeemstraSystems/js-owners #This is an inline comment. + +# You can also use email addresses if you prefer. They'll be +# used to look up users just like we do for commit author +# emails. +*.go docs@example.com + +# Teams can be specified as code owners as well. Teams should +# be identified in the format @org/team-name. Teams must have +# explicit write access to the repository. In this example, +# the vanHeemstraSystems team in the vanHeemstraSystems organization owns all .txt files. +*.txt @vanHeemstraSystems/vanHeemstraSystems + +# In this example, @vanHeemstraSystems/log-owners own any files in the build/logs +# directory at the root of the repository and any of its +# subdirectories. +/build/logs/ @vanHeemstraSystems/log-owners + +# The `docs/*` pattern will match files like +# `docs/getting-started.md` but not further nested files like +# `docs/build-app/troubleshooting.md`. +docs/* docs@vanheemstrasystems.com + +# In this example, @vanHeemstraSystems owns any file in an apps directory +# anywhere in your repository. +apps/ @vanHeemstraSystems + +# In this example, @vanHeemstraSystems/docs-owners owns any file in the `/docs` +# directory in the root of your repository and any of its +# subdirectories. +/docs/ @vanHeemstraSystems/docs-owners + +# In this example, any change inside the `/scripts` directory +# will require approval from @vanHeemstraSystems/docs-owners or @vanHeemstraSystems. +/scripts/ @vanHeemstraSystems/docs-owners @vanHeemstraSystems + +# In this example, @vanHeemstraSystems owns any file in a `/logs` directory such as +# `/build/logs`, `/scripts/logs`, and `/deeply/nested/logs`. Any changes +# in a `/logs` directory will require approval from @vanHeemstraSystems. +**/logs @vanHeemstraSystems + +# In this example, @vanHeemstraSystems owns any file in the `/apps` +# directory in the root of your repository except for the `/apps/github` +# subdirectory, as its owners are left empty. Without an owner, changes +# to `apps/github` can be made with the approval of any user who has +# write access to the repository. +/apps/ @vanHeemstraSystems +/apps/github + +# In this example, @vanHeemstraSystems owns any file in the `/apps` +# directory in the root of your repository except for the `/apps/github` +# subdirectory, as this subdirectory has its own owner @vanHeemstraSystems/docs-owners +/apps/ @vanHeemstraSystems +/apps/github @vanHeemstraSystems/docs-owners diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..8c6428b --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,79 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at [safety@vanheemstrasystems.com][email]. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available [here][version]. + +## Adoption + +This Code of Conduct was first adopted December 15th, 2021. + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ +[email]: mailto:wvanheemstra@icloud.com diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..c15a101 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1 @@ +all commit messages must follow [Semantic Commit Messages](https://gist.github.com/wvanheemstra/376206ed6fcadadbd451a1e277151cb9) or they will not trigger a release. diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..1c3f619 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,27 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: 'Bug' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..bbcbbe7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..712715c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,27 @@ +name: CI +on: + push: + branches: + - main + pull_request: + +jobs: + main: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + with: + node-version: 20 + cache: 'npm' + - run: npm cache clean --force + - run: npm ci + - run: npm install -g @nrwl/cli + - run: | + npm install --save-dev @swc-node/register @swc/core \ + @nx/webpack webpack-cli \ + @nx/eslint-plugin eslint-plugin-playwright \ + @playwright/test jest \ + @nx/jest @nx/react @nx/eslint @nx/playwright + - run: npx nx run-many -t build --verbose + - run: npx nx run-many -t test diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..c20ad00 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,145 @@ +name: Deploy +on: + push: + branches: + - main + workflow_dispatch: # Allows manual triggering + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + with: + node-version: 20 + + # Clean up existing workspace + - run: | + echo "Cleaning up workspace..." + rm -rf hatch-project + rm -rf apps + rm -f nx.json + rm -f package.json + rm -f package-lock.json + + # Create temporary directory for the new workspace + - run: | + echo "Creating temporary directory..." + mkdir -p /tmp/nx-workspace + cd /tmp/nx-workspace + + echo "Creating new Nx workspace..." + npx create-nx-workspace@latest . \ + --preset=react-monorepo \ + --appName=hatch_project \ + --style=css \ + --nxCloud=skip \ + --packageManager=npm \ + --no-interactive \ + --defaultBase=main + + echo "Workspace contents:" + ls -la + + echo "Copying workspace files back..." + cd $GITHUB_WORKSPACE + cp -r /tmp/nx-workspace/* . + cp -r /tmp/nx-workspace/.* . 2>/dev/null || true + + # Configure base URL for GitHub Pages + - run: | + echo "Configuring base URL..." + REPO_NAME=$(echo "$GITHUB_REPOSITORY" | cut -d'/' -f2) + echo "Base URL will be: /$REPO_NAME/" + + # Update vite.config.ts + cat > apps/hatch_project/vite.config.ts << EOF + /// + import { defineConfig } from 'vite'; + import react from '@vitejs/plugin-react'; + import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; + + export default defineConfig({ + root: __dirname, + base: '/$REPO_NAME/', + cacheDir: '../../node_modules/.vite/hatch_project', + + plugins: [react(), nxViteTsPaths()], + + build: { + outDir: '../../dist/apps/hatch_project', + emptyOutDir: true, + reportCompressedSize: true, + commonjsOptions: { transformMixedEsModules: true }, + }, + + test: { + globals: true, + cache: { + dir: '../../node_modules/.vitest', + }, + environment: 'jsdom', + include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + }, + }); + EOF + + # Build for production + - run: | + echo "Running build command..." + npx nx build hatch_project --configuration=production --verbose + + # Update HTML file with correct base URL + - run: | + echo "Updating base URL in index.html..." + REPO_NAME=$(echo "$GITHUB_REPOSITORY" | cut -d'/' -f2) + + # Use sed to update the base href and asset paths + sed -i "s| + As a hacker I want to disturb the functionality of the backend system in order to cause indirect + financial damage via unusable features. + CPU-Cycle Theft: > + As a hacker I want to steal CPU cycles in order to transform them into money via installed crypto currency miners. + Ransomware: > + As a hacker I want to encrypt the storage and file systems in order to demand ransom. + Identity Theft: > + As a hacker I want to steal identity data in order to reuse credentials and/or keys on other targets of the same company or outside. + PII Theft: > + As a hacker I want to steal PII (Personally Identifiable Information) data in order to blackmail the company and/or damage + their repudiation by publishing the stolen data. + + +security_requirements: + Input Validation: Strict input validation is required to reduce the overall attack surface. + EU-GDPR: Mandatory EU-GDPR + + +# Tags can be used for anything, it's just a tag. Also risk rules can act based on tags if you like. +tags_available: + + +data_assets: + +$END$ + + +technical_assets: + + +trust_boundaries: + + +shared_runtimes: + + +individual_risk_categories: + + +# NOTE: +# For risk tracking each risk-id needs to be defined (the string with the @ sign in it). These unique risk IDs +# are visible in the PDF report (the small grey string under each risk), the Excel (column "ID"), as well as the JSON responses. +# Some risk IDs have only one @ sign in them, while others multiple. The idea is to allow for unique but still speaking IDs. +# Therefore each risk instance creates its individual ID by taking all affected elements causing the risk to be within an @-delimited part. +# Using wildcards (the * sign) for parts delimited by @ signs allows to handle groups of certain risks at once. Best is to lookup the IDs +# to use in the created Excel file. Alternatively a model macro "seed-risk-tracking" is available that helps in initially +# seeding the risk tracking part here based on already identified and not yet handled risks. +risk_tracking: + + + + + +==================================================== +Live template for a data asset: +==================================================== + + $DataAssetName$: + id: $id$ + description: $END$ + usage: $usage$ + tags: + origin: + owner: + quantity: $quantity$ + confidentiality: $confidentiality$ + integrity: $integrity$ + availability: $availability$ + justification_cia_rating: + + + + + +==================================================== +Live template for a technical asset: +==================================================== + + $TechnicalAssetName$: + id: $id$ + description: $END$ + type: $type$ + usage: $usage$ + used_as_client_by_human: $used_as_client_by_human$ + out_of_scope: false + justification_out_of_scope: + size: $size$ + technology: $technology$ + tags: $tags$ + internet: $internet$ + machine: $machine$ + encryption: $encryption$ + owner: + confidentiality: $confidentiality$ + integrity: $integrity$ + availability: $availability$ + justification_cia_rating: + multi_tenant: $multi_tenant$ + redundant: $redundant$ + custom_developed_parts: $custom_developed_parts$ + data_assets_processed: # sequence of IDs to reference + data_assets_stored: # sequence of IDs to reference + data_formats_accepted: + communication_links: + + + + + +==================================================== +Live template for a communication link: +==================================================== + + $CommunicationLinkName$: + target: $target_id$ + description: $END$ + protocol: $protocol$ + authentication: $authentication$ + authorization: $authorization$ + tags: $tags$ + vpn: $vpn$ + ip_filtered: $ip_filtered$ + readonly: $readonly$ + usage: $usage$ + data_assets_sent: # sequence of IDs to reference + data_assets_received: # sequence of IDs to reference + + + + + +==================================================== +Live template for a trust boundary: +==================================================== + + $TrustBoundaryName$: + id: $id$ + description: $END$ + type: $type$ + tags: $tags$ + technical_assets_inside: # sequence of IDs to reference + trust_boundaries_nested: # sequence of IDs to reference + + + + + +==================================================== +Live template for a shared runtime: +==================================================== + + $SharedRuntimeName$: + id: $id$ + description: $END$ + tags: $tags$ + technical_assets_running: # sequence of IDs to reference + + + + + +==================================================== +Live template for an individual risk category: +==================================================== + + $IndividualRiskCategoryName$: + id: $id$ + description: $END$ + impact: + asvs: + cheat_sheet: + action: + mitigation: + check: + function: $function$ + stride: $stride$ + detection_logic: + risk_assessment: + false_positives: + model_failure_possible_reason: $model_failure_possible_reason$ + cwe: $cwe$ + risks_identified: + + + + + +==================================================== +Live template for an individual risk instance: +==================================================== + + $IndividualRiskInstanceName$: + severity: $severity$ + exploitation_likelihood: $exploitation_likelihood$ + exploitation_impact: $exploitation_impact$ + data_breach_probability: $data_breach_probability$ + data_breach_technical_assets: # list of technical asset IDs which might have data breach + $END$ + most_relevant_data_asset: $most_relevant_data_asset$ + most_relevant_technical_asset: $most_relevant_technical_asset$ + most_relevant_trust_boundary: $most_relevant_trust_boundary$ + most_relevant_shared_runtime: $most_relevant_shared_runtime$ + + + + + +==================================================== +Live template for a risk tracking: +==================================================== + + $RiskID$: # wildcards "*" between the @ characters are possible + status: $status$ + justification: $END$ + ticket: + date: + checked_by: diff --git a/.threagile/openapi.yaml b/.threagile/openapi.yaml new file mode 100644 index 0000000..1f288b9 --- /dev/null +++ b/.threagile/openapi.yaml @@ -0,0 +1,321 @@ +openapi: 3.0.3 + +info: + title: Threagile API + description: "Threagile API for Agile Threat Modeling: visit https://threagile.io for more information." + version: 1.0.0 + +servers: + - url: / + description: Threagile Server + +tags: + - name: "direct" + description: "Direct one-shot calls for on-the-fly analyzing and checking of models" + - name: "meta" + description: "Meta infos about types and version" + - name: "auth" + description: "Auth calls for crypto key and token management" + - name: "models" + description: "Persistent model creation and handling stuff" + +paths: + /meta/ping: + get: + tags: + - "meta" + summary: Simple health check ping + description: Used as health check in docker container as well + responses: + '200': + description: Simple pong response + content: + application/json: + schema: + type: object + properties: + message: + type: string + example: pong + /meta/version: + get: + tags: + - "meta" + summary: Version number + description: Version number + responses: + '200': + description: Version number + content: + application/json: + schema: + type: object + properties: + version: + type: string + example: 1.0.0 + build_timestamp: + type: string + example: 20200518160456 + /meta/types: + get: + tags: + - "meta" + summary: Listing of all enum type values + description: Listing of all enum type values + responses: + '200': + description: Listing of all enum type values (example here shows just one) + content: + application/json: + schema: + type: object + properties: + confidentiality: + type: array + items: + type: string + example: [public, internal, restricted, confidential, strictly-confidential] + /meta/stats: + get: + tags: + - "meta" + summary: Model statistics + description: Model statistics + responses: + '200': + description: Model statistics + content: + application/json: + schema: + type: object + properties: + key_count: + type: integer + example: 13 + model_count: + type: integer + example: 42 + success_count: + type: integer + example: 123 + error_count: + type: integer + example: 0 + /direct/stub: + get: + tags: + - "direct" + summary: Stub model file + description: Stub model file (as a starting point) + responses: + '200': + description: Stub model file + content: + application/x-yaml: + schema: + type: string + /direct/check: + post: + tags: + - "direct" + summary: Direct model check call + description: Direct model check call + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + responses: + '200': + description: Model ok response + content: + application/json: + schema: + type: object + properties: + message: + type: string + example: model is ok + '400': + description: Model not ok response + content: + application/json: + schema: + type: object + properties: + error: + type: string + example: "Missing referenced data asset target: some-stuff" + /direct/analyze: + post: + tags: + - "direct" + summary: Direct model analyze call + description: Direct model analyze call + parameters: + - in: query + name: dpi + required: false + example: 120 + schema: + type: integer + description: The DPI (resolution) to use for the diagram generation + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + responses: + '200': + description: Model analyzing result response (zipped) + content: + application/zip: + schema: + type: string + format: binary + '400': + description: Model not ok response + content: + application/json: + schema: + type: object + properties: + error: + type: string + example: "Missing referenced data asset target: some-stuff" + /auth/keys: + post: + tags: + - "auth" + summary: Create a new auth key + description: Create a new auth key + responses: + '201': + description: Key successfully created + content: + application/json: + schema: + type: object + properties: + key: + type: string + example: BtM1Q7V47d4B3TrVSw1133CIyL1NUpUM2tJ92vfZMMQ + '500': + description: Error + content: + application/json: + schema: + type: object + properties: + error: + type: string + example: unable to create key + delete: + tags: + - "auth" + summary: Delete an auth key + description: Delete an auth key + parameters: + - in: header + name: key + schema: + type: string + required: true + example: BtM1Q7V47d4B3TrVSw1133CIyL1NUpUM2tJ92vfZMMQ + responses: + '200': + description: Key successfully deleted + content: + application/json: + schema: + type: object + properties: + message: + type: string + example: key deleted + '404': + description: Error + content: + application/json: + schema: + type: object + properties: + error: + type: string + example: key not found + /auth/tokens: + post: + tags: + - "auth" + summary: Create a new (time limited) token from an auth key + description: Create a new (time limited) token from an auth key + parameters: + - in: header + name: key + schema: + type: string + required: true + example: BtM1Q7V47d4B3TrVSw1133CIyL1NUpUM2tJ92vfZMMQ + responses: + '201': + description: Token successfully created + content: + application/json: + schema: + type: object + properties: + token: + type: string + example: QrlcoMOtjy_h38T2N6JjrWpb4Kodg3Y7NnLN2yiDb69 + '500': + description: Error + content: + application/json: + schema: + type: object + properties: + error: + type: string + example: unable to create token + delete: + tags: + - "auth" + summary: Delete a token + description: Delete a token + parameters: + - in: header + name: token + schema: + type: string + required: true + example: QrlcoMOtjy_h38T2N6JjrWpb4Kodg3Y7NnLN2yiDb69 + responses: + '200': + description: Token successfully deleted + content: + application/json: + schema: + type: object + properties: + message: + type: string + example: token deleted + '404': + description: Error + content: + application/json: + schema: + type: object + properties: + error: + type: string + example: token not found diff --git a/.threagile/schema.json b/.threagile/schema.json new file mode 100644 index 0000000..a028d78 --- /dev/null +++ b/.threagile/schema.json @@ -0,0 +1,1244 @@ +{ + "$schema": "https://threagile.io/schema#", + "id": "https://threagile.io/schema.json", + "title": "Threagile", + "description": "Agile Threat Modeling", + "type": "object", + "properties": { + "threagile_version": { + "description": "Version of the Threagile toolkit", + "type": "string" + }, + "title": { + "description": "Title of the model", + "type": "string" + }, + "date": { + "description": "Date of the model", + "type": [ + "string", + "null" + ], + "format": "date" + }, + "author": { + "description": "Author of the model", + "type": "object", + "properties": { + "name": { + "description": "Author name", + "type": [ + "string", + "null" + ] + }, + "contact": { + "description": "Author contact info", + "type": [ + "string", + "null" + ] + }, + "homepage": { + "description": "Author homepage", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "name" + ] + }, + "contributors": { + "description": "Contributors to the model", + "type": [ + "array", + "null" + ], + "uniqueItems": true, + "items": { + "type": "object", + "properties": { + "name": { + "description": "Contributor name", + "type": [ + "string", + "null" + ] + }, + "contact": { + "description": "Contributor contact info", + "type": [ + "string", + "null" + ] + }, + "homepage": { + "description": "Contributor homepage", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "name" + ] + } + }, + "management_summary_comment": { + "description": "Individual management summary for the report", + "type": [ + "string", + "null" + ] + }, + "business_criticality": { + "description": "Business criticality of the target", + "type": "string", + "enum": [ + "archive", + "operational", + "important", + "critical", + "mission-critical" + ] + }, + "application_description": { + "description": "General description of the application, its purpose and functionality.", + "type": "object", + "properties": { + "description": { + "description": "Application description for the report", + "type": [ + "string", + "null" + ] + }, + "images": { + "description": "Application images for the report", + "type": [ + "array", + "null" + ], + "uniqueItems": true + } + } + }, + "business_overview": { + "description": "Individual business overview for the report", + "type": "object", + "properties": { + "description": { + "description": "Individual business overview for the report", + "type": [ + "string", + "null" + ] + }, + "images": { + "description": "Custom images for the report", + "type": [ + "array", + "null" + ], + "uniqueItems": true + } + } + }, + "technical_overview": { + "description": "Individual technical overview for the report", + "type": "object", + "properties": { + "description": { + "description": "Individual technical overview for the report", + "type": [ + "string", + "null" + ] + }, + "images": { + "description": "Custom images for the report", + "type": [ + "array", + "null" + ], + "uniqueItems": true + } + } + }, + "questions": { + "description": "Custom questions for the report", + "type": [ + "object", + "null" + ], + "uniqueItems": true + }, + "abuse_cases": { + "description": "Custom abuse cases for the report", + "type": [ + "object", + "null" + ], + "uniqueItems": true + }, + "security_requirements": { + "description": "Custom security requirements for the report", + "type": [ + "object", + "null" + ], + "uniqueItems": true + }, + "tags_available": { + "description": "Tags available", + "type": [ + "array", + "null" + ], + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "data_assets": { + "description": "Data assets", + "type": "object", + "uniqueItems": true, + "additionalProperties": { + "type": "object", + "properties": { + "id": { + "description": "ID", + "type": "string" + }, + "description": { + "description": "Description", + "type": [ + "string", + "null" + ] + }, + "usage": { + "description": "Usage", + "type": "string", + "enum": [ + "business", + "devops" + ] + }, + "tags": { + "description": "Tags", + "type": [ + "array", + "null" + ], + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "origin": { + "description": "Origin", + "type": [ + "string", + "null" + ] + }, + "owner": { + "description": "Owner", + "type": [ + "string", + "null" + ] + }, + "quantity": { + "description": "Quantity", + "type": "string", + "enum": [ + "very-few", + "few", + "many", + "very-many" + ] + }, + "confidentiality": { + "description": "Confidentiality", + "type": "string", + "enum": [ + "public", + "internal", + "restricted", + "confidential", + "strictly-confidential" + ] + }, + "integrity": { + "description": "Integrity", + "type": "string", + "enum": [ + "archive", + "operational", + "important", + "critical", + "mission-critical" + ] + }, + "availability": { + "description": "Availability", + "type": "string", + "enum": [ + "archive", + "operational", + "important", + "critical", + "mission-critical" + ] + }, + "justification_cia_rating": { + "description": "Justification of the rating", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "description", + "usage", + "quantity", + "confidentiality", + "integrity", + "availability" + ] + } + }, + "technical_assets": { + "description": "Technical assets", + "type": "object", + "uniqueItems": true, + "additionalProperties": { + "type": "object", + "properties": { + "id": { + "description": "ID", + "type": "string" + }, + "description": { + "description": "Description", + "type": [ + "string", + "null" + ] + }, + "type": { + "description": "Type", + "type": "string", + "enum": [ + "external-entity", + "process", + "datastore" + ] + }, + "usage": { + "description": "Usage", + "type": "string", + "enum": [ + "business", + "devops" + ] + }, + "used_as_client_by_human": { + "description": "Used as client by human", + "type": "boolean" + }, + "out_of_scope": { + "description": "Out of scope", + "type": "boolean" + }, + "justification_out_of_scope": { + "description": "Justification of out of scope", + "type": [ + "string", + "null" + ] + }, + "size": { + "description": "Size", + "type": "string", + "enum": [ + "system", + "service", + "application", + "component" + ] + }, + "technology": { + "description": "Technology", + "type": "string", + "enum": [ + "unknown-technology", + "client-system", + "browser", + "desktop", + "mobile-app", + "devops-client", + "web-server", + "web-application", + "application-server", + "database", + "file-server", + "local-file-system", + "erp", + "cms", + "web-service-rest", + "web-service-soap", + "ejb", + "search-index", + "search-engine", + "service-registry", + "reverse-proxy", + "load-balancer", + "build-pipeline", + "sourcecode-repository", + "artifact-registry", + "code-inspection-platform", + "monitoring", + "ldap-server", + "container-platform", + "batch-processing", + "event-listener", + "identity-provider", + "identity-store-ldap", + "identity-store-database", + "tool", + "cli", + "task", + "function", + "gateway", + "iot-device", + "message-queue", + "stream-processing", + "service-mesh", + "data-lake", + "report-engine", + "ai", + "mail-server", + "vault", + "hsm", + "waf", + "ids", + "ips", + "scheduler", + "mainframe", + "block-storage", + "library" + ] + }, + "tags": { + "description": "Tags", + "type": [ + "array", + "null" + ], + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "internet": { + "description": "Internet", + "type": "boolean" + }, + "machine": { + "description": "Machine", + "type": "string", + "enum": [ + "physical", + "virtual", + "container", + "serverless" + ] + }, + "encryption": { + "description": "Encryption", + "type": "string", + "enum": [ + "none", + "transparent", + "data-with-symmetric-shared-key", + "data-with-asymmetric-shared-key", + "data-with-end-user-individual-key" + ] + }, + "owner": { + "description": "Owner", + "type": [ + "string", + "null" + ] + }, + "confidentiality": { + "description": "Confidentiality", + "type": "string", + "enum": [ + "public", + "internal", + "restricted", + "confidential", + "strictly-confidential" + ] + }, + "integrity": { + "description": "Integrity", + "type": "string", + "enum": [ + "archive", + "operational", + "important", + "critical", + "mission-critical" + ] + }, + "availability": { + "description": "Availability", + "type": "string", + "enum": [ + "archive", + "operational", + "important", + "critical", + "mission-critical" + ] + }, + "justification_cia_rating": { + "description": "Justification of the rating", + "type": [ + "string", + "null" + ] + }, + "multi_tenant": { + "description": "Multi tenant", + "type": "boolean" + }, + "redundant": { + "description": "Redundant", + "type": "boolean" + }, + "custom_developed_parts": { + "description": "Custom developed parts", + "type": "boolean" + }, + "data_assets_processed": { + "description": "Data assets processed; ; all data assets stored or sent or received via a communication link (be it as a source or a target) are implicitly also processed and do not need to be listed here.", + "type": [ + "array", + "null" + ], + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "data_assets_stored": { + "description": "Data assets stored", + "type": [ + "array", + "null" + ], + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "data_formats_accepted": { + "description": "Data formats accepted", + "type": [ + "array", + "null" + ], + "uniqueItems": true, + "items": { + "type": "string", + "enum": [ + "json", + "xml", + "serialization", + "file", + "csv", + "yaml" + ] + } + }, + "diagram_tweak_order": { + "description": "diagram tweak order (affects left to right positioning)", + "type": "integer" + }, + "communication_links": { + "description": "Communication links", + "type": [ + "object", + "null" + ], + "uniqueItems": true, + "additionalProperties": { + "type": "object", + "properties": { + "target": { + "description": "Target", + "type": "string" + }, + "description": { + "description": "Description", + "type": [ + "string", + "null" + ] + }, + "protocol": { + "description": "Protocol", + "type": "string", + "enum": [ + "unknown-protocol", + "http", + "https", + "ws", + "wss", + "reverse-proxy-web-protocol", + "reverse-proxy-web-protocol-encrypted", + "mqtt", + "jdbc", + "jdbc-encrypted", + "odbc", + "odbc-encrypted", + "sql-access-protocol", + "sql-access-protocol-encrypted", + "nosql-access-protocol", + "nosql-access-protocol-encrypted", + "binary", + "binary-encrypted", + "text", + "text-encrypted", + "ssh", + "ssh-tunnel", + "smtp", + "smtp-encrypted", + "pop3", + "pop3-encrypted", + "imap", + "imap-encrypted", + "ftp", + "ftps", + "sftp", + "scp", + "ldap", + "ldaps", + "jms", + "nfs", + "smb", + "smb-encrypted", + "local-file-access", + "nrpe", + "xmpp", + "iiop", + "iiop-encrypted", + "jrmp", + "jrmp-encrypted", + "in-process-library-call", + "inter-process-communication", + "container-spawning" + ] + }, + "authentication": { + "description": "Authentication", + "type": "string", + "enum": [ + "none", + "credentials", + "session-id", + "token", + "client-certificate", + "two-factor", + "externalized" + ] + }, + "authorization": { + "description": "Authorization", + "type": "string", + "enum": [ + "none", + "technical-user", + "end-user-identity-propagation" + ] + }, + "tags": { + "description": "Tags", + "type": [ + "array", + "null" + ], + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "vpn": { + "description": "VPN", + "type": "boolean" + }, + "ip_filtered": { + "description": "IP filtered", + "type": "boolean" + }, + "readonly": { + "description": "readonly", + "type": "boolean" + }, + "usage": { + "description": "Usage", + "type": "string", + "enum": [ + "business", + "devops" + ] + }, + "data_assets_sent": { + "description": "Data assets sent", + "type": [ + "array", + "null" + ], + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "data_assets_received": { + "description": "Data assets received", + "type": [ + "array", + "null" + ], + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "diagram_tweak_weight": { + "description": "diagram tweak weight", + "type": "integer" + }, + "diagram_tweak_constraint": { + "description": "diagram tweak constraint", + "type": "boolean" + } + }, + "required": [ + "target", + "description", + "protocol", + "authentication", + "authorization", + "vpn", + "ip_filtered", + "readonly", + "usage" + ] + } + } + }, + "required": [ + "id", + "description", + "type", + "usage", + "used_as_client_by_human", + "out_of_scope", + "size", + "technology", + "internet", + "machine", + "encryption", + "owner", + "confidentiality", + "integrity", + "availability", + "multi_tenant", + "redundant", + "custom_developed_parts", + "data_assets_processed", + "data_assets_stored", + "data_formats_accepted", + "communication_links" + ] + } + }, + "trust_boundaries": { + "description": "Trust boundaries", + "type": "object", + "uniqueItems": true, + "additionalProperties": { + "type": "object", + "properties": { + "id": { + "description": "ID", + "type": "string" + }, + "description": { + "description": "Description", + "type": [ + "string", + "null" + ] + }, + "type": { + "description": "Type", + "type": "string", + "enum": [ + "network-on-prem", + "network-dedicated-hoster", + "network-virtual-lan", + "network-cloud-provider", + "network-cloud-security-group", + "network-policy-namespace-isolation", + "execution-environment" + ] + }, + "tags": { + "description": "Tags", + "type": [ + "array", + "null" + ], + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "technical_assets_inside": { + "description": "Technical assets inside", + "type": [ + "array", + "null" + ], + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "trust_boundaries_nested": { + "description": "Trust boundaries nested", + "type": [ + "array", + "null" + ], + "uniqueItems": true, + "items": { + "type": "string" + } + } + }, + "required": [ + "id", + "description", + "type", + "technical_assets_inside", + "trust_boundaries_nested" + ] + } + }, + "shared_runtimes": { + "description": "Shared runtimes", + "type": "object", + "uniqueItems": true, + "additionalProperties": { + "type": "object", + "properties": { + "id": { + "description": "ID", + "type": "string" + }, + "description": { + "description": "Description", + "type": [ + "string", + "null" + ] + }, + "tags": { + "description": "Tags", + "type": [ + "array", + "null" + ], + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "technical_assets_running": { + "description": "Technical assets running", + "type": [ + "array", + "null" + ], + "uniqueItems": true, + "items": { + "type": "string" + } + } + }, + "required": [ + "id", + "description", + "technical_assets_running" + ] + } + }, + "individual_risk_categories": { + "description": "Individual risk categories", + "type": [ + "object", + "null" + ], + "uniqueItems": true, + "additionalProperties": { + "type": "object", + "properties": { + "id": { + "description": "ID", + "type": "string" + }, + "description": { + "description": "Description", + "type": [ + "string", + "null" + ] + }, + "impact": { + "description": "Impact", + "type": "string" + }, + "asvs": { + "description": "ASVS", + "type": "string" + }, + "cheat_sheet": { + "description": "Cheat sheet", + "type": "string" + }, + "action": { + "description": "Action", + "type": "string" + }, + "mitigation": { + "description": "Mitigation", + "type": "string" + }, + "check": { + "description": "Check", + "type": "string" + }, + "function": { + "description": "Function", + "type": "string", + "enum": [ + "business-side", + "architecture", + "development", + "operations" + ] + }, + "stride": { + "description": "STRIDE", + "type": "string", + "enum": [ + "spoofing", + "tampering", + "repudiation", + "information-disclosure", + "denial-of-service", + "elevation-of-privilege" + ] + }, + "detection_logic": { + "description": "Detection logic", + "type": "string" + }, + "risk_assessment": { + "description": "Risk assessment", + "type": "string" + }, + "false_positives": { + "description": "False positives", + "type": "string" + }, + "model_failure_possible_reason": { + "description": "Model failure possible reason", + "type": "boolean" + }, + "cwe": { + "description": "CWE", + "type": "integer" + }, + "risks_identified": { + "description": "Risks identified", + "type": "object", + "uniqueItems": true, + "additionalProperties": { + "type": "object", + "properties": { + "severity": { + "description": "Severity", + "type": "string", + "enum": [ + "low", + "medium", + "elevated", + "high", + "critical" + ] + }, + "exploitation_likelihood": { + "description": "Exploitation likelihood", + "type": "string", + "enum": [ + "unlikely", + "likely", + "very-likely", + "frequent" + ] + }, + "exploitation_impact": { + "description": "Exploitation impact", + "type": "string", + "enum": [ + "low", + "medium", + "high", + "very-high" + ] + }, + "data_breach_probability": { + "description": "Data breach probability", + "type": "string", + "enum": [ + "improbable", + "possible", + "probable" + ] + }, + "data_breach_technical_assets": { + "description": "Data breach technical assets", + "type": [ + "array", + "null" + ], + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "most_relevant_data_asset": { + "description": "Most relevant data asset", + "type": [ + "string", + "null" + ] + }, + "most_relevant_technical_asset": { + "description": "Most relevant technical asset", + "type": [ + "string", + "null" + ] + }, + "most_relevant_communication_link": { + "description": "Most relevant communication link", + "type": [ + "string", + "null" + ] + }, + "most_relevant_trust_boundary": { + "description": "Most relevant trust boundary", + "type": [ + "string", + "null" + ] + }, + "most_relevant_shared_runtime": { + "description": "Most relevant shared runtime", + "type": [ + "string", + "null" + ] + } + } + } + } + }, + "required": [ + "id", + "description", + "impact", + "asvs", + "cheat_sheet", + "action", + "mitigation", + "check", + "function", + "stride", + "detection_logic", + "risk_assessment", + "false_positives", + "model_failure_possible_reason", + "cwe", + "risks_identified" + ] + } + }, + "risk_tracking": { + "description": "Risk tracking", + "type": [ + "object", + "null" + ], + "uniqueItems": true, + "additionalProperties": { + "type": "object", + "properties": { + "status": { + "description": "Status", + "type": "string", + "enum": [ + "unchecked", + "in-discussion", + "accepted", + "in-progress", + "mitigated", + "false-positive" + ] + }, + "justification": { + "description": "Justification", + "type": [ + "string", + "null" + ] + }, + "ticket": { + "description": "Ticket", + "type": [ + "string", + "null" + ] + }, + "date": { + "description": "Date", + "type": [ + "string", + "null" + ], + "format": "date" + }, + "checked_by": { + "description": "Checked by", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "status", + "justification", + "ticket", + "date", + "checked_by" + ] + } + }, + "diagram_tweak_suppress_edge_labels": { + "description": "Diagram tweak suppress edge labels", + "type": [ + "boolean", + "null" + ] + }, + "diagram_tweak_layout_left_to_right": { + "description": "Diagram tweak layout left to right", + "type": [ + "boolean", + "null" + ] + }, + "diagram_tweak_edge_layout": { + "description": "Diagram tweak edge layout", + "type": [ + "string", + "null" + ], + "enum": [ + "", + "ortho", + "spline", + "polyline", + "false", + "curved" + ] + }, + "diagram_tweak_nodesep": { + "description": "Diagram tweak nodesep", + "type": [ + "integer", + "null" + ] + }, + "diagram_tweak_ranksep": { + "description": "Diagram tweak ranksep", + "type": [ + "integer", + "null" + ] + }, + "diagram_tweak_invisible_connections_between_assets": { + "description": "Diagram tweak invisible connections between assets", + "type": [ + "array", + "null" + ], + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "diagram_tweak_same_rank_assets": { + "description": "Diagram tweak same rank assets", + "type": [ + "array", + "null" + ], + "uniqueItems": true, + "items": { + "type": "string" + } + } + }, + "required": [ + "threagile_version", + "title", + "author", + "business_criticality", + "tags_available", + "data_assets", + "technical_assets", + "shared_runtimes" + ] +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..71de926 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,8 @@ +{ + "recommendations": [ + "ckolkman.vscode-postgres" + ] + "yaml.schemas": { + "./.threagile/schema.json": ["threagile.yaml"] + } +} diff --git a/100/README.md b/100/README.md new file mode 100644 index 0000000..4ab52b0 --- /dev/null +++ b/100/README.md @@ -0,0 +1 @@ +# 100 - Introduction diff --git a/200/README.md b/200/README.md new file mode 100644 index 0000000..feee683 --- /dev/null +++ b/200/README.md @@ -0,0 +1 @@ +# 200 - Requirements diff --git a/300/100/README.md b/300/100/README.md new file mode 100644 index 0000000..107a0d4 --- /dev/null +++ b/300/100/README.md @@ -0,0 +1,15 @@ +# 100 - Why Use an Nx Monorepo? + +In this tutorial, we'll set up a monorepo that is configured with a set of features that work together toward the goal of allowing developers to focus on building features rather than the configuration, coordination and maintenance of the tooling in the repo. + +You'll notice that instead of using npm/yarn/pnpm workspaces, projects within the repository are linked using typescript path aliases that are defined in the ```tsconfig.base.json``` file. Also, since we're creating projects using Nx plugin generators, all new projects come preconfigured with useful tools like Prettier, ESLint and Jest. + +Nx Plugins are optional packages that extend the capabilities of Nx, catering to various specific technologies. For instance, we have plugins tailored to React (e.g., ```@nx/react```), Vite (```@nx/vite```), Cypress (```@nx/cypress```), and more. These plugins offer additional features, making your development experience more efficient and enjoyable when working with specific tech stacks. + +Features we'll use in this monorepo: + +- [Install dependencies at the root by default](https://nx.dev/concepts/decisions/dependency-management#single-version-policy) +- [Scaffold new code with generators](https://nx.dev/features/generate-code) +- [Updates dependencies with automated migrations](https://nx.dev/features/automate-updating-dependencies) + +Visit our "[Why Nx](https://nx.dev/getting-started/why-nx)" page for more details. diff --git a/300/200/README.md b/300/200/README.md new file mode 100644 index 0000000..4a50a17 --- /dev/null +++ b/300/200/README.md @@ -0,0 +1,5 @@ +# 200 - Video and example of final code + +Watch the video "[Tutorial - Getting Started with a React Monorepo](https://youtu.be/gc4N7kxiA50)". + +Here's the [source code](https://github.com/nrwl/nx-recipes/tree/main/react-monorepo) of an example of the final result for this tutorial. diff --git a/300/300/README.md b/300/300/README.md new file mode 100644 index 0000000..7c98014 --- /dev/null +++ b/300/300/README.md @@ -0,0 +1,501 @@ +# 300 - Creating a New React Monorepo + +Create a new React monorepo with the following command: + +``` +$ cd hatch-project/src # navigate to the 'hatch-project/src' sub-directory, previously created by hatch +$ npx create-nx-workspace@latest hatch_project --preset=react-monorepo +``` + +When prompted, provide the following answers: + +``` +Need to install the following packages: +create-nx-workspace@20.4.0 +Ok to proceed? (y) +``` + +Click y & ENTER. + +``` +NX Let's create a new workspace [https://nx.dev/getting-started/intro] + +? Application name hatch_project +``` + +Click ENTER. + +``` +? Which bundler would you like to use? +Vite [ https://vitejs.dev/ ] +Webpack [ https://webpack.js.org/ ] +Rspack [ https://www.rspack.dev/ ] +``` + +Highlight **Webpack** with the arrow keys and click ENTER. + +``` +? Test runner to use for end to end (E2E) tests ... +Playwright [ https://playwright.dev/ ] +Cypress [ https://www.cypress.io/ ] +None +``` + +Highlight **Playwright** with the arrow keys and click ENTER. + +``` +? Default stylesheet format ... +CSS +SASS(.scss) [ https://sass-lang.com ] +LESS [ https://lesscss.org ] +tailwind [ https://tailwindcss.com ] +styled-components [ https://styled-components.com ] +emotion [ https://emotion.sh ] +styled-jsx [ https://www.npmjs.com/package/styled-jsx ] +``` + +Highlight **tailwindcss** with the arrow keys and click ENTER. + + +``` +? Which CI provider would you like to use? ... +GitHub Actions +Gitlab +Azure DevOps +BitBucket Pipelines +Circle CI + +Do it later +``` + +Highlight **GitHub Actions** with the arrow keys and click ENTER. + +It will respond with: + +``` +NX Creating your v20.4.0 workspace. + +Installing dependencies with npm +Successfully created the workspace: hatch_project +Nx Cloud has been set up successfully +CI workflow has been generated successfully + +NX Directory is already under version control. Skipping initialization of git. + +NX Your CI setup is almost complete. + +Finish it by visiting: https://cloud.nx.app/connect/lvaFjW0bDV + +NX Welcome to the Nx community! 👋 + +🌟 Star Nx on GitHub: https://github.com/nrwl/nx +📢 Stay up to date on X: https://x.com/nxdevtools +💬 Discuss Nx on Discord: https://go.nx.dev/community +``` + +This will generate the following file and directory structure underneath the ```/hatch-project/src``` directory (Note: ```hatch_project``` uses that same directory as previously created by Hatch. **This is intentional!**): + +``` +└─ hatch-project + └─ src + └─ hatch_project + ├─ ... + ├─ apps + │ ├─ hatch_project + │ │ ├─ public + │ │ │ └─ ... + │ │ ├─ src + │ │ │ ├─ app + │ │ │ │ ├─ app.module.css + │ │ │ │ ├─ app.spec.tsx + │ │ │ │ ├─ app.tsx + │ │ │ │ └─ nx-welcome.tsx + │ │ │ ├─ assets + │ │ │ ├─ main.tsx + │ │ │ └─ styles.css + │ │ ├─ index.html + │ │ ├─ project.json + │ │ ├─ tsconfig.app.json + │ │ ├─ tsconfig.json + │ │ ├─ tsconfig.spec.json + │ │ └─ vite.config.ts + │ └─ hatch_project-e2e + │ └─ ... + ├─ nx.json + ├─ tsconfig.base.json + └─ package.json +``` + +**Important**: Move all files previously in ```original_hatch_project``` to ```hatch_project``` and delete ```original_hatch_project```! + +### Key Points: +- **`hatch_project/nx.json`**: Configuration for the Nx workspace. +- **`hatch_project/package.json`**: Dependencies and scripts specific to the project. +- **`hatch_project/tsconfig.json`**: TypeScript configuration for the project. +- **`hatch_project/workspace.json` or `project.json`**: Defines the structure and projects within the workspace. + +**IMPORTANT**: Move **nx.json** to the root of the repository so it can connect with Nx Cloud. + +``` +├─ hatch-project +│ ├─ ... +│ └─ src +│ └─ hatch_project +│ ├─ ... +├─ nx.json +``` + +**IMPORTANT**: Modify **nx.json** so it can connect with Nx Cloud. + +To support the nested directory structure correctly in your ```/nx.json```, you should adjust the paths to reflect the correct locations within the nested workspace. Here’s a revised example: + +```json +{ + "$schema": "./node_modules/nx/schemas/nx-schema.json", + "namedInputs": { + "default": ["{projectRoot}/**/*", "sharedGlobals"], + "nxCloudId": ["67a3831acafec34e47159841"], + "production": [ + "default", + "!{projectRoot}/.eslintrc.json", + "!{projectRoot}/eslint.config.mjs", + "!{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": ["{workspaceRoot}/.github/workflows/ci.yml"] + }, + "nxCloudId": "67b72b5c86db7789c5ca1378", + "plugins": [ + { + "plugin": "@nx/webpack/plugin", + "options": { + "buildTargetName": "build", + "serveTargetName": "serve", + "previewTargetName": "preview", + "buildDepsTargetName": "build-deps", + "watchDepsTargetName": "watch-deps" + } + }, + { + "plugin": "@nx/eslint/plugin", + "options": { + "targetName": "lint" + } + }, + { + "plugin": "@nx/playwright/plugin", + "options": { + "targetName": "e2e" + } + }, + { + "plugin": "@nx/jest/plugin", + "options": { + "targetName": "test" + } + } + ], + "targetDefaults": { + "e2e-ci--**/*": { + "dependsOn": ["^build"] + } + }, + "generators": { + "@nx/react": { + "application": { + "babel": true, + "style": "tailwind", + "linter": "eslint", + "bundler": "webpack" + }, + "component": { + "style": "tailwind" + }, + "library": { + "style": "tailwind", + "linter": "eslint" + } + } + }, + "projects": { + "hatch_project": { + "root": "hatch-project/src/hatch_project", + "sourceRoot": "hatch-project/src/hatch_project/src", + "projectType": "application" + } + } +} +``` +repository-name/nx.json + +### Key Adjustments: +- **`projects` section**: Explicitly defines the project structure, setting the `root` and `sourceRoot` to the correct paths within the nested directory. +- Ensure that all paths reflect the actual structure of your workspace. + +This configuration will help Nx Cloud properly identify and manage your nested workspace. + +Notice that it prepends paths with ```hatch-project/src/``` (e.g., ```"root": "hatch-project/src/hatch_project",```) to allow for our **nested** directory structure. + +The path for `root` in the `projects` section should be specified relative to the workspace root, which is typically the directory where your `nx.json` file is located. + +Since your `nx.json` is at `repository-name/nx.json`, the paths are relative to the `hatch-project/src/hatch_project` directory. Thus: + +- **`root`**: Should be `"hatch-project/src/hatch_project"` because it indicates the base directory for the project relative to the workspace's root. +- **`sourceRoot`**: Should be `"hatch-project/src/hatch_project/src"` for the same reason. + +If you were to use the absolute path `hatch-project/src/hatch_project`, it would not be correct in the context of how Nx expects paths to be defined. Nx uses paths relative to the workspace root to maintain consistency across different environments and setups. **Note**: In our case the path is from the root of the repository so there is no difference in relative or absolute path. + +### Key Sections: +- **`npmScope`**: Defines the scope for your packages. +- **`affected.defaultBase`**: Specifies the default branch for determining affected projects. +- **`tasksRunnerOptions`**: Configures caching and task running options. +- **`projects`**: Contains the project configuration, specifying the root and source root paths, project type, and build targets. + +Adjust paths and options as necessary to fit your specific project structure. This configuration will help Nx Cloud identify and manage your workspace correctly. + +Make sure to run the **build** command from the root of the repository - which contains the ```nx.json``` file - to ensure it recognizes the workspace correctly: + +``` +$ cd / # Go to the root of the repository +$ nx build hatch_project +``` + +**Important**: + +If you don't have `workspace.json` or `project.json`, and instead have `tsconfig.base.json`, you can adjust your setup as follows: + +* Option: Single Application: **Create a `workspace.json`**: If your project is a single application, you can create a `workspace.json` file in the root of the repository. Here’s a basic example: + +```json +{ + "version": 1, + "projects": { + "hatch_project": { + "root": "hatch-project/src/hatch_project", + "sourceRoot": "hatch-project/src/hatch_project/src", + "projectType": "application" + } + } +} +``` +repository-name/workspace.json + +* Option: Multiple Applications: If your Nx workspace contains multiple applications, you should structure your `workspace.json` (or `project.json`) to reflect each application. Here’s how to set it up: + +### Example `workspace.json` + +Create a `workspace.json` file in the root of the repository with the following structure: + +```json +{ + "version": 1, + "projects": { + "app1": { + "root": "hatch-project/src/hatch_project/app1", + "sourceRoot": "hatch-project/src/hatch_project/app1/src", + "projectType": "application" + }, + "app2": { + "root": "hatch-project/src/hatch_project/app2", + "sourceRoot": "hatch-project/src/hatch_project/app2/src", + "projectType": "application" + }, + "hatch_project": { + "root": "hatch-project/src/hatch_project", + "sourceRoot": "hatch-project/src/hatch_project/src", + "projectType": "application" + } + } +} +``` + +### Key Points: +- **Project Names**: Replace `app1`, `app2`, etc., with meaningful names for your applications. +- **Root and Source Root**: Adjust the `root` and `sourceRoot` paths to match the actual structure of your applications within the `hatch_project` directory. + +### Additional Considerations: +- **Dependencies**: If applications depend on shared libraries or each other, ensure to define those dependencies in the `nx.json` file. +- **Configuration Files**: Each application may also have its own `tsconfig.json` if needed, or you can use a shared `tsconfig.base.json` for common settings. + +### Example Directory Structure +Your directory structure might look like this: + +``` +/ +├── hatch-project/ +| ├── tsconfig.base.json +│ └── src/ +│ └── hatch_project/ +│ ├── REMOVE: nx.json +│ ├── REMOVE: workspace.json +│ ├── REMOVE: tsconfig.base.json +│ ├── app1/ +│ │ └── src/ +│ │ └── main.tsx +│ ├── app2/ +│ │ └── src/ +│ │ └── main.tsx +├── nx.json +├── workspace.json +``` + +Where ```tsconfig.base.json``` contains: + +``` +{ + "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": {} + }, + "exclude": ["node_modules", "tmp"] +} +``` +/hatch-project/src/hatch_project/tsconfig.base.json + +### Running Commands +After setting up `workspace.json`, you can run commands like: + +```bash +$ cd / # Go to the root of the repository +$ nx build app1 +$ nx build app2 +``` + +This structure will help Nx Cloud recognize and manage multiple applications effectively. + +This structure should allow Nx Cloud to detect the workspace properly. + +Run the command to **connect** your workspace to Nx Cloud from the root of the repository, specifically: + +``` +$ cd / # Go to the root of the repository +$ npm init -y # If no package.json exists +# Go through the initialization steps +$ npm install -g nx@latest # If not already installed +$ npm install --save-dev nx +$ npm install --save-dev @nrwl/workspace +$ npm install --save-dev @nx/webpack +$ npm install --save-dev webpack-cli +$ npm install --save-dev @nx/react @nx/eslint @nx/playwright @nx/jest +``` + +Above command will create a ```package.json``` file at the root of the repository: + +``` +{ + "name": "repository-name", + "version": "1.0.0", + "description": "repository-name", + "main": "index.js", + "directories": { + "doc": "docs" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "your-github-username", + "license": "ISC", + "devDependencies": { + "@nrwl/workspace": "^19.8.4", + "@nx/eslint": "^20.4.5", + "@nx/jest": "^20.4.5", + "@nx/playwright": "^20.4.5", + "@nx/react": "^20.4.5", + "@nx/webpack": "^20.4.5", + "nx": "^20.4.5", + "webpack-cli": "^6.0.1" + } +} +``` +repository-name/package.json + +Now commit these changes to GitHub repository before continuing! + +The command to connect to Nx Cloud is: + +``` +$ cd / # Go to the root of the repository +$ nx connect-to-nx-cloud +``` + +This will initiate the configuration process for Nx Cloud within your workspace. + +You will be prompted as follows: + +``` + NX ✔ This workspace already has Nx Cloud set up + +If you have not done so already, connect your workspace to your Nx Cloud account with the following URL: + +https://cloud.nx.app/connect/Ehf8PFoDWR +``` + +Finish the CI setup by visiting: https://cloud.nx.app/connect/eXwFUcpdBt # **Note**: the URL will differ per creation. See [Enable GitHub PR Integration](https://nx.dev/ci/recipes/source-control-integration/github) and/or watch [PNPM-CI: Connect Your Workspace to Nx Cloud for Enhanced Collaboration](https://www.youtube.com/watch?v=8mqHXYIl_qI). + +The message "A workspace has already been assigned to this Nx Cloud connection" means that: + +1. Your workspace is already configured with an Nx Cloud ID +2. That ID is already in use by another workspace + +To fix this: + +1. Check your current nx.json for the existing nxCloudId: + - Look for a line like: "nxCloudId": "67a3783761d0514ff26bf202" + - This ID needs to be unique for each workspace + +2. Generate a new connection: + +``` +$ nx generate @nx/workspace:disconnect-cloud +$ nx connect-to-nx-cloud +``` + +This will: + - Remove the existing cloud connection + - Generate a new, unique connection + - Provide you with a fresh URL to connect + +## Nested app directories + +You can have nested folders, no problems. 👍 Here's a [live example](https://github.com/codyslexia/nexa/tree/main/apps/graphql). You can see that apps/graphql/users is a nested directory where users is the actual project. There's also this [other example](https://github.com/nrwl/nx-incremental-large-repo/tree/master/libs/app0/lib1) from the ```nrwl``` family. + +## Nx ignore + +You can place a ```.nxignore``` in the root of the project directory, here ```/hatch-project/src/hatch_project/.nxignore```. + +For example to ignore any files in ```.next```: + +``` +.next +``` +/hatch-project/src/hatch_project/.nxignore + +Now to run a build, run the following command from the root of the repository: + +``` +$ cd / # Go to the root of the repository +$ npx nx run-many -t build +``` + +To run a build for all applications, run the following command from the root of the repository: + +``` +$ cd / # Go to the root of the repository +$ npx nx run-many -t build --all +``` diff --git a/300/400/README.md b/300/400/README.md new file mode 100644 index 0000000..ed1488f --- /dev/null +++ b/300/400/README.md @@ -0,0 +1,59 @@ +# 400 - Building the New React Monorepo + +## 100 - Test the Built Application + +First, let's serve the application: + +``` +npx nx serve hatch_project +``` + +This will: +- Start a development server +- Usually on http://localhost:4200 +- Auto-reload on changes + +## 200 - Set up Continuous Integration + +To set up CI with GitHub Actions: + +a. Create the workflow file: + +``` +mkdir -p .github/workflows +``` + +b. Create the CI configuration: + +``` +name: CI +on: + push: + branches: + - main + pull_request: + +jobs: + main: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + with: + node-version: 20 + cache: 'npm' + - run: npm cache clean --force + - run: npm ci + - run: npm install -g @nrwl/cli + - run: | + npm install --save-dev @swc-node/register @swc/core \ + @nx/webpack webpack-cli \ + @nx/eslint-plugin eslint-plugin-playwright \ + @playwright/test jest \ + @nx/jest @nx/react @nx/eslint @nx/playwright + - run: npx nx run-many -t build --verbose + - run: npx nx run-many -t test +``` +.github/workflows/ci.yml + +Our GitHub Actions workflow is now set up and successfully running builds and tests. diff --git a/300/500/README.md b/300/500/README.md new file mode 100644 index 0000000..ef94895 --- /dev/null +++ b/300/500/README.md @@ -0,0 +1,216 @@ +## 500 - Deploy with Nx Cloud + +To set up deployments with Nx Cloud: + +1. **Connect to Nx Cloud** (if not already done): + +```bash +$ cd / # Go to the root of the repository +$ npx nx connect-to-nx-cloud +``` + +2. **Enable Distributed Task Execution**: +- Visit https://nx.app +- Select your workspace +- Go to "Distributed Task Execution" +- Enable the feature + +3. **Set up Distributed Caching**: + +```bash +$ cd / # Go to the root of the repository +$ nx run-many -t build --parallel -- --mode=production +``` + +You will be prompted like below: + +``` + ✔ nx run hatch_project:build (13s) + +————————————————————————————————————————————————————————————————— + + NX Successfully ran target build for project hatch_project (13s) + + With additional flags: + --mode=production + +View logs and investigate cache misses at https://nx.app/runs/nrF7JPvJXE +``` + +4. **Configure Deployment Pipeline**: + +- If not already existing, create a branch in your GitHub repository called "gh-pages". +- In the **Settings** of the GitHub Repository choose **Pages**. +- Under **Branch**, select "gh-pages" and "root". Click **Save**. +- Create a new file: `.github/workflows/deploy.yml` +- This will handle: + - Building the application + - Running tests + - Deploying to your chosen platform + +``` +name: Deploy +on: + push: + branches: + - main + workflow_dispatch: # Allows manual triggering + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + with: + node-version: 20 + + # Clean up existing workspace + - run: | + echo "Cleaning up workspace..." + rm -rf hatch-project + rm -rf apps + rm -f nx.json + rm -f package.json + rm -f package-lock.json + + # Create temporary directory for the new workspace + - run: | + echo "Creating temporary directory..." + mkdir -p /tmp/nx-workspace + cd /tmp/nx-workspace + + echo "Creating new Nx workspace..." + npx create-nx-workspace@latest . \ + --preset=react-monorepo \ + --appName=hatch_project \ + --style=css \ + --nxCloud=skip \ + --packageManager=npm \ + --no-interactive \ + --defaultBase=main + + echo "Workspace contents:" + ls -la + + echo "Copying workspace files back..." + cd $GITHUB_WORKSPACE + cp -r /tmp/nx-workspace/* . + cp -r /tmp/nx-workspace/.* . 2>/dev/null || true + + # Configure base URL for GitHub Pages + - run: | + echo "Configuring base URL..." + REPO_NAME=$(echo "$GITHUB_REPOSITORY" | cut -d'/' -f2) + echo "Base URL will be: /$REPO_NAME/" + + # Update vite.config.ts + cat > apps/hatch_project/vite.config.ts << EOF + /// + import { defineConfig } from 'vite'; + import react from '@vitejs/plugin-react'; + import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; + + export default defineConfig({ + root: __dirname, + base: '/$REPO_NAME/', + cacheDir: '../../node_modules/.vite/hatch_project', + + plugins: [react(), nxViteTsPaths()], + + build: { + outDir: '../../dist/apps/hatch_project', + emptyOutDir: true, + reportCompressedSize: true, + commonjsOptions: { transformMixedEsModules: true }, + }, + + test: { + globals: true, + cache: { + dir: '../../node_modules/.vitest', + }, + environment: 'jsdom', + include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + }, + }); + EOF + + # Build for production + - run: | + echo "Running build command..." + npx nx build hatch_project --configuration=production --verbose + + # Update HTML file with correct base URL + - run: | + echo "Updating base URL in index.html..." + REPO_NAME=$(echo "$GITHUB_REPOSITORY" | cut -d'/' -f2) + + # Use sed to update the base href and asset paths + sed -i "s|``` command. This command creates a project directory containing a source code directory (```src```), a test directory (```tests```), and a configuration file for project-related tools (```pyproject.toml```). + +For this tutorial, let’s create a simple Python application named hatch-project that uses a Flask API. To do so, **FROM THE ROOT OF THE REPOSITORY** run ```$ hatch new "Hatch Project"```. The folder structure that’s created will look like this: + +``` +$ hatch new "Hatch Project" +hatch-project +|---- src +| |---- hatch_project +| |---- __about__.py +| |---- __init__.py +|---- tests +| |---- __init__.py +|---- LICENSE.txt +|---- README.md +|---- pyproject.toml +``` + +> **Note**: If you want to initialize an existing project, you can do so using the ```hatch new --init``` command. If there is a ```setup.py``` file available in your project, a ```setuptools``` file will be generated from it. Otherwise, Hatch interactively guides you to produce the content for the configuration file. + +We list the content for most of these files next. + +``` +# Hatch Project + +[![PyPI - Version](https://img.shields.io/pypi/v/hatch-project.svg)](https://pypi.org/project/hatch-project) +[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/hatch-project.svg)](https://pypi.org/project/hatch-project) + +----- + +## Table of Contents + +- [Installation](#installation) +- [License](#license) + +## Installation + +\`\`\`console +pip install hatch-project +\`\`\` + +## License + +`hatch-project` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license. +``` +hatch_project/README.md + +``` +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "hatch-project" +dynamic = ["version"] +description = '' +readme = "README.md" +requires-python = ">=3.8" +license = "MIT" +keywords = [] +authors = [ + { name = "Willem van Heemstra", email = "wvanheemstra@icloud.com" }, +] +classifiers = [ + "Development Status :: 4 - Beta", + "Programming Language :: Python", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", +] +dependencies = [] + +[project.urls] +Documentation = "https://github.com/Willem van Heemstra/hatch-project#readme" +Issues = "https://github.com/Willem van Heemstra/hatch-project/issues" +Source = "https://github.com/Willem van Heemstra/hatch-project" + +[tool.hatch.version] +path = "src/hatch_project/__about__.py" + +[tool.hatch.envs.types] +extra-dependencies = [ + "mypy>=1.0.0", +] +[tool.hatch.envs.types.scripts] +check = "mypy --install-types --non-interactive {args:src/hatch_project tests}" + +[tool.coverage.run] +source_pkgs = ["hatch_project", "tests"] +branch = true +parallel = true +omit = [ + "src/hatch_project/__about__.py", +] + +[tool.coverage.paths] +hatch_project = ["src/hatch_project", "*/hatch-project/src/hatch_project"] +tests = ["tests", "*/hatch-project/tests"] + +[tool.coverage.report] +exclude_lines = [ + "no cov", + "if __name__ == .__main__.:", + "if TYPE_CHECKING:", +] +``` +hatch_project/pyproject.toml + +``` +MIT License + +Copyright (c) 2025 van Heemstra Systems + +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. +``` +hatch_project/LICENSE.txt + +``` +# SPDX-FileCopyrightText: 2025-present Willem van Heemstra +# +# SPDX-License-Identifier: MIT +__version__ = "0.0.1" +``` +hatch_project/src/hatch_project/\_\_about__.py + +``` +# SPDX-FileCopyrightText: 2025-present Willem van Heemstra +# +# SPDX-License-Identifier: MIT +``` +hatch_project/src/hatch_project/\_\_init__.py + +``` +# SPDX-FileCopyrightText: 2025-present Willem van Heemstra +# +# SPDX-License-Identifier: MIT +``` +hatch_project/tests/hatch_project/\_\_init__.py + +Once you’ve created your Python application, open the ```pyproject.toml``` file. You should see that a lot of your project configuration values, such as dependencies and the Python version, are prefilled by Hatch. You’ll also notice other sections with the pattern ```[tool.hatch.*]```, which is where you’ll configure your project to use different Python dependencies, environments, and Python versions. + +More ... diff --git a/HOSTS.md b/HOSTS.md new file mode 100644 index 0000000..3fc2da9 --- /dev/null +++ b/HOSTS.md @@ -0,0 +1,32 @@ +# Hosts + +## Hetzner + +To connect via SSH to Hetzner use [the following instructions](https://serverfault.com/questions/295768/how-do-i-connect-to-ssh-with-a-different-public-key): + +Make sure the ```~/.ssh/config``` file contains a reference to Hetzner: + +``` text +Host hetzner + Hostname + User + Port 22 + IdentityFile ~/.ssh/hetzner + CertificateFile ~/.ssh/hetzner.pub + # Disable password authentication for better security + PasswordAuthentication no + # Prevent TCP forwarding if not needed + AllowTcpForwarding no + # Additional security hardening + KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512 + MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com + Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com + HostKeyAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256 +``` +~/.ssh/config + +Then all you have to do to connect is: + +``` bash +$ ssh hetzner +``` diff --git a/IMAGES.md b/IMAGES.md new file mode 100644 index 0000000..e8f9539 --- /dev/null +++ b/IMAGES.md @@ -0,0 +1,5 @@ +# Images + +## Docker Images + +- MyImage: https://hub.docker.com/repository/docker/vanheemstrasystems/myimage diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2b5f777 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 van Heemstra Systems + +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. diff --git a/NX.md b/NX.md new file mode 100644 index 0000000..b496944 --- /dev/null +++ b/NX.md @@ -0,0 +1,23 @@ +# Nx + +Based on "Installation" at https://nx.dev/getting-started/installation + +Install **Nx** (required for Nx Monorepos and Nx Cloud) globally as follows: + +``` +$ npm add --global nx@latest +``` + +To use **nx** directly, you can now just use: + +``` +$ nx --version +``` + +To update **nx**, run: + +``` +$ cd hatch-project/src/hatch_project +$ npx nx migrate latest # if nx has not yet been installed +$ nx migrate latest # if nx has already been installed +``` diff --git a/PODMAN.md b/PODMAN.md new file mode 100644 index 0000000..2293f03 --- /dev/null +++ b/PODMAN.md @@ -0,0 +1,120 @@ +# Podman + +Here's a guide to install and use Podman on macOS: + +1. Installation using Homebrew: + +``` +brew install podman +``` + +2. Initialize and start the Podman service: + +``` +podman machine init # Create a new VM +podman machine start # Start the VM +``` + +3. Basic Commands: + +``` +# Pull an image +podman pull nginx + +# List images +podman images + +# Run a container +podman run -d -p 8080:80 nginx + +# List running containers +podman ps + +# Stop a container +podman stop + +# Remove a container +podman rm + +# Remove an image +podman rmi + +# Clean up unused resources +podman system prune +``` + +4. Docker Compatibility: + +Podman is designed to be compatible with Docker, allowing you to use most Docker commands with Podman. + +Create an alias in your ~/.zshrc or ~/.bash_profile: + +``` +alias docker=podman +``` + +5. Using Podman Compose: + +``` +brew install podman-compose + +# Run docker-compose files +podman-compose up -d +``` + +6. Managing the Podman Machine: + +``` +# Check machine status +podman machine list + +# Stop the machine +podman machine stop + +# Remove the machine +podman machine rm + +# View machine logs +podman machine logs + +# Check machine status +podman machine status + +# Access machine via SSH +podman machine ssh +``` + +7. Configure Resources: + +``` +podman machine set --cpus 4 --memory 4096 +``` + +8. Connect to Podman: + +``` +# Get connection info +podman info + +# Connect to container shell +podman exec -it /bin/bash +``` + +9. Podman Desktop: + +Podman Desktop provides a GUI alternative to Docker Desktop with lower resource consumption. + +``` +# Install Podman Desktop +brew install --cask podman-desktop + +# Or download from: +# https://podman-desktop.io/ +``` + +Key benefits of Podman Desktop: +- Lower memory footprint than Docker Desktop +- Native support for rootless containers +- Compatible with Docker Compose files +- Built-in container and image management +- Integration with multiple container engines diff --git a/README.ar.md b/README.ar.md new file mode 100644 index 0000000..75fe8ca --- /dev/null +++ b/README.ar.md @@ -0,0 +1,39 @@ +اسم المستودع + +# اسم المستودع + +> خط الصرخ + +- [DNS](./DNS.md) +- [الوثائق](./DOCUMENTATION.md) +- [مسرد](./GLOSSARY.md) +- [فتحة](./HATCH.md) +- [المضيفين](./HOSTS.md) +- [الصور](./IMAGES.md) +- [NX](./NX.md) +- [رجل فرعي](./PODMAN.md) +- [مراجع](./REFERENCES.md) +- [متطلبات](./REQUIREMENTS.md) +- [القياس عن بعد](./TELEMETRY.md) + +**ملخص تنفيذي** + +نص + +ولدت مع[ريتر](https://app.rytr.me) + +## 100 - مقدمة + +يرى[README.md](./100/README.md) + +## 200 - المتطلبات + +يرى[README.md](./200/README.md) + +## 300 - بناء تطبيقنا + +يرى[README.md](./300/README.md) + +## 400 - الخلاصة + +يرى[README.md](./400/README.md) diff --git a/README.de.md b/README.de.md new file mode 100644 index 0000000..2fa6f32 --- /dev/null +++ b/README.de.md @@ -0,0 +1,39 @@ +Repository-Namen + +# Repository -Name + +> Slugline + +- [DNS](./DNS.md) +- [Dokumentation](./DOCUMENTATION.md) +- [Glossar](./GLOSSARY.md) +- [Luke](./HATCH.md) +- [Gastgeber](./HOSTS.md) +- [Bilder](./IMAGES.md) +- [NX](./NX.md) +- [Subman](./PODMAN.md) +- [Referenzen](./REFERENCES.md) +- [Anforderungen](./REQUIREMENTS.md) +- [Telemetrie](./TELEMETRY.md) + +**Zusammenfassung** + +Text + +Erzeugt mit[Ritr](https://app.rytr.me) + +## 100 - Einführung + +Sehen[README.md](./100/README.md) + +## 200 - Anforderungen + +Sehen[README.md](./200/README.md) + +## 300 - Aufbau unserer Bewerbung + +Sehen[README.md](./300/README.md) + +## 400 - Schlussfolgerung + +Sehen[README.md](./400/README.md) diff --git a/README.es.md b/README.es.md new file mode 100644 index 0000000..29bd4f4 --- /dev/null +++ b/README.es.md @@ -0,0 +1,39 @@ +repositorio + +# Nombre de repositorio + +> Línea de babosa + +- [DNS](./DNS.md) +- [Documentación](./DOCUMENTATION.md) +- [Glosario](./GLOSSARY.md) +- [Escotilla](./HATCH.md) +- [Anfitriones](./HOSTS.md) +- [Imágenes](./IMAGES.md) +- [Nx](./NX.md) +- [Submario](./PODMAN.md) +- [Referencias](./REFERENCES.md) +- [Requisitos](./REQUIREMENTS.md) +- [Telemetría](./TELEMETRY.md) + +**Resumen ejecutivo** + +Texto + +Generado con[Ritro](https://app.rytr.me) + +## 100 - Introducción + +Ver[README.md](./100/README.md) + +## 200 - Requisitos + +Ver[README.md](./200/README.md) + +## 300 - Construyendo nuestra aplicación + +Ver[README.md](./300/README.md) + +## 400 - Conclusión + +Ver[README.md](./400/README.md) diff --git a/README.fr.md b/README.fr.md new file mode 100644 index 0000000..cc81e36 --- /dev/null +++ b/README.fr.md @@ -0,0 +1,39 @@ +nom de référentiel + +# Nom de référentiel + +> Lisc + +- [DNS](./DNS.md) +- [Documentation](./DOCUMENTATION.md) +- [Glossaire](./GLOSSARY.md) +- [Trappe](./HATCH.md) +- [Hôtes](./HOSTS.md) +- [Images](./IMAGES.md) +- [Nx](./NX.md) +- [Sous-homme](./PODMAN.md) +- [Références](./REFERENCES.md) +- [Exigences](./REQUIREMENTS.md) +- [Télémétrie](./TELEMETRY.md) + +**Résumé exécutif** + +Texte + +Généré avec[Ritr](https://app.rytr.me) + +## 100 - Introduction + +Voir[README.md](./100/README.md) + +## 200 - exigences + +Voir[README.md](./200/README.md) + +## 300 - Construire notre application + +Voir[README.md](./300/README.md) + +## 400 - Conclusion + +Voir[README.md](./400/README.md) diff --git a/README.hi.md b/README.hi.md new file mode 100644 index 0000000..8e14ae2 --- /dev/null +++ b/README.hi.md @@ -0,0 +1,39 @@ +भंडार-नाम + +# भंडार नाम + +> स्लगलाइन + +- [डीएनएस](./DNS.md) +- [प्रलेखन](./DOCUMENTATION.md) +- [शब्दकोष](./GLOSSARY.md) +- [Hatch](./HATCH.md) +- [मेजबान](./HOSTS.md) +- [इमेजिस](./IMAGES.md) +- [नोकदार](./NX.md) +- [सबमैन](./PODMAN.md) +- [संदर्भ](./REFERENCES.md) +- [आवश्यकताएं](./REQUIREMENTS.md) +- [टेलीमेटरी](./TELEMETRY.md) + +**कार्यकारी सारांश** + +मूलपाठ + +के साथ उत्पन्न[Rytr](https://app.rytr.me) + +## 100 - परिचय + +देखना[README.md](./100/README.md) + +## 200 - आवश्यकताएँ + +देखना[README.md](./200/README.md) + +## 300 - हमारे आवेदन का निर्माण + +देखना[README.md](./300/README.md) + +## 400 - निष्कर्ष + +देखना[README.md](./400/README.md) diff --git a/README.md b/README.md new file mode 100644 index 0000000..d56e0d0 --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +repository-name +# Repository Name + +> Slugline + +- [DNS](./DNS.md) +- [Documentation](./DOCUMENTATION.md) +- [Glossary](./GLOSSARY.md) +- [Hatch](./HATCH.md) +- [Hosts](./HOSTS.md) +- [Images](./IMAGES.md) +- [Nx](./NX.md) +- [Podman](./PODMAN.md) +- [References](./REFERENCES.md) +- [Requirements](./REQUIREMENTS.md) +- [Telemetry](./TELEMETRY.md) + +**Executive Summary** + +Text + +Generated with [Rytr](https://app.rytr.me) + +## 100 - Introduction + +See [README.md](./100/README.md) + +## 200 - Requirements + +See [README.md](./200/README.md) + +## 300 - Building Our Application + +See [README.md](./300/README.md) + +## 400 - Conclusion + +See [README.md](./400/README.md) diff --git a/README.nl.md b/README.nl.md new file mode 100644 index 0000000..0e08f46 --- /dev/null +++ b/README.nl.md @@ -0,0 +1,39 @@ +repository-naam + +# Repository -naam + +> Sluglijn + +- [DNS](./DNS.md) +- [Documentatie](./DOCUMENTATION.md) +- [Glossarium](./GLOSSARY.md) +- [Klep](./HATCH.md) +- [Gastheren](./HOSTS.md) +- [Beelden](./IMAGES.md) +- [Nx](./NX.md) +- [Subman](./PODMAN.md) +- [Referenties](./REFERENCES.md) +- [Vereisten](./REQUIREMENTS.md) +- [Telemetrie](./TELEMETRY.md) + +**Executive Summary** + +Tekst + +Generated with [Ritr](https://app.rytr.me) + +## 100 - Inleiding + +See [README.md](./100/README.md) + +## 200 - Vereisten + +Zien[README.md](./200/README.md) + +## 300 - onze applicatie bouwen + +Zien[README.md](./300/README.md) + +## 400 - Conclusie + +Zien[README.md](./400/README.md) diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..c7c3a90 --- /dev/null +++ b/README.rst @@ -0,0 +1,15 @@ +Readme +======================================= + +SLUGLINE + +Description + +https://github.com/vanHeemstraSystems/REPOSITORY_NAME + +Read-the-Docs + +- Read: https://vanheemstrasystems-REPOSITORY-NAME.readthedocs.io/en/latest/ + +- Manage (NEW): https://app.readthedocs.org/projects/vanheemstrasystems-REPOSITORY-NAME/ +- Manage (OLD): https://readthedocs.org/dashboard/ diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 0000000..3fd00e6 --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,39 @@ +repository-name + +# 存储库名称 + +> 板条 + +- [DNS](./DNS.md) +- [文档](./DOCUMENTATION.md) +- [词汇表](./GLOSSARY.md) +- [孵化](./HATCH.md) +- [主持人](./HOSTS.md) +- [图像](./IMAGES.md) +- [nx](./NX.md) +- [Subman](./PODMAN.md) +- [参考](./REFERENCES.md) +- [要求](./REQUIREMENTS.md) +- [遥测](./TELEMETRY.md) + +**执行摘要** + +文本 + +生成[ritr](https://app.rytr.me) + +## 100-简介 + +看[README.md](./100/README.md) + +## 200-要求 + +看[README.md](./200/README.md) + +## 300 - Building Our Application + +看[README.md](./300/README.md) + +## 400-结论 + +看[README.md](./400/README.md) diff --git a/README.zh-TW.md b/README.zh-TW.md new file mode 100644 index 0000000..3cbe695 --- /dev/null +++ b/README.zh-TW.md @@ -0,0 +1,39 @@ +repository-name + +# 存儲庫名稱 + +> 板條 + +- [DNS](./DNS.md) +- [文件](./DOCUMENTATION.md) +- [詞彙表](./GLOSSARY.md) +- [孵化](./HATCH.md) +- [主持人](./HOSTS.md) +- [圖像](./IMAGES.md) +- [nx](./NX.md) +- [Subman](./PODMAN.md) +- [參考](./REFERENCES.md) +- [要求](./REQUIREMENTS.md) +- [遙測](./TELEMETRY.md) + +**執行摘要** + +文字 + +生成[ritr](https://app.rytr.me) + +## 100-簡介 + +看[README.md](./100/README.md) + +## 200-要求 + +看[README.md](./200/README.md) + +## 300-構建我們的應用程序 + +看[README.md](./300/README.md) + +## 400-結論 + +看[README.md](./400/README.md) diff --git a/REFERENCES.md b/REFERENCES.md new file mode 100644 index 0000000..2183999 --- /dev/null +++ b/REFERENCES.md @@ -0,0 +1,5 @@ +# References + +- [Reference Name](https://example.com) +- [RepoToText](https://github.com/GeekyGhost/RepoToText) +- [Building React Apps in an Nx Monorepo](https://nx.dev/getting-started/tutorials/react-monorepo-tutorial) diff --git a/REQUIREMENTS.md b/REQUIREMENTS.md new file mode 100644 index 0000000..ffb390e --- /dev/null +++ b/REQUIREMENTS.md @@ -0,0 +1,13 @@ +# Requirements + +- Hatch: simply run ```$ pip install hatch```.
+ Your output will look something like this: + ```... + Installing collected packages: trove-classifiers, zstandard, uv, tomli-w, shellingham, pluggy, pathspec, hyperlink, click, userpath, hatchling, hatch + Successfully installed click-8.1.7 hatch-1.13.0 hatchling-1.25.0 hyperlink-21.0.0 pathspec-0.12.1 pluggy-1.5.0 shellingham-1.5.4 tomli-w-1.1.0 trove-classifiers-2024.10.21.16 userpath-1.9.2 uv-0.4.26 zstandard-0.23.0 + ``` + +You can also install Hatch as an application on [Windows and Mac](https://hatch.pypa.io/latest/install/#installers) operating systems. [Conda](https://hatch.pypa.io/latest/install/#conda), [pipx](https://hatch.pypa.io/latest/install/#pipx), [Homebrew](https://hatch.pypa.io/latest/install/#homebrew), [MacPorts](https://hatch.pypa.io/latest/install/#macports), [Fedora](https://hatch.pypa.io/latest/install/#fedora), and [Void Linux](https://hatch.pypa.io/latest/install/#void-linux) installation methods are also available. + +We'll **not** add ```hatch``` to the ```requirements.txt``` file, as it is used purely to manage the development and build of the application but is not part of the aplication. + diff --git a/TELEMETRY.md b/TELEMETRY.md new file mode 100644 index 0000000..28dbe6a --- /dev/null +++ b/TELEMETRY.md @@ -0,0 +1,13 @@ +# Telemetry + +https://app.uptrace.dev/ + +To start sending tracing data to Uptrace, you need to configure OpenTelemetry Tracing SDK. To view and collect metrics, see the Metrics navigation section on the right. + +Use the following DSN to configure OpenTelemetry for your programming language: + +``` +export UPTRACE_DSN="https://4u5UnSF8ck63yJD33QZTrg@api.uptrace.dev?grpc=4317" +``` + +See [Monitor Flask performance with OpenTelemetry](https://uptrace.dev/get/instrument/opentelemetry-flask.html) diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..9534b01 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..53fc1f3 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,2 @@ +sphinx==7.1.2 +sphinx-rtd-theme==1.3.0rc1 diff --git a/docs/source/api.rst b/docs/source/api.rst new file mode 100644 index 0000000..5244001 --- /dev/null +++ b/docs/source/api.rst @@ -0,0 +1,7 @@ +API +=== + +.. autosummary:: + :toctree: generated + + PROJECT_NAME diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..a6a420c --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,35 @@ +# Configuration file for the Sphinx documentation builder. + +# -- Project information + +project = 'PROJECT_NAME' +copyright = '2024 - present, van Heemstra Systems' +author = 'Willem van Heemstra' + +release = '0.1' +version = '0.1.0' + +# -- General configuration + +extensions = [ + 'sphinx.ext.duration', + 'sphinx.ext.doctest', + 'sphinx.ext.autodoc', + 'sphinx.ext.autosummary', + 'sphinx.ext.intersphinx', +] + +intersphinx_mapping = { + 'python': ('https://docs.python.org/3/', None), + 'sphinx': ('https://www.sphinx-doc.org/en/master/', None), +} +intersphinx_disabled_domains = ['std'] + +templates_path = ['_templates'] + +# -- Options for HTML output + +html_theme = 'sphinx_rtd_theme' + +# -- Options for EPUB output +epub_show_urls = 'footnote' diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..6a1e131 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,22 @@ +Welcome to PROJECT_NAME's documentation! +=================================== + +**PROJECT_NAME** (/pro'ject/) is a NOUN for PURPOSE +that LIST_OF_FEATURES. +See EXTERNAL_RELATIONS at `LINK_TITLE `_ +and offers a *ADJECTIVE* and *ADJECTIVE* BENEFIT. + +Check out the :doc:`usage` section for further information, including +how to :ref:`installation` the project. + +.. note:: + + This project is under active development. + +Contents +-------- + +.. toctree:: + + usage + api diff --git a/docs/source/usage.rst b/docs/source/usage.rst new file mode 100644 index 0000000..f74c995 --- /dev/null +++ b/docs/source/usage.rst @@ -0,0 +1,33 @@ +Usage +===== + +.. _installation: + +Installation +------------ + +To use APPLICATION_NAME, first install it using pip: + +.. code-block:: console + + (.venv) $ pip install PACKAGE_NAME + +Getting Started +---------------- + +To retrieve a list of random ingredients, +you can use the ``PACKAGE_NAME.get_random_ingredients()`` function: + +.. autofunction:: PACKAGE_NAME.get_random_ingredients + +The ``kind`` parameter should be either ``"meat"``, ``"fish"``, +or ``"veggies"``. Otherwise, :py:func:`PACKAGE_NAME.get_random_ingredients` +will raise an exception. + +.. autoexception:: PACKAGE_NAME.InvalidKindError + +For example: + +>>> import PACKAGE_NAME +>>> PACKAGE_NAME.get_random_ingredients() +['shells', 'gorgonzola', 'parsley'] diff --git a/nx.json b/nx.json new file mode 100644 index 0000000..f871d63 --- /dev/null +++ b/nx.json @@ -0,0 +1,78 @@ +{ + "$schema": "./node_modules/nx/schemas/nx-schema.json", + "namedInputs": { + "default": ["{projectRoot}/**/*", "sharedGlobals"], + "nxCloudId": ["67a3831acafec34e47159841"], + "production": [ + "default", + "!{projectRoot}/.eslintrc.json", + "!{projectRoot}/eslint.config.mjs", + "!{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": ["{workspaceRoot}/.github/workflows/ci.yml"] + }, + "nxCloudId": "67b72b5c86db7789c5ca1378", + "plugins": [ + { + "plugin": "@nx/webpack/plugin", + "options": { + "buildTargetName": "build", + "serveTargetName": "serve", + "previewTargetName": "preview", + "buildDepsTargetName": "build-deps", + "watchDepsTargetName": "watch-deps" + } + }, + { + "plugin": "@nx/eslint/plugin", + "options": { + "targetName": "lint" + } + }, + { + "plugin": "@nx/playwright/plugin", + "options": { + "targetName": "e2e" + } + }, + { + "plugin": "@nx/jest/plugin", + "options": { + "targetName": "test" + } + } + ], + "targetDefaults": { + "e2e-ci--**/*": { + "dependsOn": ["^build"] + } + }, + "generators": { + "@nx/react": { + "application": { + "babel": true, + "style": "tailwind", + "linter": "eslint", + "bundler": "webpack" + }, + "component": { + "style": "tailwind" + }, + "library": { + "style": "tailwind", + "linter": "eslint" + } + } + }, + "projects": { + "hatch_project": { + "root": "hatch-project/src/hatch_project", + "sourceRoot": "hatch-project/src/hatch_project/src", + "projectType": "application" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..29f9013 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "replace-with-your-repository-name", + "version": "1.0.0", + "description": "", + "main": "index.js", + "directories": { + "doc": "docs" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Replace with your GitHub username", + "license": "ISC", + "devDependencies": { + "@nrwl/workspace": "^19.8.4", + "@nx/eslint": "^20.4.5", + "@nx/jest": "^20.4.5", + "@nx/playwright": "^20.4.5", + "@nx/react": "^20.4.5", + "@nx/webpack": "^20.4.5", + "nx": "^20.4.5", + "webpack-cli": "^6.0.1" + } +} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..8470b4e --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,8 @@ +[build-system] +requires = ["flit_core >=3.2,<4"] +build-backend = "flit_core.buildapi" + +[project] +name = "YOUR_PROJECT_NAME" +authors = [{name = "Willem van Heemstra", email = "wvanheemstra@icloud.com"}] +dynamic = ["version", "description"] diff --git a/schemas/.schemastore b/schemas/.schemastore new file mode 100644 index 0000000..e115e63 --- /dev/null +++ b/schemas/.schemastore @@ -0,0 +1 @@ +https://www.schemastore.org/ diff --git a/threagile.bat b/threagile.bat new file mode 100644 index 0000000..e55987c --- /dev/null +++ b/threagile.bat @@ -0,0 +1 @@ +docker run --rm -it -v %cd%:/app/work threagile/threagile %* diff --git a/threagile.sh b/threagile.sh new file mode 100644 index 0000000..6ebc25e --- /dev/null +++ b/threagile.sh @@ -0,0 +1,3 @@ +#!/bin/bash +sudo chmod a+rwx -R "$(pwd)" +docker run --rm -it -v "$(pwd)":/app/work threagile/threagile "$@" diff --git a/threagile.yaml b/threagile.yaml new file mode 100644 index 0000000..491170d --- /dev/null +++ b/threagile.yaml @@ -0,0 +1,3 @@ +threagile_version: 1.0.0 + +title: diff --git a/workspace.json b/workspace.json new file mode 100644 index 0000000..87715f8 --- /dev/null +++ b/workspace.json @@ -0,0 +1,10 @@ +{ + "version": 1, + "projects": { + "hatch_project": { + "root": "hatch-project/src/hatch_project", + "sourceRoot": "hatch-project/src/hatch_project/src", + "projectType": "application" + } + } +}