diff --git a/.github/workflows/closed.yml b/.github/workflows/closed.yml deleted file mode 100644 index 9e69ded..0000000 --- a/.github/workflows/closed.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Cleanup Branch - -on: - pull_request: - types: [ closed ] - -permissions: - contents: read - -jobs: - delete: - runs-on: ubuntu-latest - steps: - - uses: snnaplab/delete-branch-cache-action@v1 - with: - # Specify explicitly because the ref at the time of merging will be a branch name such as 'main', 'develop' - ref: refs/pull/${{ github.event.number }}/merge diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..618c6c8 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,41 @@ +name: Publish docs + +on: + push: + tags: + - v*.*.* + workflow_dispatch: + +permissions: + pages: write + contents: write + id-token: write + +jobs: + docs: + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - uses: actions/checkout@v6 + + - uses: oven-sh/setup-bun@v2 + + - name: Install dependencies + working-directory: docs + run: bun install --frozen-lockfile + + - name: Build docs + working-directory: docs + run: bun run build + + - uses: actions/configure-pages@v6 + + - uses: actions/upload-pages-artifact@v5 + with: + path: docs/.vitepress/dist + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v5 diff --git a/.gitignore b/.gitignore index c7e23f7..6c46621 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,9 @@ tmp/ ## Vitepress !docs/.vitepress +docs/.vitepress/* +!docs/.vitepress/theme/ +!docs/.vitepress/config.mts ## Golang go.work diff --git a/.goreleaser.yaml b/.goreleaser.yaml index fd5bf2d..43d3d08 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -4,7 +4,7 @@ project_name: squadron builds: - binary: squadron - main: ./cmd/main.go + main: ./cmd/squadron env: - CGO_ENABLED=0 flags: @@ -12,7 +12,7 @@ builds: - -tags=safe ldflags: - -s -w - - -X github.com/foomo/squadron/cmd/actions.version={{.Version}} + - -X github.com/foomo/squadron/internal/cli.version={{.Version}} goos: - windows - darwin diff --git a/Makefile b/Makefile index 7897095..34633ba 100644 --- a/Makefile +++ b/Makefile @@ -88,13 +88,13 @@ test.update: build: @mkdir -p bin @echo "〉building bin/squadron" - @go build -tags=safe -o bin/squadron cmd/main.go + @go build -tags=safe -o bin/squadron ./cmd/squadron .PHONY: install ## Install binary install: @echo "〉installing ${GOPATH}/bin/squadron" - @go build -tags=safe -o ${GOPATH}/bin/squadron cmd/main.go + @go build -tags=safe -o ${GOPATH}/bin/squadron ./cmd/squadron ### Security @@ -140,7 +140,7 @@ docs: docs.cli ## Generate cli docs.cli: @echo "〉generating cli reference" - @go run scripts/cmd-reference/main.go + @go run ./cmd/squadron-docs .PHONY: godocs ## Open go docs diff --git a/README.md b/README.md index afff790..01af9fe 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@ -[](https://github.com/foomo/squadron/releases) -[](https://github.com/foomo/squadron/releases) -[](https://hub.docker.com/r/foomo/squadron) -[](https://github.com/foomo/squadron) -[](https://goreportcard.com/report/github.com/foomo/squadron) -[](https://godoc.org/github.com/foomo/squadron) +[](https://goreportcard.com/report/github.com/foomo/squadron) +[](https://godoc.org/github.com/foomo/squadron) +[](https://github.com/foomo/squadron/releases) +[](https://hub.docker.com/r/foomo/squadron) +[](https://github.com/foomo/squadron)
@@ -11,125 +10,56 @@
# Squadron
-Application for managing kubernetes microservice environments.
+**Docker Compose for Kubernetes.**
-Use it, if a helm chart is not enough in order to organize multiple services into an effective squadron.
+Squadron is a CLI that orchestrates multiple Helm charts and Docker image builds
+as one cohesive deployment, driven by a single declarative `squadron.yaml`. It
+brings the familiar `docker-compose` workflow — define your services once, bring
+the whole stack up with one command — to Kubernetes, where each service is a real
+Helm release. In production, a squadron is just another set of Helm charts.
-Another way to think of it would be `helm-compose`, because it makes k8s and helm way more approachable, not matter if it is development or production (where it just becomes another helm chart)
+📖 **[Read the documentation →](https://foomo.github.io/squadron)**
-## Configuration `squadron.yaml`
-
-Configure your squadron
-
-```yaml
-# https://raw.githubusercontent.com/foomo/squadron/refs/heads/main/squadron.schema.json
-version: '2.3'
-
-# squadron template vars
-vars: {}
-
-# helm global vars
-global: {}
-
-# squadron definitions
-squadron:
- # squadron units
- site:
- # squadron unit
- frontend:
- # optional release name override
- name: my-frontend
- # optional release namespace override
- namespace: my-namespace
- # helm chart definition
- chart:
- name: mychart
- version: 0.1.0
- repository: http://helm.mycompany.com/repository
- # container bakes
- bakes:
- service:
- tags:
- - docker.mycompany.com/mycomapny/frontend:latest
- dockerfile: Dockerfile
- args:
- foo: foo
- bar: bar
- # container builds
- builds:
- service:
- tag: latest
- file: Dockerfile
- image: docker.mycompany.com/mycomapny/frontend
- build_arg:
- - "foo=foo"
- - "bar=bar"
- # helm chart values
- values:
- image: docker.mycompany.com/mycomapny/frontend:latest
- # squadron unit
- backend:
- # helm chart definition
- chart: <% env "PROJECT_ROOT" %>/path/to/chart
- # kustomize path
- kustomize: <% env "PROJECT_ROOT" %>/path/to/kustomize
- # container bakes
- bakes:
- service:
- tags:
- - docker.mycompany.com/mycomapny/backend:latest
- dockerfile: Dockerfile
- args:
- foo: foo
- bar: bar
- # container builds
- builds:
- service:
- tag: latest
- file: Dockerfile
- image: docker.mycompany.com/mycomapny/backend
- build_arg:
- - "foo=foo"
- - "bar=bar"
- # helm chart values
- values:
- image: docker.mycompany.com/mycomapny/backend:latest
-```
-
-## Usage
+## Install
```shell
-$ squadron help
-Docker compose for kubernetes
-
-Usage:
- squadron [command]
-
-Available Commands:
- bake bake or rebake squadron units
- build build or rebuild squadron units
- completion Generate completion script
- config generate and view the squadron config
- diff shows the diff between the installed and local chart
- down uninstalls the squadron or given units
- help Help about any command
- list list squadron units
- push pushes the squadron or given units
- rollback rolls back the squadron or given units
- schema generate squadron json schema
- status installs the squadron or given units
- template render chart templates locally and display the output
- up installs the squadron or given units
- version show version information
-
-Flags:
- -d, --debug show all output
- -f, --file strings specify alternative squadron files (default [squadron.yaml])
- -h, --help help for squadron
-
-Use "squadron [command] --help" for more information about a command.
+go install github.com/foomo/squadron/cmd/squadron@latest
```
+See the [installation guide](https://foomo.github.io/squadron/guide/installation)
+for release binaries and the Docker image.
+
+## Example
+
+```yaml
+# squadron.yaml
+version: '2.3'
+squadron:
+ storefinder:
+ backend:
+ chart: <% env "PROJECT_ROOT" %>/charts/backend
+ builds:
+ default:
+ image: docker.mycompany.com/storefinder/backend
+ tag: latest
+ context: ./app
+ values:
+ image:
+ repository: <% .Squadron.storefinder.backend.builds.default.image %>
+ tag: <% .Squadron.storefinder.backend.builds.default.tag | quote %>
+```
+
+```shell
+squadron build # build the images
+squadron up # install / upgrade the releases
+squadron status # check release status
+squadron down # tear it down
+```
+
+See the [Quick Start](https://foomo.github.io/squadron/guide/quickstart) and the
+[configuration reference](https://foomo.github.io/squadron/guide/configuration)
+for the full picture.
+
## How to Contribute
Contributions are welcome! Please read the [contributing guide](docs/CONTRIBUTING.md).
diff --git a/_examples/helloworld/Makefile b/_examples/helloworld/Makefile
index 10c5b3b..95a5e93 100644
--- a/_examples/helloworld/Makefile
+++ b/_examples/helloworld/Makefile
@@ -7,22 +7,22 @@ export PROJECT_ROOT=$(PWD)
.PHONY: list
## Show config
list:
- @go run ../../cmd/main.go list
+ @go run ../../cmd/squadron list
.PHONY: config
## Show config
config:
- @go run ../../cmd/main.go config
+ @go run ../../cmd/squadron config
.PHONY: build
## Show config
build:
- @go run ../../cmd/main.go build
+ @go run ../../cmd/squadron build
.PHONY: template
## Show config
template:
- @go run ../../cmd/main.go template
+ @go run ../../cmd/squadron template
## === Utils ===
diff --git a/_examples/kustomize/Makefile b/_examples/kustomize/Makefile
index 10c5b3b..95a5e93 100644
--- a/_examples/kustomize/Makefile
+++ b/_examples/kustomize/Makefile
@@ -7,22 +7,22 @@ export PROJECT_ROOT=$(PWD)
.PHONY: list
## Show config
list:
- @go run ../../cmd/main.go list
+ @go run ../../cmd/squadron list
.PHONY: config
## Show config
config:
- @go run ../../cmd/main.go config
+ @go run ../../cmd/squadron config
.PHONY: build
## Show config
build:
- @go run ../../cmd/main.go build
+ @go run ../../cmd/squadron build
.PHONY: template
## Show config
template:
- @go run ../../cmd/main.go template
+ @go run ../../cmd/squadron template
## === Utils ===
diff --git a/_examples/monorepo/Makefile b/_examples/monorepo/Makefile
index 259e4e3..56794e2 100644
--- a/_examples/monorepo/Makefile
+++ b/_examples/monorepo/Makefile
@@ -9,22 +9,22 @@ files=$(shell find . -name 'squadron.yaml' | tail -r | xargs echo -n | tr " ", "
.PHONY: list
## Show config
list:
- @go run ../../cmd/main.go -f ${files} list --builds --charts
+ @go run ../../cmd/squadron -f ${files} list --builds --charts
.PHONY: config
## Show config
config:
- @go run ../../cmd/main.go -f ${files} config
+ @go run ../../cmd/squadron -f ${files} config
.PHONY: build
## Show config
build:
- @go run ../../cmd/main.go -f ${files} build
+ @go run ../../cmd/squadron -f ${files} build
.PHONY: template
## Show config
template:
- @go run ../../cmd/main.go -f ${files} template
+ @go run ../../cmd/squadron -f ${files} template
## === Utils ===
diff --git a/biome.json b/biome.json
index b853d0e..aa6e469 100644
--- a/biome.json
+++ b/biome.json
@@ -18,7 +18,10 @@
"linter": {
"enabled": true,
"rules": {
- "recommended": true
+ "recommended": true,
+ "complexity": {
+ "noImportantStyles": "off"
+ }
}
},
"json": {
diff --git a/cmd/main.go b/cmd/main.go
deleted file mode 100644
index 0010cff..0000000
--- a/cmd/main.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package main
-
-import (
- "github.com/foomo/squadron/cmd/actions"
-)
-
-func main() {
- actions.Execute()
-}
diff --git a/scripts/cmd-reference/main.go b/cmd/squadron-docs/main.go
similarity index 92%
rename from scripts/cmd-reference/main.go
rename to cmd/squadron-docs/main.go
index b03371b..0e8bd3c 100644
--- a/scripts/cmd-reference/main.go
+++ b/cmd/squadron-docs/main.go
@@ -8,7 +8,7 @@ import (
"path/filepath"
"strings"
- "github.com/foomo/squadron/cmd/actions"
+ "github.com/foomo/squadron/internal/cli"
"github.com/spf13/cobra/doc"
)
@@ -28,7 +28,7 @@ func main() {
log.Fatal(err)
}
- c := actions.NewRoot()
+ c := cli.NewRoot()
c.DisableAutoGenTag = true
filePrepender := func(filename string) string {
diff --git a/cmd/squadron/main.go b/cmd/squadron/main.go
new file mode 100644
index 0000000..5a008ce
--- /dev/null
+++ b/cmd/squadron/main.go
@@ -0,0 +1,9 @@
+package main
+
+import (
+ "github.com/foomo/squadron/internal/cli"
+)
+
+func main() {
+ cli.Execute()
+}
diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts
index e927b4b..57ee878 100644
--- a/docs/.vitepress/config.mts
+++ b/docs/.vitepress/config.mts
@@ -1,59 +1,111 @@
import { defineConfig } from "vitepress";
-import {
- groupIconMdPlugin,
- groupIconVitePlugin,
-} from "vitepress-plugin-group-icons";
-import llmstxt, {
- copyOrDownloadAsMarkdownButtons,
-} from "vitepress-plugin-llms";
-import { withSidebar } from "vitepress-sidebar";
-const version = "latest";
-
-const vitepressConfig = {
+export default defineConfig({
title: "Squadron",
description: "Docker Compose for Kubernetes",
+ lang: "en-US",
+ cleanUrls: true,
+ lastUpdated: true,
+ appearance: "dark",
+ ignoreDeadLinks: false,
+ base: "/squadron/",
+ sitemap: {
+ hostname: "https://foomo.github.io/squadron",
+ },
themeConfig: {
logo: "/logo.png",
+ outline: [2, 4],
nav: [
+ { text: "Guide", link: "/guide/introduction" },
+ { text: "Reference", link: "/reference/" },
+ ],
+ sidebar: [
{
text: "Guide",
- link: "/guide/",
+ items: [
+ { text: "Introduction", link: "/guide/introduction" },
+ { text: "Installation", link: "/guide/installation" },
+ { text: "Quick Start", link: "/guide/quickstart" },
+ { text: "Core Concepts", link: "/guide/concepts" },
+ { text: "Configuration", link: "/guide/configuration" },
+ ],
},
{
- text: `${version}`,
+ text: "Reference",
+ items: [
+ { text: "Overview", link: "/reference/" },
+ {
+ text: "CLI",
+ link: "/reference/cli/squadron",
+ collapsed: true,
+ items: [
+ { text: "squadron", link: "/reference/cli/squadron" },
+ { text: "up", link: "/reference/cli/squadron_up" },
+ { text: "down", link: "/reference/cli/squadron_down" },
+ { text: "diff", link: "/reference/cli/squadron_diff" },
+ { text: "status", link: "/reference/cli/squadron_status" },
+ { text: "rollback", link: "/reference/cli/squadron_rollback" },
+ { text: "bake", link: "/reference/cli/squadron_bake" },
+ { text: "build", link: "/reference/cli/squadron_build" },
+ { text: "push", link: "/reference/cli/squadron_push" },
+ { text: "list", link: "/reference/cli/squadron_list" },
+ { text: "config", link: "/reference/cli/squadron_config" },
+ { text: "template", link: "/reference/cli/squadron_template" },
+ { text: "schema", link: "/reference/cli/squadron_schema" },
+ {
+ text: "completion",
+ link: "/reference/cli/squadron_completion",
+ },
+ { text: "version", link: "/reference/cli/squadron_version" },
+ ],
+ },
+ ],
+ },
+ {
+ text: "Contributing",
+ collapsed: true,
items: [
{
- text: "Release Notes",
- link: "https://github.com/foomo/squadron/releases",
+ text: "Guideline",
+ link: "/CONTRIBUTING.md",
+ },
+ {
+ text: "Code of conduct",
+ link: "/CODE_OF_CONDUCT.md",
+ },
+ {
+ text: "Security guidelines",
+ link: "/SECURITY.md",
},
],
},
],
- outline: {
- level: [2, 3],
- },
+ socialLinks: [
+ { icon: "github", link: "https://github.com/foomo/squadron" },
+ ],
editLink: {
pattern: "https://github.com/foomo/squadron/edit/main/docs/:path",
- text: "Suggest changes to this page",
},
search: {
provider: "local",
},
footer: {
- message: "Released under the MIT License.",
+ message:
+ 'Made with ♥ foomo by bestbytes',
+ },
+ },
+ markdown: {
+ // https://github.com/vuejs/vitepress/discussions/3724
+ theme: {
+ light: "catppuccin-latte",
+ dark: "catppuccin-frappe",
},
- socialLinks: [
- {
- icon: "github",
- link: "https://github.com/foomo/squadron",
- },
- ],
},
head: [
["meta", { name: "theme-color", content: "#ffffff" }],
["link", { rel: "icon", href: "/logo.png" }],
["meta", { name: "author", content: "foomo by bestbytes" }],
+ // OpenGraph
["meta", { property: "og:title", content: "foomo/squadron" }],
[
"meta",
@@ -87,35 +139,4 @@ const vitepressConfig = {
},
],
],
- markdown: {
- theme: {
- dark: "one-dark-pro",
- light: "github-light",
- },
- config(md) {
- md.use(groupIconMdPlugin);
- md.use(copyOrDownloadAsMarkdownButtons);
- },
- },
- vite: {
- plugins: [
- groupIconVitePlugin(),
- llmstxt({
- excludeIndexPage: false,
- }),
- ],
- },
- sitemap: {
- hostname: "https://foomo.github.io/squadron",
- },
- ignoreDeadLinks: true,
-};
-
-export default defineConfig(
- withSidebar(vitepressConfig, {
- useTitleFromFrontmatter: true,
- frontmatterOrderDefaultValue: 10,
- useFolderTitleFromIndexFile: true,
- sortMenusByFrontmatterOrder: true,
- }),
-);
+});
diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css
new file mode 100644
index 0000000..9773e5c
--- /dev/null
+++ b/docs/.vitepress/theme/custom.css
@@ -0,0 +1,91 @@
+@font-face {
+ font-family: "Bebas Neue";
+ src: url("/fonts/BebasNeue-Regular.ttf") format("truetype");
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+}
+
+/* Inter variable (normal) */
+@font-face {
+ font-family: "Inter";
+ src: url("/fonts/Inter-VariableFont_opsz,wght.ttf") format("truetype");
+ font-weight: 100 900;
+ font-optical-sizing: auto;
+ font-style: normal;
+ font-display: swap;
+}
+
+/* Inter variable (italic) */
+@font-face {
+ font-family: "Inter";
+ src: url("/fonts/Inter-Italic-VariableFont_opsz,wght.ttf") format("truetype");
+ font-weight: 100 900;
+ font-optical-sizing: auto;
+ font-style: italic;
+ font-display: swap;
+}
+
+/* JetBrains Mono variable (normal) */
+@font-face {
+ font-family: "JetBrains Mono";
+ src: url("/fonts/JetBrainsMono-VariableFont_wght.ttf") format("truetype");
+ font-weight: 100 900;
+ font-stretch: 100%;
+ font-style: normal;
+ font-display: swap;
+}
+
+/* JetBrains Mono variable (italic) */
+@font-face {
+ font-family: "JetBrains Mono";
+ src: url("/fonts/JetBrainsMono-Italic-VariableFont_wght.ttf")
+ format("truetype");
+ font-weight: 100 900;
+ font-stretch: 100%;
+ font-style: italic;
+ font-display: swap;
+}
+
+:root {
+ --vp-font-family-base:
+ "Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
+ "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+ --vp-font-family-mono:
+ "JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Monaco, Consolas,
+ "Liberation Mono", "Courier New", monospace;
+ --vp-font-family-display:
+ "Bebas Neue", "Inter", ui-sans-serif, system-ui, -apple-system,
+ BlinkMacSystemFont, sans-serif;
+}
+
+.VPNavBarTitle .logo {
+ height: 36px !important;
+ width: auto !important;
+}
+
+h1,
+.vp-doc h1 {
+ font-family: var(--vp-font-family-display);
+ font-weight: 400;
+ letter-spacing: 2px;
+ text-transform: uppercase;
+}
+
+.home-page .section-title {
+ font-family: var(--vp-font-family-display);
+ font-weight: 400 !important;
+ letter-spacing: 2px !important;
+ text-transform: uppercase !important;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ text-rendering: optimizeLegibility;
+}
+
+.hero-title,
+.title-main {
+ font-family: var(--vp-font-family-display);
+ font-weight: 400;
+ letter-spacing: 4px;
+ text-transform: uppercase;
+}
diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts
new file mode 100644
index 0000000..1bc8611
--- /dev/null
+++ b/docs/.vitepress/theme/index.ts
@@ -0,0 +1,9 @@
+import type { Theme } from "vitepress";
+import DefaultTheme from "vitepress/theme";
+import "@catppuccin/vitepress/theme/frappe/blue.css";
+
+import "./custom.css";
+
+export default {
+ extends: DefaultTheme,
+} satisfies Theme;
diff --git a/docs/bun.lock b/docs/bun.lock
index 0bd140e..4e68c5a 100644
--- a/docs/bun.lock
+++ b/docs/bun.lock
@@ -5,11 +5,11 @@
"": {
"name": "docs",
"devDependencies": {
+ "@catppuccin/vitepress": "^0.1.2",
"micromark-util-decode-string": "2.0.1",
"vitepress": "1.6.4",
"vitepress-plugin-group-icons": "1.6.5",
"vitepress-plugin-llms": "1.9.3",
- "vitepress-sidebar": "1.33.1",
},
},
},
@@ -60,6 +60,8 @@
"@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="],
+ "@catppuccin/vitepress": ["@catppuccin/vitepress@0.1.2", "", { "peerDependencies": { "typescript": "^5.0.0" } }, "sha512-dqhgo6U6GWbgh3McAgwemUC8Y2Aj48rRcQx/9iuPzBPAgo7NA3yi7ZcR0wolAENMmoOMAHBV+rz/5DfiGxtZLA=="],
+
"@docsearch/css": ["@docsearch/css@3.8.2", "", {}, "sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ=="],
"@docsearch/js": ["@docsearch/js@3.8.2", "", { "dependencies": { "@docsearch/react": "3.8.2", "preact": "^10.0.0" } }, "sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ=="],
@@ -126,8 +128,6 @@
"@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="],
- "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
-
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.53.3", "", { "os": "android", "cpu": "arm" }, "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w=="],
@@ -280,8 +280,6 @@
"copy-anything": ["copy-anything@4.0.5", "", { "dependencies": { "is-what": "^5.2.0" } }, "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA=="],
- "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
-
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
@@ -292,8 +290,6 @@
"devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
- "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="],
-
"emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"emoji-regex-xs": ["emoji-regex-xs@1.0.0", "", {}, "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg=="],
@@ -318,16 +314,12 @@
"focus-trap": ["focus-trap@7.6.6", "", { "dependencies": { "tabbable": "^6.3.0" } }, "sha512-v/Z8bvMCajtx4mEXmOo7QEsIzlIOqRXTIwgUfsFOF9gEsespdbD0AkPIka1bSXZ8Y8oZ+2IVDQZePkTfEHZl7Q=="],
- "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
-
"format": ["format@0.2.2", "", {}, "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww=="],
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
"get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
- "glob": ["glob@11.1.0", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw=="],
-
"gray-matter": ["gray-matter@4.0.3", "", { "dependencies": { "js-yaml": "^3.13.1", "kind-of": "^6.0.2", "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" } }, "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q=="],
"hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="],
@@ -346,10 +338,6 @@
"is-what": ["is-what@5.5.0", "", {}, "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw=="],
- "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
-
- "jackspeak": ["jackspeak@4.1.1", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" } }, "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ=="],
-
"js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="],
"kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="],
@@ -358,8 +346,6 @@
"longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
- "lru-cache": ["lru-cache@11.2.4", "", {}, "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg=="],
-
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
"mark.js": ["mark.js@8.11.1", "", {}, "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ=="],
@@ -430,8 +416,6 @@
"minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="],
- "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
-
"minisearch": ["minisearch@7.2.0", "", {}, "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg=="],
"mitt": ["mitt@3.0.1", "", {}, "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="],
@@ -444,14 +428,8 @@
"oniguruma-to-es": ["oniguruma-to-es@3.1.1", "", { "dependencies": { "emoji-regex-xs": "^1.0.0", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ=="],
- "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="],
-
"package-manager-detector": ["package-manager-detector@1.6.0", "", {}, "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA=="],
- "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
-
- "path-scurry": ["path-scurry@2.0.1", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA=="],
-
"path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="],
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
@@ -472,8 +450,6 @@
"punycode.js": ["punycode.js@2.3.1", "", {}, "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA=="],
- "qsu": ["qsu@1.10.4", "", {}, "sha512-v5RhwvHMkDdbXEaAxQh5re8q7DiG6EE70+CNwYVA6wZsa4gUrpur+D8lIO3PrzeCj3azc/S79X5v3BH8ILfr9A=="],
-
"regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="],
"regex-recursion": ["regex-recursion@6.0.2", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg=="],
@@ -498,14 +474,8 @@
"section-matter": ["section-matter@1.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "kind-of": "^6.0.0" } }, "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA=="],
- "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
-
- "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
-
"shiki": ["shiki@2.5.0", "", { "dependencies": { "@shikijs/core": "2.5.0", "@shikijs/engine-javascript": "2.5.0", "@shikijs/engine-oniguruma": "2.5.0", "@shikijs/langs": "2.5.0", "@shikijs/themes": "2.5.0", "@shikijs/types": "2.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ=="],
- "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
-
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
@@ -516,14 +486,10 @@
"string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
- "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
-
"stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="],
"strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
- "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
-
"strip-bom-string": ["strip-bom-string@1.0.0", "", {}, "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g=="],
"superjson": ["superjson@2.2.6", "", { "dependencies": { "copy-anything": "^4" } }, "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA=="],
@@ -538,6 +504,8 @@
"trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="],
+ "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
+
"uc.micro": ["uc.micro@2.1.0", "", {}, "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="],
"ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="],
@@ -568,16 +536,10 @@
"vitepress-plugin-llms": ["vitepress-plugin-llms@1.9.3", "", { "dependencies": { "gray-matter": "^4.0.3", "markdown-it": "^14.1.0", "markdown-title": "^1.0.2", "mdast-util-from-markdown": "^2.0.2", "millify": "^6.1.0", "minimatch": "^10.0.3", "path-to-regexp": "^8.3.0", "picocolors": "^1.1.1", "pretty-bytes": "^7.0.1", "remark": "^15.0.1", "remark-frontmatter": "^5.0.0", "tokenx": "^1.1.0", "unist-util-remove": "^4.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-iU6LQVGS35urNGW/RXHTtt9gj6kprV9ptJDX7ZiC+kgFtqiBMDo2bdXh2YG+KUGU3geKZWkWZcurhnrNCmofsA=="],
- "vitepress-sidebar": ["vitepress-sidebar@1.33.1", "", { "dependencies": { "glob": "11.1.0", "gray-matter": "4.0.3", "qsu": "^1.10.4" } }, "sha512-wPUbXezGakVldawixeRW5tKQTLKoMj2t4nWoThKfCltBM/9a38IE+wCXmmRNW22ZKC32SD/X/sG6NyCTK8QBRg=="],
-
"vue": ["vue@3.5.25", "", { "dependencies": { "@vue/compiler-dom": "3.5.25", "@vue/compiler-sfc": "3.5.25", "@vue/runtime-dom": "3.5.25", "@vue/server-renderer": "3.5.25", "@vue/shared": "3.5.25" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-YLVdgv2K13WJ6n+kD5owehKtEXwdwXuj2TTyJMsO7pSeKw2bfRNZGjhB7YzrpbMYj5b5QsUebHpOqR3R3ziy/g=="],
- "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
-
"wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
- "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
-
"y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
"yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
@@ -586,18 +548,6 @@
"zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
- "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
-
- "@isaacs/cliui/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
-
- "@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
-
"js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
-
- "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
-
- "@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
-
- "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
}
}
diff --git a/docs/guide/concepts.md b/docs/guide/concepts.md
new file mode 100644
index 0000000..449e42a
--- /dev/null
+++ b/docs/guide/concepts.md
@@ -0,0 +1,95 @@
+---
+title: Core Concepts
+---
+
+# Core Concepts
+
+## Squadrons and units
+
+A `squadron.yaml` describes one or more **squadrons**, and each squadron
+contains one or more **units**:
+
+```yaml
+squadron:
+