diff --git a/.devcontainer/multicontainer-node/devcontainer.json b/.devcontainer/multicontainer-node/devcontainer.json new file mode 100644 index 0000000..c556c95 --- /dev/null +++ b/.devcontainer/multicontainer-node/devcontainer.json @@ -0,0 +1,39 @@ +{ + "name": "Node Multi-Container", + "dockerComposeFile": ["../../docker-compose.yml"], + "service": "node-app", + "shutdownAction": "none", + "workspaceFolder": "/workspace/src/node", + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Configure tool-specific properties. + "customizations": { + // Configure properties specific to VS Code. + "vscode": { + "settings": {}, + "extensions": [ + "streetsidesoftware.code-spell-checker" + ] + } + }, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [3000], + + // Use 'portsAttributes' to set default properties for specific forwarded ports. + // More info: https://containers.dev/implementors/json_reference/#port-attributes + "portsAttributes": { + "3000": { + "label": "Hello Remote World", + "onAutoForward": "notify" + } + }, + + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "yarn install" + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/.devcontainer/multicontainer-python/devcontainer.json b/.devcontainer/multicontainer-python/devcontainer.json new file mode 100644 index 0000000..59cd7ca --- /dev/null +++ b/.devcontainer/multicontainer-python/devcontainer.json @@ -0,0 +1,39 @@ +{ + "name": "Python Multi-Container", + "dockerComposeFile": ["../../docker-compose.yml"], + "service": "python-api", + "shutdownAction": "none", + "workspaceFolder": "/workspace/src/python", + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Configure tool-specific properties. + "customizations": { + // Configure properties specific to VS Code. + "vscode": { + "settings": {}, + "extensions": [ + "streetsidesoftware.code-spell-checker" + ] + } + }, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [9000], + + // Use 'portsAttributes' to set default properties for specific forwarded ports. + // More info: https://containers.dev/implementors/json_reference/#port-attributes + "portsAttributes": { + "9000": { + "label": "Hello Remote World", + "onAutoForward": "notify" + } + }, + + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "pip3 install -r requirements.txt" + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/.markdownlint.json b/.markdownlint.json index 06ac46f..03c2167 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -1,5 +1,6 @@ { "default": true, + "MD013": false, "MD024": { "siblings_only": true }, "MD025": false, "MD033": false diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..488967a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,16 @@ +services: + python-api: + image: mcr.microsoft.com/devcontainers/python:1-3.12-bookworm + volumes: + # Mount the root folder that contains .git + - .:/workspace + command: sleep infinity + # ... + + node-app: + image: mcr.microsoft.com/devcontainers/typescript-node:1-20-bookworm + volumes: + # Mount the root folder that contains .git + - .:/workspace + command: sleep infinity + # ... diff --git a/slides/Slides.md b/slides/Slides.md index cbe0dba..f723f3d 100644 --- a/slides/Slides.md +++ b/slides/Slides.md @@ -1,11 +1,12 @@ +--- marp: true -theme: custom-default footer: '@Chris_L_Ayers - https://chris-ayers.com' +theme: custom-default --- # The Power of Dev Containers and GitHub Codespaces -### From Local Dev to Cloud Ready: Portable Environments with Dev Containers & Codespaces +## From Local Dev to Cloud Ready ## ![w:60px](./img/portrait.png) Chris Ayers @@ -25,462 +26,323 @@ footer: '@Chris_L_Ayers - https://chris-ayers.com' LinkedIn: - [chris\-l\-ayers](https://linkedin.com/in/chris-l-ayers/) Blog: [https://chris-ayers\.com/](https://chris-ayers.com/) GitHub: [Codebytes](https://github.com/codebytes) - Mastodon: @Chrisayers@hachyderm.io + Mastodon: [@Chrisayers@hachyderm.io](https://hachyderm.io/@Chrisayers) ~~ Twitter: @Chris_L_Ayers~~ --- # Agenda -- Prerequisites -- What Are Dev Containers? -- Why Use Dev Containers? -- How Dev Containers Work -- How to Build a Dev Container -- Templates, Features, Customization +- Why Dev Containers +- What They Are & How They Work +- Quick Start & Building +- Templates vs Features vs Customizations +- Core Concepts (Image vs Feature vs Template) - GitHub Codespaces - Demo - ---- - -# Prerequisites - -
-
- -## DevContainers - -- VSCode - - Dev Containers Extension - - GitHub Codespaces Extension -- IntelliJ IDEA - -
- -
- -## Docker - -- Docker installed locally -- Remote Docker host (optional for remote container execution) -- Other Docker compliant CLIs, installed locally or remotely - -
-
- -## GitHub Codespaces Requirement - -- GitHub Account -- GitHub Codespaces - -
+- Advanced: Security, Multi-Service, Prebuilds, Performance & Cost, Debug & Ports, Troubleshooting, Limits +- Resources & Q&A --- -# What are Dev Containers? +# Why Dev Containers? -- Environments that run in a container -- Containers that let you open or mount any folder and still use VS Code UI and tooling -- Places to run Apps, Tools, or Runtimes needed for a project or codebase -- [Containers.dev](https://containers.dev/) - An open specification for enriching containers with development specific content and settings. +- Onboard new contributors quickly +- Consistent tooling and versions for all developers +- Reduce system conflicts and "works on my machine" issues +- Secure, isolated environments for development +- Easy startup tasks and reproducible builds --- -
-
+# What Are Dev Containers? -# Why use Dev Containers? +- Containerized environments for development +- Let you open any folder in VS Code with all dependencies ready +- Run apps, tools, or runtimes needed for a project +- Based on the open [containers.dev](https://containers.dev/) specification -
-
+--- -- Onboard new People -- Use consistent tooling -- Use consistent versions -- Reduce System Conflicts -- Perform Startup Tasks - Improve security via isolation +# Prerequisites -
-
+- VS Code (Dev Containers extension, Codespaces extension) +- Docker (local or remote) +- GitHub account (for Codespaces) +- Optionally: IntelliJ IDEA, other containers CLIs like podman --- - +# How Dev Containers Work -# Inner and Outer Loops +Your editor talks to a containerized environment with all dependencies, keeping your local system clean. -![w:850px](img/inner-loop.png) +![Dev Containers center](img/architecture-containers.png) --- - +# Building a Dev Container -# How Dev Containers Work +From the Command Palette: -![Dev Containers](img/architecture-containers.png) - -Your editor talks to a containerized environment with all the dependencies, so your local system stays clean. +![Add Dev Container files w:850px center](./img/add-dev-containers-config.png) --- -# Where do Dev Containers Live? +# Templates, Features, Customizations -![devcontainer folder](img/dev-container-folder.png) +- Templates: project bootstrap (scaffold config) +- Features: add tools/runtimes (idempotent, versioned) +- Customizations: editor settings, extensions, startup tasks, port forwarding --- -# Multiple Dev Container Configurations - -Tooling supports multiple devcontainers. -Each one should be in its own subdirectory at: - -.devcontainer/SUBDIRECTORY/devcontainer.json. +# Image vs Feature vs Template -![bg right fit](img/multiple-devcontainers.png) +| Concept | When to Use | Change Frequency | Pinning Strategy | +|---------|-------------|------------------|------------------| +| Base Image | Need different language/runtime base or OS | Low | Tag (e.g. :1-20-bookworm) or digest | +| Feature | Add/upgrade a CLI (gh, kubectl), language, or utility | Medium | Major tag (node:1) or minor for guarantees | +| Template | Starting a new repo / adding devcontainer from scratch | One-off | Template version (commit / release) | --- -# How do you build a Dev Container? +# Principles & Practices -From the Command Pallet +Principles: +- Keep Dockerfile minimal; use Features for add-ons +- Templates are for initial setup, not ongoing changes +- Prebuild images for slow, shared setup (language servers, SDKs) -![Add Dev Container files w:850px](./img/add-dev-containers-config.png) +Practices: +- Everyone needs it & rarely changes? → Bake into image/Feature +- Project-scoped & changes often? → postCreateCommand +- Personal? → Dotfiles/Settings Sync --- -# Which Dev Container do I Pick? +# Managing Extensions Deep Dive -![Add Options](./img/dev-container-choices.png) +- Add via customizations.vscode.extensions +- Opt-out: prefix with '-' to remove inherited extension +- Default extensions (user setting): dev.containers.defaultExtensions +- Force location (rare): remote.extensionKind overrides +- Keep lean: only language / tooling essentials; reduces startup & index time --- -# Templates +# Extensions Example -Full List: [https://containers.dev/templates](https://containers.dev/templates) - -- Base (Alpine, Debian, Ubuntu) -- Language Based (C#, C++, Java, Go, Node, Python, Rust, Ruby, PHP) -- Tool Focused (Markdown, Kubernetes, Docker, Jekyll) +```json +"customizations": { + "vscode": { + "extensions": [ + "ms-azuretools.vscode-docker", + "-dbaeumer.vscode-eslint" // opt-out inherited + ] + } +} +``` --- -# Customizations +# Port Forwarding -- Features - Install tools into the container image. -- Extensions - Install extensions for the editor inside the container. -- Settings - Configure the editor settings inside the container. -- Startup Tasks - Run commands when the container starts. -- Networking - Port Forwarding - Expose ports to the host. +- Auto port detection: output parsing ("Listening on 3000") triggers forward suggestion +- forwardPorts: auto-forward on start; portsAttributes: label, onAutoForward, visibility +- Published vs Forwarded: + - Forwarded: appears as localhost to app (ideal for dev auth flows) + - Published: network-accessible (team demos, external callbacks) +- Browser preview & automatic HTTPS upgrade (if dev server supports) --- +# Example portsAttributes -# Features - -Full list here: [https://containers.dev/features](https://containers.dev/features) - -- CLIs (azure, gh, gcp, aws) -- Tools (Terraform, kubernetes...) -- Runtimes (Node, Python, Go, Java, .NET, PHP, Ruby, Rust, C/C++, C#) +```json +"portsAttributes": { + "3000": { "label": "Web UI", "onAutoForward": "openBrowser" }, + "9229": { "label": "Node Inspector", "elevateIfNeeded": true } +} +``` --- -# Docker-in-Docker vs Docker-on-Docker - -- **Docker-in-Docker (DinD):** - - Runs its own Docker daemon inside the dev container - - Good for isolation and CI - - Slightly slower, more resource use +# Minimal devcontainer.json Example -- **Docker-on-Docker (DoD):** - - Shares host Docker socket (`/var/run/docker.sock`) - - Faster, but less isolated - - Not always available (e.g., Codespaces) +```json +{ + "image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bookworm", + "features": { + "ghcr.io/devcontainers/features/github-cli:1": {}, + "ghcr.io/devcontainers/features/node:1": { "version": "20" } + }, + "forwardPorts": [3000], + "customizations": { + "vscode": { + "extensions": ["dbaeumer.vscode-eslint", "ms-azuretools.vscode-docker"], + "settings": { "editor.formatOnSave": true } + } + }, + "postCreateCommand": "npm ci", + "remoteUser": "node" +} +``` --- -# Image Selection for Dev Containers +# Environment Variables in Dev Containers -- Use the official .NET 9 image for Aspire workloads -- Extend or use a custom Dockerfile for extra tools -- Most local dev: DoD is faster and simpler -- CI or Codespaces: DinD is safer and more portable +Set environment variables in `devcontainer.json`: -# Configuration Loop +```json +{ + "containerEnv": { "MY_ENV_VAR": "value" }, + "remoteEnv": { "API_TOKEN": "${localEnv:API_TOKEN}" } +} +``` -![Configuration Loop](img/configuration-loop.png) +- `containerEnv`: for all processes in the container +- `remoteEnv`: for the VS Code server and extensions --- -# GitHub Codespaces - -- Don't need to worry about Docker Desktop locally -- Access from VS Code Desktop, Browser, GitHub CLI, IntelliJ (JetBrains Gateway) -- Machine types: 2 -> 32 cores, 8 -> 128 GB RAM, 32 -> 128 GB storage (quota + plan dependent) -- Default universal base image when no config present -- Only Linux (x86_64) today; same environment regardless of local OS -- Prebuilds optionally warm caches & dependencies for faster start -- Spin up secure, disposable environments for PR reviews, experiments, onboarding - -# devcontainer.json – Core Anatomy +# Env Vars: Container vs Remote (Advanced) -Key properties (spec: containers.dev) - -- image | build : Base image or build definition -- features : Add runtime/tooling building blocks (OCI delivered) -- name , workspaceFolder , workspaceMount -- customizations.vscode : extensions, settings, commands -- forwardPorts , portsAttributes , appPort (publish) -- postCreateCommand | onCreateCommand (initial provisioning) -- postStartCommand (runs each container start) -- postAttachCommand (runs after editor attaches) -- updateContentCommand (runs when repo content changes / rebuild) -- remoteUser | containerUser , userEnvProbe -- containerEnv | remoteEnv (environment vars) -- runArgs , overrides (Compose), mounts (extra volumes / bind mounts) -- shutdownAction , hostRequirements (cpu/ram/storage expectations) - -Keep it minimal: prefer pre-built images + Features over large inline scripts. +- **containerEnv**: set at container start (Dockerfile, Compose, or devcontainer.json) +- **remoteEnv**: injected at attach time (user, secrets, paths) +- Use dynamic values: `${localEnv:VAR}` or `${containerWorkspaceFolder}` +- `userEnvProbe`: merge shell profile exports into remoteEnv ("loginShell", "interactiveShell", or "none") --- -# Lifecycle & Personalization - -- onCreateCommand / postCreateCommand : one-time setup (install deps) -- postStartCommand : after container starts (lightweight tasks) -- postAttachCommand : when editor connects (show tips, start watchers) -- updateContentCommand : react to repo content updates (regen code, build docs) -- Dotfiles repo (shell, aliases, tooling) auto-applied -- Settings Sync (VS Code) for editor preferences -- Extensions: add in customizations.vscode.extensions (use -ext.id to opt-out) -- Always install defaults via dev.containers.defaultExtensions / defaultFeatures +# Mounting Local Folders -Tip: Keep long-running tasks out of postStart to reduce initial readiness time. +You can mount local folders or files into your dev container using the `mounts` property: ---- - -# Advanced Configuration Highlights +```json +{ + "mounts": [ + "source=${localWorkspaceFolder}/.npmrc,target=/root/.npmrc,type=bind,consistency=cached", + "source=${env:HOME}/.ssh,target=/root/.ssh,type=bind,consistency=cached" + ] +} +``` -- Multi-container: docker-compose.yml + service property -- Mounts: bind, volume, tmpfs for caches (node_modules, package cache) -- portsAttributes: label, auto-open, visibility (public / private) -- hostRequirements: signal required resources for Codespaces selection -- remoteEnv vs containerEnv (apply after attach vs base container) -- Pre-built image metadata labels merge devcontainer settings -- Multiple configurations: .devcontainer//devcontainer.json choices -- Non-root user (features often add 'vscode' or 'devcontainer' user) for security +This is useful for sharing config files, SSH keys, or other resources from your host. --- -# Pre-building Images & Codespaces Prebuilds +# Non-Root User Best Practice + +Always run as a non-root user for security. Most official images set `remoteUser` to `vscode` or `devcontainer` by default. -- Pre-build (CI) container images to bake in deps, tools, language servers -- Use Dev Container CLI or devcontainers/ci GitHub Action -- Benefits: Faster startup, deterministic builds, pinned versions, supply chain traceability -- Include metadata labels (devcontainer.metadata) to auto-apply config -- Codespaces Prebuilds: run build + postCreate on default branches / PRs -- Reduces time-to-first-keystroke for large mono-repos -- Cache package managers (npm, pip, cargo, go mod) inside layer +To enforce non-root: +```json +{ + "remoteUser": "vscode" +} +``` +Or add the non-root-user Feature if needed. -Measure: Track median create time before/after prebuild adoption. +More: [Add a non-root user](https://code.visualstudio.com/remote/advancedcontainers/add-nonroot-user) --- -# Codespaces Personalization & Secrets -- Dotfiles repo: ~/.dotfiles (configurable target + install script) -- Settings Sync: unify keybindings, snippets, UI -- User-level secrets: injected as env vars; never commit secrets in devcontainer.json -- Repository / Org secrets for workflows vs Codespaces user secrets separation -- Port forwarding: automatic detection (server output) + manual forward -- Shared terminals (pairing) & Live Share (optional) for collaboration -- GitHub CLI inside container simplifies auth & repo ops +# GitHub Codespaces: What & Why -Principle: Keep personal customization (dotfiles) separate from project config. +- Cloud-hosted, instant dev environments for any repo +- No local Docker or setup required +- Consistent, secure, and disposable workspaces +- Fast onboarding: prebuilds, dotfiles, and settings sync --- -# Performance Tips -- Prefer pre-built images + Features over large postCreate scripts -- Use volumes instead of bind mounts for heavy I/O on macOS/Windows -- Cache language deps in image layers (lock files first for better cache hits) -- Trim image size: multi-stage builds, remove build toolchains in final stage -- Avoid unnecessary apt-get upgrade; pin versions -- Use updateContentCommand only for light incremental tasks -- Rebuild when changing Dockerfile; use Reopen in Recovery Container to fix build errors fast +# GitHub Codespaces: Architecture -Metric to watch: Codespaces create time (goal: < 30s perceived ready). +![center w:620px](img/codespaces.png) --- -# Security Best Practices -- Non-root user (remoteUser) with least privileges -- Pin image tags (avoid :latest) & verify supply chain (SBOM where possible) -- Minimal Feature set: install only required tools -- Regularly rebuild to pick up CVE patches (automated CI scan) -- Secrets via Codespaces secrets; never bake into image layers -- Consider readonly mounts for source during audits / review sessions -- Use Dependabot / container scanning for base image & dependencies +# Codespaces: Key Features -Outcome: Reproducible, auditable, least-privilege environments. +- Start a dev environment from any branch, PR, or template +- Prebuilds: dependencies and tools ready before you connect +- Port forwarding, shared terminals, and Live Share for collaboration +- Personalization: dotfiles, settings sync, user secrets --- -# Known Limitations & Constraints -- Codespaces: Linux only (no Windows/macOS containers) -- Architecture: x86_64 (arm64 building requires remote emulation or CI build) -- Dev Containers: Windows container images not supported in VS Code extension -- Alpine images: some extensions fail (glibc expectations) -- Multi-root workspace: single container context (unless Compose multi-service) -- Network: corporate proxies require explicit HTTP(S)_PROXY env vars -- Performance: bind mounts slower on macOS/Windows; prefer volumes +# Codespaces: How to Use -Plan mitigations early (prebuild, volumes, pinned tool versions). +- Open any repo in a codespace from GitHub.com, VS Code, or CLI +- Choose machine size, region, and devcontainer config +- Suspend, resume, or delete codespaces as needed +- Works with VS Code (browser/desktop), JetBrains Gateway, and GitHub CLI --- -# GitHub Codespaces Architecture +# Codespaces: Limitations & Cost - - -![w:750px](img/codespaces.png) +- Linux-only (x86_64); no Windows containers +- Single container unless using Compose +- Bind mounts slower on macOS/Windows (prefer volumes) +- Pay for compute, storage, and prebuilds (beyond free quota) +- See [docs.github.com/codespaces](https://docs.github.com/en/codespaces/) for details --- -# GitHub Codespace templates - -[https://github.com/codespaces/templates](https://github.com/codespaces/templates) +# GitHub Codespaces: Billing & Cost Control -![bg right:60% width:95%](img/github-codespace-templates.png) +- Pay for compute hours, storage, and prebuild usage (beyond free quota) +- Key levers: machine size, idle timeout, auto-delete unused codespaces +- Strategies: right-size, prebuild only critical branches, monitor usage/cost +- Always check current docs for pricing details --- -# DEMO TIME +# Demo Time ![bg right 70%](img/connected-to-dev-container.png) --- -![bg](img/questions.jpg) +# Advanced Topics --- -# Codespaces Billing & Cost Control - -- Billing dimensions: compute hours (core/hour), storage (persistent disk), prebuild usage -- Free included quota varies by plan; beyond that pay-as-you-go with budgets/spending limits -- Cost levers: machine type, idle timeout, automatic deletion of unused codespaces -- Strategies: - - Right-size: start small, scale up only when tests / builds need it - - Prebuild only critical branches (main, release/*, high-traffic PRs) - - Pause / stop vs delete (stop retains storage; delete frees cost) - - Archive artifacts externally (cache warm vs extra storage) -- Monitor: Usage dashboard + budget alerts; treat create time & cost per PR as KPIs - -Note: Exact pricing subject to change—always verify current docs before presenting numbers. - ---- +# Dev Container CLI -# Workspace Trust & Safety +The `devcontainer` CLI lets you build, run, and automate dev containers from the terminal—no VS Code required. -- First open: VS Code prompts to Trust repository (controls auto-exec of tasks, extensions) -- Trust decisions propagate to container actions (build, postCreate scripts) -- Recovery container: safe mode to fix failing builds without executing untrusted scripts -- Recommendations: - - Review Dockerfile & scripts before trusting third-party repos - - Pin base images & Features; avoid curl | bash patterns without checksum - - Use readonly mounts for exploration when uncertain +- `devcontainer build --workspace-folder .`   Build a dev container image +- `devcontainer up --workspace-folder .`   Start a dev container +- `devcontainer exec --workspace-folder . bash -lc "npm test"`   Run a command inside -Outcome: Minimize supply chain risk while preserving inner-loop speed. +[github.com/devcontainers/cli](https://github.com/devcontainers/cli) --- -# Managing Extensions Deep Dive - -- Add via customizations.vscode.extensions -- Opt-out: prefix with '-' to remove inherited extension -- Default extensions (user setting): dev.containers.defaultExtensions -- Force location (rare): remote.extensionKind overrides -- Keep lean: only language / tooling essentials; reduces startup & index time -- Example: - -``` -"customizations": { - "vscode": { - "extensions": [ - "ms-azuretools.vscode-docker", - "-dbaeumer.vscode-eslint" // opt-out inherited - ] - } -} -``` - ---- - -# Debugging & Port Forwarding - -- Debug flows identical: launch.json attaches inside container -- Auto port detection: output parsing ("Listening on 3000") triggers forward suggestion -- forwardPorts: auto-forward on start; portsAttributes: label, onAutoForward, visibility -- Published vs Forwarded: - - Forwarded: appears as localhost to app (ideal for dev auth flows) - - Published: network-accessible (team demos, external callbacks) -- Browser preview & automatic HTTPS upgrade (if dev server supports) - -Example portsAttributes: -``` -"portsAttributes": { - "3000": { "label": "Web UI", "onAutoForward": "openBrowser" }, - "9229": { "label": "Node Inspector", "elevateIfNeeded": true } -} -``` - ---- +# Prebuild & CI Integration Example -# Minimal devcontainer.json Example +devcontainer.json (simplified): -``` +```json { - "image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bookworm", - "features": { - "ghcr.io/devcontainers/features/github-cli:1": {}, - "ghcr.io/devcontainers/features/node:1": { "version": "20" } - }, - "forwardPorts": [3000], - "customizations": { - "vscode": { - "extensions": ["dbaeumer.vscode-eslint", "ms-azuretools.vscode-docker"], - "settings": { "editor.formatOnSave": true } - } - }, - "postCreateCommand": "npm ci", - "remoteUser": "node" + "image": "ghcr.io/your-org/your-prebuilt:latest", + "postAttachCommand": "npm run dev" } ``` --- -# Prebuild & CI Integration Example +# Prebuild CI Workflow (GitHub Actions) -devcontainer.json (simplified): -``` -{ - "image": "ghcr.io/your-org/your-prebuilt:latest", - "postAttachCommand": "npm run dev" -} -``` -GitHub Action (devcontainers/ci): -``` +```yaml name: Prebuild Dev Container on: push: @@ -503,43 +365,23 @@ jobs: --- -# Multi-Service (Compose) Pattern +# Tips & Tricks: Git Line Endings (Windows/WSL) -- docker-compose.yml defines api, db, cache, worker services -- devcontainer.json references primary service: "service": "api" -- Shared network: service hostnames = service names (db:5432) -- volumes: persist database state or ephemeral for clean tests -- Add Features only to dev container service; others use minimal images -- Tip: Use HEALTHCHECK for dependent service readiness (faster stabilize) +On Windows/WSL, you may see many modified files due to line ending differences between host and container. -Flow: Editor -> api container (extensions) -> other services via internal network. +- Add a `.gitattributes` file to enforce consistent line endings: ---- - -# Metrics & Continuous Improvement - -Track: -- Time to first keystroke (creation start -> editor ready) -- PostCreate duration (optimize by prebuilding layers) -- Container image size & layer churn -- Cache hit rate for package managers -- Codespaces cost per PR (optional) - -Improve Loop: -1 Measure -> 2 Identify slow stage -> 3 Shift left into image -> 4 Validate -> 5 Automate. +```gitattributes +* text=auto eol=lf +*.{cmd,[cC][mM][dD]} text eol=crlf +*.{bat,[bB][aA][tT]} text eol=crlf +``` --- # Troubleshooting & Recovery -- Build fails: Reopen in Recovery Container -> fix Dockerfile -> Rebuild -- Slow startup: inspect logs (Dev Containers output), compare against prebuild baseline -- Missing tools: confirm Features applied (metadata labels vs local file) -- Port conflict: adjust forwardPorts or use random host mapping -- Extension issues: run with --log-level trace, temporarily disable customizations -- Disk performance (macOS/Windows): prefer volume (Clone in Container Volume) - -Mindset: Fail fast, keep recovery path frictionless. +![center fit](img/configuration-loop.png) --- @@ -556,9 +398,7 @@ Mindset: Fail fast, keep recovery path frictionless. - [Beginner's Series to Dev Containers](https://learn.microsoft.com/en-us/shows/beginners-series-to-dev-containers/) - [devcontainer.json Reference](https://containers.dev/implementors/json_reference) - [Dev Container CLI](https://code.visualstudio.com/docs/devcontainers/devcontainer-cli) -- [Prebuilds (GitHub Codespaces)](https://docs.github.com/codespaces) - [Advanced Config (VS Code)](https://code.visualstudio.com/remote/advancedcontainers/overview) -- [https://github.com/codebytes](https://github.com/codebytes)
diff --git a/src/go/.devcontainer/devcontainer.json b/src/go/.devcontainer/devcontainer.json new file mode 100644 index 0000000..c9ac758 --- /dev/null +++ b/src/go/.devcontainer/devcontainer.json @@ -0,0 +1,39 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/go +{ + "name": "Go", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/go:1-1.22-bookworm", + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Configure tool-specific properties. + "customizations": { + // Configure properties specific to VS Code. + "vscode": { + "settings": {}, + "extensions": [ + "streetsidesoftware.code-spell-checker" + ] + } + }, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [9000], + + // Use 'portsAttributes' to set default properties for specific forwarded ports. + // More info: https://containers.dev/implementors/json_reference/#port-attributes + "portsAttributes": { + "9000": { + "label": "Hello Remote World", + "onAutoForward": "notify" + } + } + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "go version", + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/src/go/.gitattributes b/src/go/.gitattributes new file mode 100644 index 0000000..314766e --- /dev/null +++ b/src/go/.gitattributes @@ -0,0 +1,3 @@ +* text=auto eol=lf +*.{cmd,[cC][mM][dD]} text eol=crlf +*.{bat,[bB][aA][tT]} text eol=crlf diff --git a/src/go/.gitignore b/src/go/.gitignore new file mode 100644 index 0000000..d121356 --- /dev/null +++ b/src/go/.gitignore @@ -0,0 +1,336 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +*.DS_Store + +out +pkg +debug diff --git a/src/go/.vscode/launch.json b/src/go/.vscode/launch.json new file mode 100644 index 0000000..01f10d4 --- /dev/null +++ b/src/go/.vscode/launch.json @@ -0,0 +1,12 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Server", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "${workspaceFolder}/server.go" + } + ] +} diff --git a/src/go/go.mod b/src/go/go.mod new file mode 100644 index 0000000..fe93d39 --- /dev/null +++ b/src/go/go.mod @@ -0,0 +1,3 @@ +module github.com/microsoft/vscode-remote-try-go + +go 1.19 diff --git a/src/go/hello/hello.go b/src/go/hello/hello.go new file mode 100644 index 0000000..db44cd1 --- /dev/null +++ b/src/go/hello/hello.go @@ -0,0 +1,22 @@ +package hello + +// User user type +type User struct { + ID int64 + Name string + Addr *Address +} + +// Address address type +type Address struct { + City string + ZIP int + LatLng [2]float64 +} + +var alex = User{} + +// Hello writes a welcome string +func Hello() string { + return "Hello, " + alex.Name +} diff --git a/src/go/server.go b/src/go/server.go new file mode 100644 index 0000000..28dbdb4 --- /dev/null +++ b/src/go/server.go @@ -0,0 +1,25 @@ +/*---------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE in the project root for license information. + *---------------------------------------------------------------------------------------*/ + +package main + +import ( + "fmt" + "io" + "net/http" + + "github.com/microsoft/vscode-remote-try-go/hello" +) + +func handle(w http.ResponseWriter, r *http.Request) { + io.WriteString(w, hello.Hello()) +} + +func main() { + portNumber := "9000" + http.HandleFunc("/", handle) + fmt.Println("Server listening on port ", portNumber) + http.ListenAndServe(":"+portNumber, nil) +} diff --git a/src/node/.eslintrc.json b/src/node/.eslintrc.json new file mode 100644 index 0000000..6144597 --- /dev/null +++ b/src/node/.eslintrc.json @@ -0,0 +1,21 @@ +{ + "root": true, + "env": { + "node": true, + "es6": true + }, + "rules": { + "no-console": 0, + "eqeqeq":"warn", + "no-cond-assign": 0, + "no-unused-vars": 1, + "no-extra-semi": "warn", + "semi": "warn" + }, + "extends": "eslint:recommended", + "parserOptions": { + "ecmaFeatures": { + "experimentalObjectRestSpread": true + } + } +} diff --git a/src/node/.gitattributes b/src/node/.gitattributes new file mode 100644 index 0000000..314766e --- /dev/null +++ b/src/node/.gitattributes @@ -0,0 +1,3 @@ +* text=auto eol=lf +*.{cmd,[cC][mM][dD]} text eol=crlf +*.{bat,[bB][aA][tT]} text eol=crlf diff --git a/src/node/.gitignore b/src/node/.gitignore new file mode 100644 index 0000000..1aae53a --- /dev/null +++ b/src/node/.gitignore @@ -0,0 +1,334 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +*.DS_Store + +out \ No newline at end of file diff --git a/src/node/.vscode/launch.json b/src/node/.vscode/launch.json new file mode 100644 index 0000000..179ed34 --- /dev/null +++ b/src/node/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "program": "${workspaceFolder}/server.js" + } + ] +} \ No newline at end of file diff --git a/src/node/package.json b/src/node/package.json new file mode 100644 index 0000000..c52b0e2 --- /dev/null +++ b/src/node/package.json @@ -0,0 +1,14 @@ +{ + "name": "docker_web_app", + "version": "1.0.0", + "description": "Node.js on Docker", + "author": "First Last ", + "main": "server.js", + "private": true, + "scripts": { + "start": "node server.js" + }, + "dependencies": { + "express": "^4.20.0" + } +} diff --git a/src/node/server.js b/src/node/server.js new file mode 100644 index 0000000..6de36ad --- /dev/null +++ b/src/node/server.js @@ -0,0 +1,28 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +const express = require('express'); + +// Constants +const PORT = 3000; +const HOST = '0.0.0.0'; + +// App +const app = express(); +app.get('/', (req, res) => { + res.send('Hello remote world!\n'); +}); + +// New endpoint: GET /hello?name=YOUR_NAME -> "hello YOUR_NAME" +app.get('/hello', (req, res) => { + const nameParam = req.query && typeof req.query.name === 'string' ? req.query.name.trim() : ''; + const name = nameParam.length > 0 ? nameParam : 'world'; + res.send(`hello ${name}\n`); +}); + +app.listen(PORT, HOST); +console.log(`Running on http://${HOST}:${PORT}`); \ No newline at end of file diff --git a/src/node/yarn.lock b/src/node/yarn.lock new file mode 100644 index 0000000..1a2f702 --- /dev/null +++ b/src/node/yarn.lock @@ -0,0 +1,468 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +body-parser@1.20.3: + version "1.20.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" + integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g== + dependencies: + bytes "3.1.2" + content-type "~1.0.5" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.13.0" + raw-body "2.5.2" + type-is "~1.6.18" + unpipe "1.0.0" + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4, content-type@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9" + integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w== + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +encodeurl@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== + +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +express@^4.20.0: + version "4.21.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.21.1.tgz#9dae5dda832f16b4eec941a4e44aa89ec481b281" + integrity sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.3" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.7.1" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~2.0.0" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.3.1" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.3" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.10" + proxy-addr "~2.0.7" + qs "6.13.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.19.0" + serve-static "1.16.2" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +finalhandler@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019" + integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ== + dependencies: + debug "2.6.9" + encodeurl "~2.0.0" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== + +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +hasown@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +inherits@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +merge-descriptors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" + integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +object-inspect@^1.13.1: + version "1.13.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" + integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +path-to-regexp@0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz#67e9108c5c0551b9e5326064387de4763c4d5f8b" + integrity sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w== + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +qs@6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" + integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== + dependencies: + side-channel "^1.0.6" + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +safe-buffer@5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +send@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" + integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serve-static@1.16.2: + version "1.16.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" + integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw== + dependencies: + encodeurl "~2.0.0" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.19.0" + +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== diff --git a/src/python/.gitattributes b/src/python/.gitattributes new file mode 100644 index 0000000..314766e --- /dev/null +++ b/src/python/.gitattributes @@ -0,0 +1,3 @@ +* text=auto eol=lf +*.{cmd,[cC][mM][dD]} text eol=crlf +*.{bat,[bB][aA][tT]} text eol=crlf diff --git a/src/python/.gitignore b/src/python/.gitignore new file mode 100644 index 0000000..9787daf --- /dev/null +++ b/src/python/.gitignore @@ -0,0 +1,332 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +*.DS_Store diff --git a/src/python/.vscode/launch.json b/src/python/.vscode/launch.json new file mode 100644 index 0000000..bed8fa4 --- /dev/null +++ b/src/python/.vscode/launch.json @@ -0,0 +1,27 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Flask", + "type": "python", + "request": "launch", + "module": "flask", + "env": { + "FLASK_APP": "app.py", + "FLASK_ENV": "development", + "FLASK_DEBUG": "0" + }, + "args": [ + "run", + "--host","0.0.0.0", + "--port","9000", + "--no-debugger", + "--no-reload" + ], + "jinja": true + } + ] +} \ No newline at end of file diff --git a/src/python/app.py b/src/python/app.py new file mode 100644 index 0000000..8c27ec7 --- /dev/null +++ b/src/python/app.py @@ -0,0 +1,11 @@ +#----------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See LICENSE in the project root for license information. +#----------------------------------------------------------------------------------------- + +from flask import Flask +app = Flask(__name__) + +@app.route("/") +def hello(): + return app.send_static_file("index.html") diff --git a/src/python/requirements.txt b/src/python/requirements.txt new file mode 100644 index 0000000..8ab6294 --- /dev/null +++ b/src/python/requirements.txt @@ -0,0 +1 @@ +flask \ No newline at end of file diff --git a/src/python/static/index.html b/src/python/static/index.html new file mode 100644 index 0000000..ea0d532 --- /dev/null +++ b/src/python/static/index.html @@ -0,0 +1,9 @@ + + + VS Code Rocks! + + +

VS Code can do that?

+

Yes it can!

+ + \ No newline at end of file