Compare commits

...

10 Commits

Author SHA1 Message Date
Jeff McCune
ab5f17c3d2 (#115) Fix goreleaser
Import modules to take the direct dependency and prevent go mod tidy
from modifying go.mod and go.sum which causes goreleaser to fail.
2024-04-10 19:09:30 -07:00
Jeff McCune
a8918c74d4 (#115) Angular spike - fix make frontend
And install frontend deps.
2024-04-09 21:03:26 -07:00
Jeff McCune
ae5738d82d (#115) Angular with SSR
Executed:

    ng new
    ng add @angular/ssr

Name: holos
Style: CSS
SSR and SSG?: No

ssr added using ng add following https://angular.io/guide/prerendering
2024-04-09 20:52:42 -07:00
Jeff McCune
bb99aedffa (#115) Remove frontend
Clean up for ng new in angular spike.
2024-04-09 20:35:43 -07:00
Jeff McCune
d6ee1864c8 (#116) Tilt for development
Add Tilt back from holos server

Note with this patch the ec-creds.yaml file needs to be applied to the
provisioner and an external secret used to sync the image pull creds.

With this patch the dev instance is accessible behind the auth proxy.
pgAdmin also works from the Tilt UI.

https://jeff.holos.dev.k2.ois.run/app/start
2024-04-09 20:26:37 -07:00
Jeff McCune
8a4be66277 (#113) Fix goreleaser try 4
Please check in your pipeline what can be changing the following files:
  M go.sum
2024-04-09 16:48:21 -07:00
Jeff McCune
79ce2f8458 (#113) Fix goreleaser try 3 2024-04-09 16:35:38 -07:00
Jeff McCune
3d4ae44ddd (#113) Fix goreleaser try 2
goreleaser fails with Failure: plugin connect-query: could not find protoc plugin for name connect-query - please make sure protoc-gen-connect-query is installed and present on your $PATH
2024-04-09 16:23:35 -07:00
Jeff McCune
1efb1faa40 (#113) Fix goreleaser
git executable must come before actions checkout
2024-04-09 16:04:42 -07:00
Jeff McCune
bfd6a56397 (#113) Fix actions workflows 2024-04-09 15:57:31 -07:00
134 changed files with 14756 additions and 6650 deletions

View File

@@ -17,11 +17,30 @@ jobs:
name: lint
runs-on: gha-rs
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 20
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: stable
cache: false
- name: Install tools
run: sudo apt update && sudo apt -qq -y install curl zip unzip tar bzip2 make
- name: Install Deps
run: |
make go-deps
go generate ./...
make frontend-deps
make frontend
go mod tidy
- name: golangci-lint
uses: golangci/golangci-lint-action@v4
with:

View File

@@ -14,23 +14,45 @@ jobs:
goreleaser:
runs-on: gha-rs
steps:
# Must come before Checkout, otherwise goreleaser fails
- name: Provide GPG and Git
run: sudo apt update && sudo apt -qq -y install gnupg git
run: sudo apt update && sudo apt -qq -y install gnupg git curl zip unzip tar bzip2 make
# Must come after git executable is provided
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 20
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: stable
# Necessary to run these outside of goreleaser, otherwise
# /home/runner/_work/holos/holos/internal/frontend/node_modules/.bin/protoc-gen-connect-query is not in PATH
- name: Install Deps
run: |
make go-deps
go generate ./...
make frontend-deps
make frontend
go mod tidy
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.GPG_CODE_SIGNING_SECRETKEY }}
passphrase: ${{ secrets.GPG_CODE_SIGNING_PASSPHRASE }}
- name: List keys
run: gpg -K
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: stable
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v5
with:

View File

@@ -18,13 +18,18 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 20
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: stable
- name: Provide unzip for Helm
run: sudo apt update && sudo apt -qq -y install curl zip unzip tar bzip2
- name: Install tools
run: sudo apt update && sudo apt -qq -y install curl zip unzip tar bzip2 make
- name: Set up Helm
uses: azure/setup-helm@v4
@@ -32,5 +37,13 @@ jobs:
- name: Set up Kubectl
uses: azure/setup-kubectl@v3
- name: Install Deps
run: |
make go-deps
go generate ./...
make frontend-deps
make frontend
go mod tidy
- name: Test
run: ./scripts/test

2
.gitignore vendored
View File

@@ -2,7 +2,7 @@ bin/
vendor/
.idea/
coverage.out
dist/
/dist/
*.hold/
/deploy/
.vscode/

View File

@@ -10,10 +10,8 @@ version: 1
before:
hooks:
# You may remove this if you don't use go modules.
- go mod tidy
# you may remove this if you don't need go generate
- go generate ./...
- go mod tidy
builds:
- main: ./cmd/holos
@@ -23,6 +21,9 @@ builds:
- linux
- windows
- darwin
goarch:
- amd64
- arm64
signs:
- artifacts: checksum

View File

@@ -12,6 +12,9 @@ IMAGE_NAME=$(DOCKER_REPO)
$( shell mkdir -p bin)
# For buf plugin protoc-gen-connect-es
export PATH := $(PWD)/internal/frontend/holos/node_modules/.bin:$(PATH)
GIT_COMMIT=$(shell git rev-parse HEAD)
GIT_TREE_STATE=$(shell test -n "`git status --porcelain`" && echo "dirty" || echo "clean")
BUILD_DATE=$(shell date -Iseconds)
@@ -94,6 +97,37 @@ coverage: test ## Test coverage profile.
snapshot: ## Go release snapshot
goreleaser release --snapshot --clean
.PHONY: buf
buf: ## buf generate
cd service && buf mod update
buf generate
.PHONY: go-deps
go-deps: ## install go executables
go install github.com/bufbuild/buf/cmd/buf@v1
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@v1
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1
go install connectrpc.com/connect/cmd/protoc-gen-connect-go@v1
go install honnef.co/go/tools/cmd/staticcheck@latest
# curl https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash
.PHONY: frontend-deps
frontend-deps: ## Setup npm and vite
cd internal/frontend/holos && npm install
cd internal/frontend/holos && npm install --save-dev @bufbuild/buf @connectrpc/protoc-gen-connect-es
cd internal/frontend/holos && npm install @connectrpc/connect @connectrpc/connect-web @bufbuild/protobuf
# https://github.com/connectrpc/connect-query-es/blob/1350b6f07b6aead81793917954bdb1cc3ce09df9/packages/protoc-gen-connect-query/README.md?plain=1#L23
cd internal/frontend/holos && npm install --save-dev @connectrpc/protoc-gen-connect-query @bufbuild/protoc-gen-es
cd internal/frontend/holos && npm install @connectrpc/connect-query @bufbuild/protobuf
.PHONY: frontend
frontend: buf
mkdir -p internal/frontend/holos/dist
cd internal/frontend/holos/dist && rm -rf app
cd internal/frontend/holos && ng build
touch internal/frontend/frontend.go
.PHONY: help
help: ## Display this help menu.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)

315
Tiltfile Normal file
View File

@@ -0,0 +1,315 @@
# -*- mode: Python -*-
# This Tiltfile manages a Go project with live leload in Kubernetes
listen_port = 3000
metrics_port = 9090
# Use our wrapper to set the kube namespace
if os.getenv('TILT_WRAPPER') != '1':
fail("could not run, ./hack/tilt/bin/tilt was not used to start tilt")
# AWS Account to work in
aws_account = '271053619184'
aws_region = 'us-east-2'
# Resource ids
holos_backend = 'Holos Backend'
pg_admin = 'pgAdmin'
pg_cluster = 'PostgresCluster'
pg_svc = 'Database Pod'
compile_id = 'Go Build'
auth_id = 'Auth Policy'
lint_id = 'Run Linters'
tests_id = 'Run Tests'
# PostgresCluster resource name in k8s
pg_cluster_name = 'holos'
# Database name inside the PostgresCluster
pg_database_name = 'holos'
# PGAdmin name
pg_admin_name = 'pgadmin'
# Default Registry.
# See: https://github.com/tilt-dev/tilt.build/blob/master/docs/choosing_clusters.md#manual-configuration
# Note, Tilt will append the image name to the registry uri path
default_registry('{account}.dkr.ecr.{region}.amazonaws.com/holos-run/holos-server'.format(account=aws_account, region=aws_region))
# Set a name prefix specific to the user. Multiple developers share the tilt-holos namespace.
developer = os.getenv('USER')
holos_server = 'holos'
# See ./hack/tilt/bin/tilt
namespace = os.getenv('NAMESPACE')
# We always develop against the k1 cluster.
os.putenv('KUBECONFIG', os.path.abspath('./hack/tilt/kubeconfig'))
# The context defined in ./hack/tilt/kubeconfig
allow_k8s_contexts('sso@k1')
allow_k8s_contexts('sso@k2')
allow_k8s_contexts('sso@k3')
allow_k8s_contexts('sso@k4')
allow_k8s_contexts('sso@k5')
# PG db connection for localhost -> k8s port-forward
os.putenv('PGHOST', 'localhost')
os.putenv('PGPORT', '15432')
# We always develop in the dev aws account.
os.putenv('AWS_CONFIG_FILE', os.path.abspath('./hack/tilt/aws.config'))
os.putenv('AWS_ACCOUNT', aws_account)
os.putenv('AWS_DEFAULT_REGION', aws_region)
os.putenv('AWS_PROFILE', 'dev-holos')
os.putenv('AWS_SDK_LOAD_CONFIG', '1')
# Authenticate to AWS ECR when tilt up is run by the developer
local_resource('AWS Credentials', './hack/tilt/aws-login.sh', auto_init=True)
# Extensions are open-source, pre-packaged functions that extend Tilt
#
# More info: https://github.com/tilt-dev/tilt-extensions
# More info: https://docs.tilt.dev/extensions.html
load('ext://restart_process', 'docker_build_with_restart')
load('ext://k8s_attach', 'k8s_attach')
load('ext://git_resource', 'git_checkout')
load('ext://uibutton', 'cmd_button')
# Paths edited by the developer Tilt watches to trigger compilation.
# Generated files should be excluded to avoid an infinite build loop.
developer_paths = [
'./cmd',
'./internal/server',
'./internal/ent/schema',
'./frontend/package-lock.json',
'./frontend/src',
'./go.mod',
'./pkg',
'./service/holos',
]
# Builds the holos-server executable
local_resource(compile_id, 'make build', deps=developer_paths)
# Build Docker image
# Tilt will automatically associate image builds with the resource(s)
# that reference them (e.g. via Kubernetes or Docker Compose YAML).
#
# More info: https://docs.tilt.dev/api.html#api.docker_build
#
docker_build_with_restart(
'holos',
context='.',
entrypoint=[
'/app/bin/holos',
'server',
'--listen-port={}'.format(listen_port),
'--oidc-issuer=https://login.ois.run',
'--oidc-audience=262096764402729854@holos_platform',
'--metrics-port={}'.format(metrics_port),
],
dockerfile='./hack/tilt/Dockerfile',
only=['./bin'],
# (Recommended) Updating a running container in-place
# https://docs.tilt.dev/live_update_reference.html
live_update=[
# Sync files from host to container
sync('./bin', '/app/bin'),
# Wait for aws-login https://github.com/tilt-dev/tilt/issues/3048
sync('./tilt/aws-login.last', '/dev/null'),
# Execute commands in the container when paths change
# run('/app/hack/codegen.sh', trigger=['./app/api'])
],
)
# Run local commands
# Local commands can be helpful for one-time tasks like installing
# project prerequisites. They can also manage long-lived processes
# for non-containerized services or dependencies.
#
# More info: https://docs.tilt.dev/local_resource.html
#
# local_resource('install-helm',
# cmd='which helm > /dev/null || brew install helm',
# # `cmd_bat`, when present, is used instead of `cmd` on Windows.
# cmd_bat=[
# 'powershell.exe',
# '-Noninteractive',
# '-Command',
# '& {if (!(Get-Command helm -ErrorAction SilentlyContinue)) {scoop install helm}}'
# ]
# )
# Teach tilt about our custom resources (Note, this may be intended for workloads)
# k8s_kind('authorizationpolicy')
# k8s_kind('requestauthentication')
# k8s_kind('virtualservice')
k8s_kind('pgadmin')
# Troubleshooting
def resource_name(id):
print('resource: {}'.format(id))
return id.name
workload_to_resource_function(resource_name)
# Apply Kubernetes manifests
# Tilt will build & push any necessary images, re-deploying your
# resources as they change.
#
# More info: https://docs.tilt.dev/api.html#api.k8s_yaml
#
def holos_yaml():
"""Return a k8s Deployment personalized for the developer."""
k8s_yaml_template = str(read_file('./hack/tilt/k8s.yaml'))
return k8s_yaml_template.format(
name=holos_server,
developer=developer,
namespace=namespace,
listen_port=listen_port,
metrics_port=metrics_port,
tz=os.getenv('TZ'),
)
# Customize a Kubernetes resource
# By default, Kubernetes resource names are automatically assigned
# based on objects in the YAML manifests, e.g. Deployment name.
#
# Tilt strives for sane defaults, so calling k8s_resource is
# optional, and you only need to pass the arguments you want to
# override.
#
# More info: https://docs.tilt.dev/api.html#api.k8s_resource
#
k8s_yaml(blob(holos_yaml()))
# Backend server process
k8s_resource(
workload=holos_server,
new_name=holos_backend,
objects=[
'{}:serviceaccount'.format(holos_server),
'{}:servicemonitor'.format(holos_server),
],
resource_deps=[compile_id],
links=[
link('https://{}.holos.dev.k2.ois.run/app/'.format(developer), "Holos Web UI")
],
)
# AuthorizationPolicy - Beyond Corp functionality
k8s_resource(
new_name=auth_id,
objects=[
'{}:virtualservice'.format(holos_server),
'{}-allow-groups:authorizationpolicy'.format(holos_server),
'{}-allow-nothing:authorizationpolicy'.format(holos_server),
'{}-allow-well-known-paths:authorizationpolicy'.format(holos_server),
'{}-auth:authorizationpolicy'.format(holos_server),
'{}:requestauthentication'.format(holos_server),
],
)
# Database
# Note: Tilt confuses the backup pods with the database server pods, so this code is careful to tease the pods
# apart so logs are streamed correctly.
# See: https://github.com/tilt-dev/tilt.specs/blob/master/resource_assembly.md
# pgAdmin Web UI
k8s_resource(
workload=pg_admin_name,
new_name=pg_admin,
port_forwards=[
port_forward(15050, 5050, pg_admin),
],
)
# Disabled because these don't group resources nicely
# k8s_kind('postgrescluster')
# Postgres database in-cluster
k8s_resource(
new_name=pg_cluster,
objects=['holos:postgrescluster'],
)
# Needed to select the database by label
# https://docs.tilt.dev/api.html#api.k8s_custom_deploy
k8s_custom_deploy(
pg_svc,
apply_cmd=['./hack/tilt/k8s-get-db-sts', pg_cluster_name],
delete_cmd=['echo', 'Skipping delete. Object managed by custom resource.'],
deps=[],
)
k8s_resource(
pg_svc,
port_forwards=[
port_forward(15432, 5432, 'psql'),
],
resource_deps=[pg_cluster]
)
# Run tests
local_resource(
tests_id,
'make test',
allow_parallel=True,
auto_init=False,
deps=developer_paths,
)
# Run linter
local_resource(
lint_id,
'make lint',
allow_parallel=True,
auto_init=False,
deps=developer_paths,
)
# UI Buttons for helpful things.
# Icons: https://fonts.google.com/icons
os.putenv("GH_FORCE_TTY", "80%")
cmd_button(
'{}:go-test-failfast'.format(tests_id),
argv=['./hack/tilt/go-test-failfast'],
resource=tests_id,
icon_name='quiz',
text='Fail Fast',
)
cmd_button(
'{}:issues'.format(holos_server),
argv=['./hack/tilt/gh-issues'],
resource=holos_backend,
icon_name='folder_data',
text='Issues',
)
cmd_button(
'{}:gh-issue-view'.format(holos_server),
argv=['./hack/tilt/gh-issue-view'],
resource=holos_backend,
icon_name='task',
text='View Issue',
)
cmd_button(
'{}:get-pgdb-creds'.format(holos_server),
argv=['./hack/tilt/get-pgdb-creds', pg_cluster_name, pg_database_name],
resource=pg_svc,
icon_name='lock_open_right',
text='DB Creds',
)
cmd_button(
'{}:get-pgdb-creds'.format(pg_admin_name),
argv=['./hack/tilt/get-pgdb-creds', pg_cluster_name, pg_database_name],
resource=pg_admin,
icon_name='lock_open_right',
text='DB Creds',
)
cmd_button(
'{}:get-pgadmin-creds'.format(pg_admin_name),
argv=['./hack/tilt/get-pgadmin-creds', pg_admin_name],
resource=pg_admin,
icon_name='lock_open_right',
text='pgAdmin Login',
)
print("✨ Tiltfile evaluated")

24
buf.gen.yaml Normal file
View File

@@ -0,0 +1,24 @@
# Generates gRPC and ConnectRPC bindings for Go and TypeScript
#
# Note: protoc-gen-connect-query is the primary method of wiring up the React
# frontend.
version: v1
plugins:
- plugin: go
out: service/gen
opt: paths=source_relative
- plugin: connect-go
out: service/gen
opt: paths=source_relative
- plugin: es
out: internal/frontend/holos/gen
opt:
- target=ts
- plugin: connect-es
out: internal/frontend/holos/gen
opt:
- target=ts
- plugin: connect-query
out: internal/frontend/holos/gen
opt:
- target=ts

8
buf.lock Normal file
View File

@@ -0,0 +1,8 @@
# Generated by buf. DO NOT EDIT.
version: v1
deps:
- remote: buf.build
owner: bufbuild
repository: protovalidate
commit: b983156c5e994cc9892e0ce3e64e17e0
digest: shake256:fb47a62989d38c2529bcc5cd86ded43d800eb84cee82b42b9e8a9e815d4ee8134a0fb9d0ce8299b27c2d2bbb7d6ade0c4ad5a8a4d467e1e2c7ca619ae9f634e2

3
buf.work.yaml Normal file
View File

@@ -0,0 +1,3 @@
version: v1
directories:
- service

4
go.mod
View File

@@ -15,6 +15,8 @@ require (
github.com/jackc/pgx/v5 v5.5.5
github.com/lmittmann/tint v1.0.4
github.com/mattn/go-isatty v0.0.20
github.com/mattn/go-runewidth v0.0.9
github.com/olekukonko/tablewriter v0.0.5
github.com/prometheus/client_golang v1.19.0
github.com/rogpeppe/go-internal v1.12.0
github.com/sethvargo/go-retry v0.2.4
@@ -24,7 +26,6 @@ require (
golang.org/x/net v0.22.0
golang.org/x/tools v0.19.0
google.golang.org/protobuf v1.33.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.29.2
k8s.io/apimachinery v0.29.2
k8s.io/client-go v0.29.2
@@ -103,6 +104,7 @@ require (
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.110.1 // indirect
k8s.io/kube-openapi v0.0.0-20231206194836-bf4651e18aa8 // indirect
k8s.io/utils v0.0.0-20231127182322-b307cd553661 // indirect

2
hack/tilt/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
aws-login.last
kubeconfig

7
hack/tilt/Dockerfile Normal file
View File

@@ -0,0 +1,7 @@
FROM 271053619184.dkr.ecr.us-east-2.amazonaws.com/holos-run/container-images/debian:bullseye AS final
USER root
WORKDIR /app
ADD bin bin
RUN chown -R app: /app
USER app
ENTRYPOINT bin/holos server

21
hack/tilt/aws-login.sh Executable file
View File

@@ -0,0 +1,21 @@
#! /bin/bash
set -euo pipefail
PARENT="$(cd $(dirname "$0") && pwd)"
# If necessary
if [[ -s "${PARENT}/aws-login.last" ]]; then
last="$(<"${PARENT}/aws-login.last")"
now="$(date +%s)"
if [[ $(( now - last )) -lt 28800 ]]; then
echo "creds are still valid" >&2
exit 0
fi
fi
aws sso logout
aws sso login
aws ecr get-login-password --region us-east-2 | docker login --username AWS --password-stdin "${AWS_ACCOUNT}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
# Touch a file so tilt docker_build can watch it as a dep
date +%s > "${PARENT}/aws-login.last"

7
hack/tilt/aws.config Normal file
View File

@@ -0,0 +1,7 @@
[profile dev-holos]
sso_account_id = 271053619184
sso_role_name = AdministratorAccess
sso_start_url = https://openinfrastructure.awsapps.com/start
sso_region = us-east-2
region = us-east-2
output = json

153
hack/tilt/ecr-creds.yaml Normal file
View File

@@ -0,0 +1,153 @@
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app.kubernetes.io/component: container-registry
app.kubernetes.io/instance: holos-system-ecr
app.kubernetes.io/name: holos-system-ecr
app.kubernetes.io/part-of: holos
name: holos-system-ecr
namespace: holos-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/component: container-registry
app.kubernetes.io/instance: holos-system-ecr
app.kubernetes.io/name: holos-system-ecr
app.kubernetes.io/part-of: holos
name: holos-system-ecr
rules:
- apiGroups:
- ""
resources:
- secrets
- namespaces
verbs:
- list
- apiGroups:
- ""
resourceNames:
- holos-system-ecr-image-pull-creds
resources:
- secrets
verbs:
- '*'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/component: container-registry
app.kubernetes.io/instance: holos-system-ecr
app.kubernetes.io/name: holos-system-ecr
app.kubernetes.io/part-of: holos
name: holos-system-ecr
namespace: holos-system
roleRef:
kind: ClusterRole
name: holos-system-ecr
subjects:
- kind: ServiceAccount
name: holos-system-ecr
namespace: holos-system
---
apiVersion: v1
data:
refresh.sh: |-
#! /bin/bash
tmpdir="$(mktemp -d)"
finish() {
rm -rf "${tmpdir}"
}
trap finish EXIT
set -euo pipefail
aws sts assume-role-with-web-identity \
--role-arn ${AWS_ROLE_ARN} \
--role-session-name CronJob \
--web-identity-token file:///run/secrets/irsa/serviceaccount/token \
> "${tmpdir}/creds.json"
export AWS_ACCESS_KEY_ID=$(jq -r .Credentials.AccessKeyId "${tmpdir}/creds.json")
export AWS_SECRET_ACCESS_KEY=$(jq -r .Credentials.SecretAccessKey "${tmpdir}/creds.json")
export AWS_SESSION_TOKEN=$(jq -r .Credentials.SessionToken "${tmpdir}/creds.json")
set -x
aws ecr get-login-password --region ${AWS_REGION} \
| docker login --username AWS --password-stdin ${AWS_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com
kubectl create secret docker-registry 'holos-system-ecr-image-pull-creds' \
--from-file=.dockerconfigjson=${HOME}/.docker/config.json \
--dry-run=client -o yaml \
> "${tmpdir}/secret.yaml"
# Get namespaces one per line
kubectl -o=jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' get namespaces > ${tmpdir}/namespaces.txt
# Copy the secret to all namespaces
for ns in $(grep -vE '^gke-|^kube-|^gmp-' ${tmpdir}/namespaces.txt); do
echo "---" >> "${tmpdir}/secretlist.yaml"
kubectl --dry-run=client -o yaml -n $ns apply -f "${tmpdir}/secret.yaml" >> "${tmpdir}/secretlist.yaml"
done
kubectl apply --server-side=true -f "${tmpdir}/secretlist.yaml"
kind: ConfigMap
metadata:
labels:
app.kubernetes.io/component: image-pull-secret
app.kubernetes.io/instance: holos-system-ecr
app.kubernetes.io/name: refresher
app.kubernetes.io/part-of: holos
name: holos-system-ecr
namespace: holos-system
---
apiVersion: batch/v1
kind: CronJob
metadata:
labels:
app.kubernetes.io/component: container-registry
app.kubernetes.io/instance: holos-system-ecr
app.kubernetes.io/name: holos-system-ecr
app.kubernetes.io/part-of: holos
name: holos-system-ecr
namespace: holos-system
spec:
schedule: 0 */4 * * *
jobTemplate:
spec:
template:
spec:
containers:
- command:
- bash
- /app/scripts/refresh.sh
env:
- name: AWS_ACCOUNT
value: "271053619184"
- name: AWS_REGION
value: us-east-2
- name: AWS_ROLE_ARN
value: arn:aws:iam::271053619184:role/ImagePull
image: quay.io/holos/toolkit:latest
imagePullPolicy: Always
name: toolkit
resources:
limits:
cpu: 50m
memory: 64Mi
requests:
cpu: 50m
memory: 64Mi
volumeMounts:
- mountPath: /app/scripts
name: scripts
- mountPath: /run/secrets/irsa/serviceaccount
name: irsa
restartPolicy: OnFailure
serviceAccountName: holos-system-ecr
volumes:
- configMap:
name: holos-system-ecr
name: scripts
- name: irsa
projected:
sources:
- serviceAccountToken:
path: "token"
audience: "irsa"
expirationSeconds: 3600

37
hack/tilt/get-pgadmin-creds Executable file
View File

@@ -0,0 +1,37 @@
#! /bin/bash
#
tmpdir="$(mktemp -d)"
finish() {
code=$?
if [[ $code -gt 10 ]]; then
jq . "${tmpdir}/creds.json"
echo "could not update pg password: jq got null on line $code" >&2
fi
rm -rf "$tmpdir"
exit $code
}
trap finish EXIT
set -euo pipefail
umask 077
if [[ $(uname) != Darwin ]]; then
pbcopy() {
xsel --input --clipboard
xsel --output --clipboard | xsel --input --primary
}
fi
sel="postgres-operator.crunchydata.com/pgadmin=${1}"
# secret="(kubectl -n "${NAMESPACE}" get secret --selector=$sel '--output=jsonpath={.items..metadata.name}')"
kubectl get secret "--selector=$sel" -o=json | jq '.items[].data | map_values(@base64d)' > "${tmpdir}/creds.json"
echo -n "username: "
jq --exit-status -r ".username" "${tmpdir}/creds.json"
password="$(jq --exit-status -r ".password" "${tmpdir}/creds.json")"
# n.b. don't send the trailing newline.
echo -n "$password" | pbcopy
echo "password: copied to clipboard."

53
hack/tilt/get-pgdb-creds Executable file
View File

@@ -0,0 +1,53 @@
#! /bin/bash
#
tmpdir="$(mktemp -d)"
finish() {
code=$?
if [[ $code -gt 10 ]]; then
jq . "${tmpdir}/creds.json"
echo "could not update pg password: jq got null on line $code" >&2
fi
rm -rf "$tmpdir"
exit $code
}
trap finish EXIT
set -euo pipefail
umask 077
if [[ $(uname) != Darwin ]]; then
pbcopy() {
xsel --input --clipboard
xsel --output --clipboard | xsel --input --primary
}
fi
kubectl get secret "${1}-pguser-${2}" -o json > "${tmpdir}/creds.json"
export PGDATABASE="$(jq --exit-status -r '.data | map_values(@base64d) | .dbname' ${tmpdir}/creds.json || exit $LINENO)"
export PGUSER="$(jq --exit-status -r '.data | map_values(@base64d) | .user' ${tmpdir}/creds.json || exit $LINENO)"
export PGPASSWORD="$(jq --exit-status -r '.data | map_values(@base64d) | .password' ${tmpdir}/creds.json || exit $LINENO)"
prefix="${PGHOST}:${PGPORT}:${PGDATABASE}:${PGUSER}"
if [[ -f ~/.pgpass ]]; then
(grep -v "^${prefix}:" ~/.pgpass || true) > "${tmpdir}/pgpass"
fi
echo "${prefix}:${PGPASSWORD}" >> "${tmpdir}/pgpass"
cp "${tmpdir}/pgpass" ~/.pgpass
echo "updated: ${HOME}/.pgpass" >&2
cat <<EOF >&2
## Connect from a localhost shell through the port forward to the cluster
export PGHOST=${PGHOST}
export PGPORT=${PGPORT}
export PGDATABASE=${PGDATABASE}
export PGUSER=${PGUSER}
psql -c '\conninfo'
EOF
psql --host=${PGHOST} --port=${PGPORT} ${PGDATABASE} -c '\conninfo'
# n.b. do not send a trailing newline to xsel
echo -n "$PGPASSWORD" | pbcopy
echo "password: copied to clipboard."

9
hack/tilt/gh-issue-view Executable file
View File

@@ -0,0 +1,9 @@
#! /bin/bash
#
set -euo pipefail
issue="$(git rev-parse --abbrev-ref HEAD | tr -d -c 0-9)"
if [[ -z $issue ]]; then
echo "could not extract issue number from branch name" >&2
exit 1
fi
exec gh issue view --comments $issue

4
hack/tilt/gh-issues Executable file
View File

@@ -0,0 +1,4 @@
#! /bin/bash
set -euo pipefail
export GH_FORCE_TTY='120%'
exec gh issue list

8
hack/tilt/go-test-failfast Executable file
View File

@@ -0,0 +1,8 @@
#! /bin/bash
#
set -euo pipefail
for s in $(go list ./...); do
if ! go test -failfast -v -p 1 $s; then
break
fi
done

20
hack/tilt/k8s-get-db-sts Executable file
View File

@@ -0,0 +1,20 @@
#! /bin/bash
#
# Output the stateful set yaml of the database using selectors
set -euo pipefail
sel="postgres-operator.crunchydata.com/cluster=${1},postgres-operator.crunchydata.com/instance-set=db"
x=30
while [[ $x -gt 0 ]]; do
for pod in $(kubectl get statefulsets --selector=$sel '--output=jsonpath={.items..metadata.name}'); do
echo "---"
kubectl get -o yaml statefulsets/$pod
x=0
done
if [[ $x -gt 0 ]]; then
((x--))
sleep 1
fi
done

5
hack/tilt/k8s-namespace Executable file
View File

@@ -0,0 +1,5 @@
#! /bin/bash
#
set -euo pipefail
cp "${KUBECONFIG}.template" "${KUBECONFIG}"
kubectl config set-context --current --namespace "${NAMESPACE}"

318
hack/tilt/k8s.yaml Normal file
View File

@@ -0,0 +1,318 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: '{name}'
namespace: '{namespace}'
labels:
app: '{name}'
holos.run/developer: '{developer}'
spec:
selector:
matchLabels:
app: '{name}'
template:
metadata:
labels:
app: '{name}'
holos.run/developer: '{developer}'
sidecar.istio.io/inject: 'true'
spec:
serviceAccountName: holos
containers:
- name: holos
image: holos # Tilt appends a tilt-* tag for the built docker image
# args are configured in the Tiltfile
env:
- name: GOMAXPROCS
value: '1'
- name: TZ
value: '{tz}'
- name: SHUTDOWN_DELAY
value: '0'
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: holos-pguser-holos
key: uri
ports:
- name: http
containerPort: {listen_port}
protocol: TCP
resources:
requests:
cpu: 250m
memory: 100Mi
limits:
cpu: 1000m
memory: 200Mi
---
apiVersion: v1
kind: Service
metadata:
name: '{name}'
namespace: '{namespace}'
labels:
app: '{name}'
holos.run/developer: '{developer}'
spec:
type: ClusterIP
selector:
app: '{name}'
ports:
- name: http
port: {listen_port}
appProtocol: http2
protocol: TCP
targetPort: {listen_port}
- name: metrics
port: {metrics_port}
appProtocol: http
protocol: TCP
targetPort: {metrics_port}
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: '{name}'
namespace: '{namespace}'
labels:
app: '{name}'
holos.run/developer: '{developer}'
spec:
endpoints:
- port: metrics
path: /metrics
interval: 15s
selector:
matchLabels:
app: '{name}'
holos.run/developer: '{developer}'
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: '{name}'
namespace: '{namespace}'
labels:
app: '{name}'
holos.run/developer: '{developer}'
spec:
gateways:
- istio-ingress/default
hosts:
- '{developer}.holos.dev.k2.ois.run'
http:
- route:
- destination:
host: '{name}'
port:
number: {listen_port}
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: holos
namespace: '{namespace}'
labels:
app: '{name}'
holos.run/developer: '{developer}'
imagePullSecrets:
- name: kube-system-ecr-image-pull-creds
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
labels:
app: '{name}'
holos.run/developer: '{developer}'
name: '{name}-allow-groups'
namespace: '{namespace}'
spec:
action: ALLOW
rules:
- when:
- key: request.auth.claims[groups]
values:
- holos-developer
- holos-developer@openinfrastructure.co
selector:
matchLabels:
holos.run/authz: dev-holos-sso
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: '{name}-allow-nothing'
namespace: '{namespace}'
labels:
app: '{name}'
holos.run/developer: '{developer}'
spec:
action: ALLOW
selector:
matchLabels:
holos.run/authz: dev-holos-sso
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: '{name}-allow-well-known-paths'
namespace: '{namespace}'
labels:
app: '{name}'
holos.run/developer: '{developer}'
spec:
action: ALLOW
rules:
- to:
- operation:
paths:
- /healthz
- /metrics
- /callbacks/github
selector:
matchLabels:
holos.run/authz: dev-holos-sso
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: '{name}-auth'
namespace: '{namespace}'
labels:
app: '{name}'
holos.run/developer: '{developer}'
spec:
action: CUSTOM
provider:
name: dev-holos-sso
rules:
- to:
- operation:
notPaths:
- /healthz
- /metrics
- /callbacks/github
when:
- key: request.headers[Authorization]
notValues:
- Bearer *
selector:
matchLabels:
holos.run/authz: dev-holos-sso
---
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: '{name}'
namespace: '{namespace}'
labels:
app: '{name}'
holos.run/developer: '{developer}'
spec:
jwtRules:
- audiences:
- https://sso.dev.holos.run
forwardOriginalToken: true
fromHeaders:
- name: x-auth-request-access-token
issuer: https://idex.core.ois.run
jwksUri: https://idex.core.ois.run/keys
- audiences:
- holos-cli
forwardOriginalToken: true
fromHeaders:
- name: authorization
prefix: 'Bearer '
issuer: https://idex.core.ois.run
jwksUri: https://idex.core.ois.run/keys
selector:
matchLabels:
holos.run/authz: dev-holos-sso
---
apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PGAdmin
metadata:
name: 'pgadmin'
namespace: '{namespace}'
labels:
holos.run/developer: '{developer}'
spec:
serverGroups:
- name: holos
postgresClusterSelector:
matchLabels:
holos.run/developer: '{developer}'
dataVolumeClaimSpec:
accessModes:
- "ReadWriteOnce"
resources:
requests:
storage: 1Gi
---
apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
name: 'holos'
namespace: '{namespace}'
labels:
holos.run/developer: '{developer}'
spec:
image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres:ubi8-16.1-0
postgresVersion: 16
users:
- name: holos
databases:
- holos
options: 'SUPERUSER'
- name: kratos
databases:
- kratos
options: 'SUPERUSER'
- name: hydra
databases:
- hydra
options: 'SUPERUSER'
- name: '{developer}'
databases:
- holos
- kratos
- hydra
- '{developer}'
options: 'SUPERUSER'
# https://access.crunchydata.com/documentation/postgres-operator/latest/architecture/user-management
instances:
- name: db
dataVolumeClaimSpec:
accessModes:
- "ReadWriteOnce"
resources:
requests:
storage: 1Gi
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
podAffinityTerm:
topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
postgres-operator.crunchydata.com/cluster: '{name}'
backups:
pgbackrest:
image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.47-2
# https://github.com/CrunchyData/postgres-operator/issues/2531#issuecomment-1713676019
global:
archive-async: "y"
archive-push-queue-max: "100MiB"
spool-path: "/pgdata/backups"
repos:
- name: repo1
volume:
volumeClaimSpec:
accessModes:
- "ReadWriteOnce"
resources:
requests:
storage: 1Gi

View File

@@ -0,0 +1,45 @@
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJpVENDQVRDZ0F3SUJBZ0lSQU9TenlHd2VMK3N4NjVvckVCTXV1c293Q2dZSUtvWkl6ajBFQXdJd0ZURVQKTUJFR0ExVUVDaE1LYTNWaVpYSnVaWFJsY3pBZUZ3MHlOREF5TVRNd05UQTRNRFJhRncwek5EQXlNVEF3TlRBNApNRFJhTUJVeEV6QVJCZ05WQkFvVENtdDFZbVZ5Ym1WMFpYTXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CCkJ3TkNBQVREWUluR09EN2ZpbFVIeXNpZG1ac2Vtd2liTk9hT1A5ZzVJT1VsTkllUHZ1Y01ZV01aNWNkZXpVQmIKMGh4Zm1WYXR0QWxpcnorMlFpVld5by9WZFNsOG8yRXdYekFPQmdOVkhROEJBZjhFQkFNQ0FvUXdIUVlEVlIwbApCQll3RkFZSUt3WUJCUVVIQXdFR0NDc0dBUVVGQndNQ01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0hRWURWUjBPCkJCWUVGTGVtcEhSM25lVXYvSUc1WWpwempDbWUydmIyTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSUNZajRsNUgKL043OG5UcnJxQzMxWjlsY0lpODEwcno5N3JIdUJnWFZZUkxBQWlBNHVEc0YyNEI5aGV3WklUbWEwaHpCMjNOdQpwZnprTWV5VzZHV2U2RWh4NGc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
server: https://k2.core.ois.run:6443
name: k2
contexts:
- context:
cluster: k2
namespace: default
user: admin@k2
name: admin@k2
- context:
cluster: k2
namespace: ${NAMESPACE}
user: oidc
name: sso@k2
current-context: sso@k2
kind: Config
preferences: {}
users:
- name: admin@k2
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJoRENDQVNxZ0F3SUJBZ0lRVXZKTlEvV0Ewalg5RXF6ZElIMFA4ekFLQmdncWhrak9QUVFEQWpBVk1STXcKRVFZRFZRUUtFd3ByZFdKbGNtNWxkR1Z6TUI0WERUSTBNRE14TVRJek1UY3hPVm9YRFRJMU1ETXhNVEl6TVRjeQpPVm93S1RFWE1CVUdBMVVFQ2hNT2MzbHpkR1Z0T20xaGMzUmxjbk14RGpBTUJnTlZCQU1UQldGa2JXbHVNRmt3CkV3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFNjZrMStQb1l5OHlPWTZkRFR5MHJYRTUvRlZJVU0rbkcKNEVzSXZxOHBuZ2lVRWRkeTdYM3hvZ2E5d2NSZy8xeVZ4Q2FNbzBUVEZveXkxaVZMMWxGWDNLTklNRVl3RGdZRApWUjBQQVFIL0JBUURBZ1dnTUJNR0ExVWRKUVFNTUFvR0NDc0dBUVVGQndNQ01COEdBMVVkSXdRWU1CYUFGTGVtCnBIUjNuZVV2L0lHNVlqcHpqQ21lMnZiMk1Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lDaDVGTWlXV3hxVHYyc0wKQVdvQ2lxaWJ0OUNUMnpsNzRlSTllMEZPTzRKTkFpRUF5T0wwR3RxVnlTSHUzbUsvVDBxZFhYQ3dmdHdWQVE4cgo2ejJWaVZrMzg2dz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
client-key-data: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSURtdTh0UGVrRmhlNzRXWm5idXlwOFZ1VUIxTVYwcTN4QklOclVVbjBaRjVvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFNjZrMStQb1l5OHlPWTZkRFR5MHJYRTUvRlZJVU0rbkc0RXNJdnE4cG5naVVFZGR5N1gzeApvZ2E5d2NSZy8xeVZ4Q2FNbzBUVEZveXkxaVZMMWxGWDNBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
- name: oidc
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
args:
- oidc-login
- get-token
- --oidc-issuer-url=https://login.ois.run
- --oidc-client-id=261774567918339420@holos_platform
- --oidc-extra-scope=openid
- --oidc-extra-scope=email
- --oidc-extra-scope=profile
- --oidc-extra-scope=groups
- --oidc-extra-scope=offline_access
- --oidc-extra-scope=urn:zitadel:iam:org:domain:primary:openinfrastructure.co
- --oidc-use-pkce
command: kubectl
env: null
interactiveMode: IfAvailable
provideClusterInfo: false

33
hack/tilt/pgpass-zalando Executable file
View File

@@ -0,0 +1,33 @@
#! /bin/bash
#
tmpdir="$(mktemp -d)"
finish() {
rm -rf "$tmpdir"
}
trap finish EXIT
set -euo pipefail
umask 077
kubectl -n "dev-${USER}" get secret "${USER}.holos-server-db.credentials.postgresql.acid.zalan.do" -o json > "${tmpdir}/creds.json"
if [[ -f ~/.pgpass ]]; then
(grep -v "^localhost:14126:holos:${USER}:" ~/.pgpass || true) > "${tmpdir}/pgpass"
fi
PGUSER="$(jq -r '.data | map_values(@base64d) | .username' ${tmpdir}/creds.json)"
PGPASSWORD="$(jq -r '.data | map_values(@base64d) | .password' ${tmpdir}/creds.json)"
echo "${PGHOST}:${PGPORT}:${PGDATABASE}:${PGUSER}:${PGPASSWORD}" >> "${tmpdir}/pgpass"
cp "${tmpdir}/pgpass" ~/.pgpass
echo "updated: ${HOME}/.pgpass" >&2
cat <<EOF >&2
## Connect from a localhost shell through the port forward to the cluster
export PGHOST=${PGHOST}
export PGPORT=${PGPORT}
export PGDATABASE=${PGDATABASE}
export PGUSER=${PGUSER}
psql -c '\conninfo'
EOF
psql --host=${PGHOST} --port=${PGPORT} ${PGDATABASE} -c '\conninfo'

View File

@@ -10,14 +10,14 @@ import (
"reflect"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/server/ent/migrate"
"github.com/holos-run/holos/internal/ent/migrate"
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"github.com/holos-run/holos/internal/server/ent/user"
"github.com/holos-run/holos/internal/server/ent/useridentity"
"github.com/holos-run/holos/internal/ent/user"
"github.com/holos-run/holos/internal/ent/useridentity"
)
// Client is the client that holds all ent builders.

View File

@@ -12,8 +12,8 @@ import (
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"github.com/holos-run/holos/internal/server/ent/user"
"github.com/holos-run/holos/internal/server/ent/useridentity"
"github.com/holos-run/holos/internal/ent/user"
"github.com/holos-run/holos/internal/ent/useridentity"
)
// ent aliases to avoid import conflicts in user's code.

View File

@@ -5,12 +5,12 @@ package enttest
import (
"context"
"github.com/holos-run/holos/internal/server/ent"
"github.com/holos-run/holos/internal/ent"
// required by schema hooks.
_ "github.com/holos-run/holos/internal/server/ent/runtime"
_ "github.com/holos-run/holos/internal/ent/runtime"
"entgo.io/ent/dialect/sql/schema"
"github.com/holos-run/holos/internal/server/ent/migrate"
"github.com/holos-run/holos/internal/ent/migrate"
)
type (

View File

@@ -6,7 +6,7 @@ import (
"context"
"fmt"
"github.com/holos-run/holos/internal/server/ent"
"github.com/holos-run/holos/internal/ent"
)
// The UserFunc type is an adapter to allow the use of ordinary

View File

@@ -12,9 +12,9 @@ import (
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/server/ent/predicate"
"github.com/holos-run/holos/internal/server/ent/user"
"github.com/holos-run/holos/internal/server/ent/useridentity"
"github.com/holos-run/holos/internal/ent/predicate"
"github.com/holos-run/holos/internal/ent/user"
"github.com/holos-run/holos/internal/ent/useridentity"
)
const (

View File

@@ -6,9 +6,9 @@ import (
"time"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/server/ent/schema"
"github.com/holos-run/holos/internal/server/ent/user"
"github.com/holos-run/holos/internal/server/ent/useridentity"
"github.com/holos-run/holos/internal/ent/schema"
"github.com/holos-run/holos/internal/ent/user"
"github.com/holos-run/holos/internal/ent/useridentity"
)
// The init function reads all schema descriptors with runtime code

View File

@@ -2,7 +2,7 @@
package runtime
// The schema-stitching logic is generated in github.com/holos-run/holos/internal/server/ent/runtime.go
// The schema-stitching logic is generated in github.com/holos-run/holos/internal/ent/runtime.go
const (
Version = "v0.13.1" // Version of ent codegen.

View File

@@ -10,7 +10,7 @@ import (
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/server/ent/user"
"github.com/holos-run/holos/internal/ent/user"
)
// User is the model entity for the User schema.

View File

@@ -8,7 +8,7 @@ import (
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/server/ent/predicate"
"github.com/holos-run/holos/internal/ent/predicate"
)
// ID filters vertices based on their ID field.

View File

@@ -13,8 +13,8 @@ import (
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/server/ent/user"
"github.com/holos-run/holos/internal/server/ent/useridentity"
"github.com/holos-run/holos/internal/ent/user"
"github.com/holos-run/holos/internal/ent/useridentity"
)
// UserCreate is the builder for creating a User entity.

View File

@@ -8,8 +8,8 @@ import (
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/holos-run/holos/internal/server/ent/predicate"
"github.com/holos-run/holos/internal/server/ent/user"
"github.com/holos-run/holos/internal/ent/predicate"
"github.com/holos-run/holos/internal/ent/user"
)
// UserDelete is the builder for deleting a User entity.

View File

@@ -12,9 +12,9 @@ import (
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/server/ent/predicate"
"github.com/holos-run/holos/internal/server/ent/user"
"github.com/holos-run/holos/internal/server/ent/useridentity"
"github.com/holos-run/holos/internal/ent/predicate"
"github.com/holos-run/holos/internal/ent/user"
"github.com/holos-run/holos/internal/ent/useridentity"
)
// UserQuery is the builder for querying User entities.

View File

@@ -12,9 +12,9 @@ import (
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/server/ent/predicate"
"github.com/holos-run/holos/internal/server/ent/user"
"github.com/holos-run/holos/internal/server/ent/useridentity"
"github.com/holos-run/holos/internal/ent/predicate"
"github.com/holos-run/holos/internal/ent/user"
"github.com/holos-run/holos/internal/ent/useridentity"
)
// UserUpdate is the builder for updating User entities.

View File

@@ -10,8 +10,8 @@ import (
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/server/ent/user"
"github.com/holos-run/holos/internal/server/ent/useridentity"
"github.com/holos-run/holos/internal/ent/user"
"github.com/holos-run/holos/internal/ent/useridentity"
)
// UserIdentity is the model entity for the UserIdentity schema.

View File

@@ -8,7 +8,7 @@ import (
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/server/ent/predicate"
"github.com/holos-run/holos/internal/ent/predicate"
)
// ID filters vertices based on their ID field.

View File

@@ -13,8 +13,8 @@ import (
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/server/ent/user"
"github.com/holos-run/holos/internal/server/ent/useridentity"
"github.com/holos-run/holos/internal/ent/user"
"github.com/holos-run/holos/internal/ent/useridentity"
)
// UserIdentityCreate is the builder for creating a UserIdentity entity.

View File

@@ -8,8 +8,8 @@ import (
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/holos-run/holos/internal/server/ent/predicate"
"github.com/holos-run/holos/internal/server/ent/useridentity"
"github.com/holos-run/holos/internal/ent/predicate"
"github.com/holos-run/holos/internal/ent/useridentity"
)
// UserIdentityDelete is the builder for deleting a UserIdentity entity.

View File

@@ -11,9 +11,9 @@ import (
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/server/ent/predicate"
"github.com/holos-run/holos/internal/server/ent/user"
"github.com/holos-run/holos/internal/server/ent/useridentity"
"github.com/holos-run/holos/internal/ent/predicate"
"github.com/holos-run/holos/internal/ent/user"
"github.com/holos-run/holos/internal/ent/useridentity"
)
// UserIdentityQuery is the builder for querying UserIdentity entities.

View File

@@ -11,8 +11,8 @@ import (
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/holos-run/holos/internal/server/ent/predicate"
"github.com/holos-run/holos/internal/server/ent/useridentity"
"github.com/holos-run/holos/internal/ent/predicate"
"github.com/holos-run/holos/internal/ent/useridentity"
)
// UserIdentityUpdate is the builder for updating UserIdentity entities.

View File

@@ -11,10 +11,10 @@ import (
const Path = "/app/"
//go:embed all:dist
//go:embed all:holos/dist/holos/browser
var content embed.FS
//go:embed dist/app/index.html
//go:embed holos/dist/holos/browser/index.html
var spaIndexHtml []byte
// Root returns the content root subdirectory

View File

@@ -0,0 +1,16 @@
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.ts]
quote_type = single
[*.md]
max_line_length = off
trim_trailing_whitespace = false

45
internal/frontend/holos/.gitignore vendored Normal file
View File

@@ -0,0 +1,45 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# Compiled output
/dist
/tmp
/out-tsc
/bazel-out
# Node
/node_modules
npm-debug.log
yarn-error.log
# IDEs and editors
.idea/
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# Visual Studio Code
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# Miscellaneous
/.angular/cache
.sass-cache/
/connect.lock
/coverage
/libpeerconnection.log
testem.log
/typings
# System files
.DS_Store
Thumbs.db
# Generated files
/gen/

View File

@@ -0,0 +1,27 @@
# Holos
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.0.10.
## Development server
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files.
## Code scaffolding
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
## Build
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.
## Running unit tests
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
## Running end-to-end tests
Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.
## Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.

View File

@@ -0,0 +1,100 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"holos": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
"outputPath": "dist/holos",
"index": "src/index.html",
"browser": "src/main.ts",
"polyfills": [
"zone.js"
],
"tsConfig": "tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": [],
"server": "src/main.server.ts",
"prerender": true,
"ssr": {
"entry": "server.ts"
}
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "holos:build:production"
},
"development": {
"buildTarget": "holos:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"buildTarget": "holos:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"polyfills": [
"zone.js",
"zone.js/testing"
],
"tsConfig": "tsconfig.spec.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": []
}
}
}
}
}
}

12710
internal/frontend/holos/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,52 @@
{
"name": "holos",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test",
"serve:ssr:holos": "node dist/holos/server/server.mjs"
},
"private": true,
"dependencies": {
"@angular/animations": "^17.0.0",
"@angular/common": "^17.0.0",
"@angular/compiler": "^17.0.0",
"@angular/core": "^17.0.0",
"@angular/forms": "^17.0.0",
"@angular/platform-browser": "^17.0.0",
"@angular/platform-browser-dynamic": "^17.0.0",
"@angular/platform-server": "^17.0.0",
"@angular/router": "^17.0.0",
"@angular/ssr": "^17.3.3",
"@bufbuild/protobuf": "^1.8.0",
"@connectrpc/connect": "^1.4.0",
"@connectrpc/connect-query": "^1.3.1",
"@connectrpc/connect-web": "^1.4.0",
"express": "^4.18.2",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.2"
},
"devDependencies": {
"@angular-devkit/build-angular": "^17.0.10",
"@angular/cli": "^17.0.10",
"@angular/compiler-cli": "^17.0.0",
"@bufbuild/buf": "^1.30.1",
"@bufbuild/protoc-gen-es": "^1.8.0",
"@connectrpc/protoc-gen-connect-es": "^1.4.0",
"@connectrpc/protoc-gen-connect-query": "^1.3.1",
"@types/express": "^4.17.17",
"@types/jasmine": "~5.1.0",
"@types/node": "^18.18.0",
"jasmine-core": "~5.1.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.2.2"
}
}

View File

@@ -0,0 +1,56 @@
import { APP_BASE_HREF } from '@angular/common';
import { CommonEngine } from '@angular/ssr';
import express from 'express';
import { fileURLToPath } from 'node:url';
import { dirname, join, resolve } from 'node:path';
import bootstrap from './src/main.server';
// The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express {
const server = express();
const serverDistFolder = dirname(fileURLToPath(import.meta.url));
const browserDistFolder = resolve(serverDistFolder, '../browser');
const indexHtml = join(serverDistFolder, 'index.server.html');
const commonEngine = new CommonEngine();
server.set('view engine', 'html');
server.set('views', browserDistFolder);
// Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { });
// Serve static files from /browser
server.get('*.*', express.static(browserDistFolder, {
maxAge: '1y'
}));
// All regular routes use the Angular engine
server.get('*', (req, res, next) => {
const { protocol, originalUrl, baseUrl, headers } = req;
commonEngine
.render({
bootstrap,
documentFilePath: indexHtml,
url: `${protocol}://${headers.host}${originalUrl}`,
publicPath: browserDistFolder,
providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }],
})
.then((html) => res.send(html))
.catch((err) => next(err));
});
return server;
}
function run(): void {
const port = process.env['PORT'] || 4000;
// Start up the Node server
const server = app();
server.listen(port, () => {
console.log(`Node Express server listening on http://localhost:${port}`);
});
}
run();

View File

@@ -0,0 +1,336 @@
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * The content below * * * * * * * * * * * -->
<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * -->
<!-- * * * * * * * * * * and can be replaced. * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * Delete the template below * * * * * * * * * -->
<!-- * * * * * * * to get started with your project! * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<style>
:host {
--bright-blue: oklch(51.01% 0.274 263.83);
--electric-violet: oklch(53.18% 0.28 296.97);
--french-violet: oklch(47.66% 0.246 305.88);
--vivid-pink: oklch(69.02% 0.277 332.77);
--hot-red: oklch(61.42% 0.238 15.34);
--orange-red: oklch(63.32% 0.24 31.68);
--gray-900: oklch(19.37% 0.006 300.98);
--gray-700: oklch(36.98% 0.014 302.71);
--gray-400: oklch(70.9% 0.015 304.04);
--red-to-pink-to-purple-vertical-gradient: linear-gradient(
180deg,
var(--orange-red) 0%,
var(--vivid-pink) 50%,
var(--electric-violet) 100%
);
--red-to-pink-to-purple-horizontal-gradient: linear-gradient(
90deg,
var(--orange-red) 0%,
var(--vivid-pink) 50%,
var(--electric-violet) 100%
);
--pill-accent: var(--bright-blue);
font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol";
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
h1 {
font-size: 3.125rem;
color: var(--gray-900);
font-weight: 500;
line-height: 100%;
letter-spacing: -0.125rem;
margin: 0;
font-family: "Inter Tight", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol";
}
p {
margin: 0;
color: var(--gray-700);
}
main {
width: 100%;
min-height: 100%;
display: flex;
justify-content: center;
align-items: center;
padding: 1rem;
box-sizing: inherit;
position: relative;
}
.angular-logo {
max-width: 9.2rem;
}
.content {
display: flex;
justify-content: space-around;
width: 100%;
max-width: 700px;
margin-bottom: 3rem;
}
.content h1 {
margin-top: 1.75rem;
}
.content p {
margin-top: 1.5rem;
}
.divider {
width: 1px;
background: var(--red-to-pink-to-purple-vertical-gradient);
margin-inline: 0.5rem;
}
.pill-group {
display: flex;
flex-direction: column;
align-items: start;
flex-wrap: wrap;
gap: 1.25rem;
}
.pill {
display: flex;
align-items: center;
--pill-accent: var(--bright-blue);
background: color-mix(in srgb, var(--pill-accent) 5%, transparent);
color: var(--pill-accent);
padding-inline: 0.75rem;
padding-block: 0.375rem;
border-radius: 2.75rem;
border: 0;
transition: background 0.3s ease;
font-family: var(--inter-font);
font-size: 0.875rem;
font-style: normal;
font-weight: 500;
line-height: 1.4rem;
letter-spacing: -0.00875rem;
text-decoration: none;
}
.pill:hover {
background: color-mix(in srgb, var(--pill-accent) 15%, transparent);
}
.pill-group .pill:nth-child(6n + 1) {
--pill-accent: var(--bright-blue);
}
.pill-group .pill:nth-child(6n + 2) {
--pill-accent: var(--french-violet);
}
.pill-group .pill:nth-child(6n + 3),
.pill-group .pill:nth-child(6n + 4),
.pill-group .pill:nth-child(6n + 5) {
--pill-accent: var(--hot-red);
}
.pill-group svg {
margin-inline-start: 0.25rem;
}
.social-links {
display: flex;
align-items: center;
gap: 0.73rem;
margin-top: 1.5rem;
}
.social-links path {
transition: fill 0.3s ease;
fill: var(--gray-400);
}
.social-links a:hover svg path {
fill: var(--gray-900);
}
@media screen and (max-width: 650px) {
.content {
flex-direction: column;
width: max-content;
}
.divider {
height: 1px;
width: 100%;
background: var(--red-to-pink-to-purple-horizontal-gradient);
margin-block: 1.5rem;
}
}
</style>
<main class="main">
<div class="content">
<div class="left-side">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 982 239"
fill="none"
class="angular-logo"
>
<g clip-path="url(#a)">
<path
fill="url(#b)"
d="M388.676 191.625h30.849L363.31 31.828h-35.758l-56.215 159.797h30.848l13.174-39.356h60.061l13.256 39.356Zm-65.461-62.675 21.602-64.311h1.227l21.602 64.311h-44.431Zm126.831-7.527v70.202h-28.23V71.839h27.002v20.374h1.392c2.782-6.71 7.2-12.028 13.255-15.956 6.056-3.927 13.584-5.89 22.503-5.89 8.264 0 15.465 1.8 21.684 5.318 6.137 3.518 10.964 8.673 14.319 15.382 3.437 6.71 5.074 14.81 4.992 24.383v76.175h-28.23v-71.92c0-8.019-2.046-14.237-6.219-18.819-4.173-4.5-9.819-6.791-17.102-6.791-4.91 0-9.328 1.063-13.174 3.272-3.846 2.128-6.792 5.237-9.001 9.328-2.046 4.009-3.191 8.918-3.191 14.728ZM589.233 239c-10.147 0-18.82-1.391-26.103-4.091-7.282-2.7-13.092-6.382-17.511-10.964-4.418-4.582-7.528-9.655-9.164-15.219l25.448-6.136c1.145 2.372 2.782 4.663 4.991 6.954 2.209 2.291 5.155 4.255 8.837 5.81 3.683 1.554 8.428 2.291 14.074 2.291 8.019 0 14.647-1.964 19.884-5.81 5.237-3.845 7.856-10.227 7.856-19.064v-22.665h-1.391c-1.473 2.946-3.601 5.892-6.383 9.001-2.782 3.109-6.464 5.645-10.965 7.691-4.582 2.046-10.228 3.109-17.101 3.109-9.165 0-17.511-2.209-25.039-6.545-7.446-4.337-13.42-10.883-17.757-19.474-4.418-8.673-6.628-19.473-6.628-32.565 0-13.091 2.21-24.301 6.628-33.383 4.419-9.082 10.311-15.955 17.839-20.7 7.528-4.746 15.874-7.037 25.039-7.037 7.037 0 12.846 1.145 17.347 3.518 4.582 2.373 8.182 5.236 10.883 8.51 2.7 3.272 4.746 6.382 6.137 9.327h1.554v-19.8h27.821v121.749c0 10.228-2.454 18.737-7.364 25.447-4.91 6.709-11.538 11.7-20.048 15.055-8.509 3.355-18.165 4.991-28.884 4.991Zm.245-71.266c5.974 0 11.047-1.473 15.302-4.337 4.173-2.945 7.446-7.118 9.573-12.519 2.21-5.482 3.274-12.027 3.274-19.637 0-7.609-1.064-14.155-3.274-19.8-2.127-5.646-5.318-10.064-9.491-13.255-4.174-3.11-9.329-4.746-15.384-4.746s-11.537 1.636-15.792 4.91c-4.173 3.272-7.365 7.772-9.492 13.418-2.128 5.727-3.191 12.191-3.191 19.392 0 7.2 1.063 13.745 3.273 19.228 2.127 5.482 5.318 9.736 9.573 12.764 4.174 3.027 9.41 4.582 15.629 4.582Zm141.56-26.51V71.839h28.23v119.786h-27.412v-21.273h-1.227c-2.7 6.709-7.119 12.191-13.338 16.446-6.137 4.255-13.747 6.382-22.748 6.382-7.855 0-14.81-1.718-20.783-5.237-5.974-3.518-10.72-8.591-14.075-15.382-3.355-6.709-5.073-14.891-5.073-24.464V71.839h28.312v71.921c0 7.609 2.046 13.664 6.219 18.083 4.173 4.5 9.655 6.709 16.365 6.709 4.173 0 8.183-.982 12.111-3.028 3.927-2.045 7.118-5.072 9.655-9.082 2.537-4.091 3.764-9.164 3.764-15.218Zm65.707-109.395v159.796h-28.23V31.828h28.23Zm44.841 162.169c-7.61 0-14.402-1.391-20.457-4.091-6.055-2.7-10.883-6.791-14.32-12.109-3.518-5.319-5.237-11.946-5.237-19.801 0-6.791 1.228-12.355 3.765-16.773 2.536-4.419 5.891-7.937 10.228-10.637 4.337-2.618 9.164-4.664 14.647-6.055 5.4-1.391 11.046-2.373 16.856-3.027 7.037-.737 12.683-1.391 17.102-1.964 4.337-.573 7.528-1.555 9.574-2.782 1.963-1.309 3.027-3.273 3.027-5.973v-.491c0-5.891-1.718-10.391-5.237-13.664-3.518-3.191-8.51-4.828-15.056-4.828-6.955 0-12.356 1.473-16.447 4.5-4.009 3.028-6.71 6.546-8.183 10.719l-26.348-3.764c2.046-7.282 5.483-13.336 10.31-18.328 4.746-4.909 10.638-8.59 17.511-11.045 6.955-2.455 14.565-3.682 22.912-3.682 5.809 0 11.537.654 17.265 2.045s10.965 3.6 15.711 6.71c4.746 3.109 8.51 7.282 11.455 12.6 2.864 5.318 4.337 11.946 4.337 19.883v80.184h-27.166v-16.446h-.9c-1.719 3.355-4.092 6.464-7.201 9.328-3.109 2.864-6.955 5.237-11.619 6.955-4.828 1.718-10.229 2.536-16.529 2.536Zm7.364-20.701c5.646 0 10.556-1.145 14.729-3.354 4.173-2.291 7.364-5.237 9.655-9.001 2.292-3.763 3.355-7.854 3.355-12.273v-14.155c-.9.737-2.373 1.391-4.5 2.046-2.128.654-4.419 1.145-7.037 1.636-2.619.491-5.155.9-7.692 1.227-2.537.328-4.746.655-6.628.901-4.173.572-8.019 1.472-11.292 2.781-3.355 1.31-5.973 3.11-7.855 5.401-1.964 2.291-2.864 5.318-2.864 8.918 0 5.237 1.882 9.164 5.728 11.782 3.682 2.782 8.51 4.091 14.401 4.091Zm64.643 18.328V71.839h27.412v19.965h1.227c2.21-6.955 5.974-12.274 11.292-16.038 5.319-3.763 11.456-5.645 18.329-5.645 1.555 0 3.355.082 5.237.163 1.964.164 3.601.328 4.91.573v25.938c-1.227-.41-3.109-.819-5.646-1.146a58.814 58.814 0 0 0-7.446-.49c-5.155 0-9.738 1.145-13.829 3.354-4.091 2.209-7.282 5.236-9.655 9.164-2.373 3.927-3.519 8.427-3.519 13.5v70.448h-28.312ZM222.077 39.192l-8.019 125.923L137.387 0l84.69 39.192Zm-53.105 162.825-57.933 33.056-57.934-33.056 11.783-28.556h92.301l11.783 28.556ZM111.039 62.675l30.357 73.803H80.681l30.358-73.803ZM7.937 165.115 0 39.192 84.69 0 7.937 165.115Z"
/>
<path
fill="url(#c)"
d="M388.676 191.625h30.849L363.31 31.828h-35.758l-56.215 159.797h30.848l13.174-39.356h60.061l13.256 39.356Zm-65.461-62.675 21.602-64.311h1.227l21.602 64.311h-44.431Zm126.831-7.527v70.202h-28.23V71.839h27.002v20.374h1.392c2.782-6.71 7.2-12.028 13.255-15.956 6.056-3.927 13.584-5.89 22.503-5.89 8.264 0 15.465 1.8 21.684 5.318 6.137 3.518 10.964 8.673 14.319 15.382 3.437 6.71 5.074 14.81 4.992 24.383v76.175h-28.23v-71.92c0-8.019-2.046-14.237-6.219-18.819-4.173-4.5-9.819-6.791-17.102-6.791-4.91 0-9.328 1.063-13.174 3.272-3.846 2.128-6.792 5.237-9.001 9.328-2.046 4.009-3.191 8.918-3.191 14.728ZM589.233 239c-10.147 0-18.82-1.391-26.103-4.091-7.282-2.7-13.092-6.382-17.511-10.964-4.418-4.582-7.528-9.655-9.164-15.219l25.448-6.136c1.145 2.372 2.782 4.663 4.991 6.954 2.209 2.291 5.155 4.255 8.837 5.81 3.683 1.554 8.428 2.291 14.074 2.291 8.019 0 14.647-1.964 19.884-5.81 5.237-3.845 7.856-10.227 7.856-19.064v-22.665h-1.391c-1.473 2.946-3.601 5.892-6.383 9.001-2.782 3.109-6.464 5.645-10.965 7.691-4.582 2.046-10.228 3.109-17.101 3.109-9.165 0-17.511-2.209-25.039-6.545-7.446-4.337-13.42-10.883-17.757-19.474-4.418-8.673-6.628-19.473-6.628-32.565 0-13.091 2.21-24.301 6.628-33.383 4.419-9.082 10.311-15.955 17.839-20.7 7.528-4.746 15.874-7.037 25.039-7.037 7.037 0 12.846 1.145 17.347 3.518 4.582 2.373 8.182 5.236 10.883 8.51 2.7 3.272 4.746 6.382 6.137 9.327h1.554v-19.8h27.821v121.749c0 10.228-2.454 18.737-7.364 25.447-4.91 6.709-11.538 11.7-20.048 15.055-8.509 3.355-18.165 4.991-28.884 4.991Zm.245-71.266c5.974 0 11.047-1.473 15.302-4.337 4.173-2.945 7.446-7.118 9.573-12.519 2.21-5.482 3.274-12.027 3.274-19.637 0-7.609-1.064-14.155-3.274-19.8-2.127-5.646-5.318-10.064-9.491-13.255-4.174-3.11-9.329-4.746-15.384-4.746s-11.537 1.636-15.792 4.91c-4.173 3.272-7.365 7.772-9.492 13.418-2.128 5.727-3.191 12.191-3.191 19.392 0 7.2 1.063 13.745 3.273 19.228 2.127 5.482 5.318 9.736 9.573 12.764 4.174 3.027 9.41 4.582 15.629 4.582Zm141.56-26.51V71.839h28.23v119.786h-27.412v-21.273h-1.227c-2.7 6.709-7.119 12.191-13.338 16.446-6.137 4.255-13.747 6.382-22.748 6.382-7.855 0-14.81-1.718-20.783-5.237-5.974-3.518-10.72-8.591-14.075-15.382-3.355-6.709-5.073-14.891-5.073-24.464V71.839h28.312v71.921c0 7.609 2.046 13.664 6.219 18.083 4.173 4.5 9.655 6.709 16.365 6.709 4.173 0 8.183-.982 12.111-3.028 3.927-2.045 7.118-5.072 9.655-9.082 2.537-4.091 3.764-9.164 3.764-15.218Zm65.707-109.395v159.796h-28.23V31.828h28.23Zm44.841 162.169c-7.61 0-14.402-1.391-20.457-4.091-6.055-2.7-10.883-6.791-14.32-12.109-3.518-5.319-5.237-11.946-5.237-19.801 0-6.791 1.228-12.355 3.765-16.773 2.536-4.419 5.891-7.937 10.228-10.637 4.337-2.618 9.164-4.664 14.647-6.055 5.4-1.391 11.046-2.373 16.856-3.027 7.037-.737 12.683-1.391 17.102-1.964 4.337-.573 7.528-1.555 9.574-2.782 1.963-1.309 3.027-3.273 3.027-5.973v-.491c0-5.891-1.718-10.391-5.237-13.664-3.518-3.191-8.51-4.828-15.056-4.828-6.955 0-12.356 1.473-16.447 4.5-4.009 3.028-6.71 6.546-8.183 10.719l-26.348-3.764c2.046-7.282 5.483-13.336 10.31-18.328 4.746-4.909 10.638-8.59 17.511-11.045 6.955-2.455 14.565-3.682 22.912-3.682 5.809 0 11.537.654 17.265 2.045s10.965 3.6 15.711 6.71c4.746 3.109 8.51 7.282 11.455 12.6 2.864 5.318 4.337 11.946 4.337 19.883v80.184h-27.166v-16.446h-.9c-1.719 3.355-4.092 6.464-7.201 9.328-3.109 2.864-6.955 5.237-11.619 6.955-4.828 1.718-10.229 2.536-16.529 2.536Zm7.364-20.701c5.646 0 10.556-1.145 14.729-3.354 4.173-2.291 7.364-5.237 9.655-9.001 2.292-3.763 3.355-7.854 3.355-12.273v-14.155c-.9.737-2.373 1.391-4.5 2.046-2.128.654-4.419 1.145-7.037 1.636-2.619.491-5.155.9-7.692 1.227-2.537.328-4.746.655-6.628.901-4.173.572-8.019 1.472-11.292 2.781-3.355 1.31-5.973 3.11-7.855 5.401-1.964 2.291-2.864 5.318-2.864 8.918 0 5.237 1.882 9.164 5.728 11.782 3.682 2.782 8.51 4.091 14.401 4.091Zm64.643 18.328V71.839h27.412v19.965h1.227c2.21-6.955 5.974-12.274 11.292-16.038 5.319-3.763 11.456-5.645 18.329-5.645 1.555 0 3.355.082 5.237.163 1.964.164 3.601.328 4.91.573v25.938c-1.227-.41-3.109-.819-5.646-1.146a58.814 58.814 0 0 0-7.446-.49c-5.155 0-9.738 1.145-13.829 3.354-4.091 2.209-7.282 5.236-9.655 9.164-2.373 3.927-3.519 8.427-3.519 13.5v70.448h-28.312ZM222.077 39.192l-8.019 125.923L137.387 0l84.69 39.192Zm-53.105 162.825-57.933 33.056-57.934-33.056 11.783-28.556h92.301l11.783 28.556ZM111.039 62.675l30.357 73.803H80.681l30.358-73.803ZM7.937 165.115 0 39.192 84.69 0 7.937 165.115Z"
/>
</g>
<defs>
<radialGradient
id="c"
cx="0"
cy="0"
r="1"
gradientTransform="rotate(118.122 171.182 60.81) scale(205.794)"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="#FF41F8" />
<stop offset=".707" stop-color="#FF41F8" stop-opacity=".5" />
<stop offset="1" stop-color="#FF41F8" stop-opacity="0" />
</radialGradient>
<linearGradient
id="b"
x1="0"
x2="982"
y1="192"
y2="192"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="#F0060B" />
<stop offset="0" stop-color="#F0070C" />
<stop offset=".526" stop-color="#CC26D5" />
<stop offset="1" stop-color="#7702FF" />
</linearGradient>
<clipPath id="a"><path fill="#fff" d="M0 0h982v239H0z" /></clipPath>
</defs>
</svg>
<h1>Hello, {{ title }}</h1>
<p>Congratulations! Your app is running. 🎉</p>
</div>
<div class="divider" role="separator" aria-label="Divider"></div>
<div class="right-side">
<div class="pill-group">
@for (item of [
{ title: 'Explore the Docs', link: 'https://angular.dev' },
{ title: 'Learn with Tutorials', link: 'https://angular.dev/tutorials' },
{ title: 'CLI Docs', link: 'https://angular.dev/tools/cli' },
{ title: 'Angular Language Service', link: 'https://angular.dev/tools/language-service' },
{ title: 'Angular DevTools', link: 'https://angular.dev/tools/devtools' },
]; track item.title) {
<a
class="pill"
[href]="item.link"
target="_blank"
rel="noopener"
>
<span>{{ item.title }}</span>
<svg
xmlns="http://www.w3.org/2000/svg"
height="14"
viewBox="0 -960 960 960"
width="14"
fill="currentColor"
>
<path
d="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h280v80H200v560h560v-280h80v280q0 33-23.5 56.5T760-120H200Zm188-212-56-56 372-372H560v-80h280v280h-80v-144L388-332Z"
/>
</svg>
</a>
}
</div>
<div class="social-links">
<a
href="https://github.com/angular/angular"
aria-label="Github"
target="_blank"
rel="noopener"
>
<svg
width="25"
height="24"
viewBox="0 0 25 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
alt="Github"
>
<path
d="M12.3047 0C5.50634 0 0 5.50942 0 12.3047C0 17.7423 3.52529 22.3535 8.41332 23.9787C9.02856 24.0946 9.25414 23.7142 9.25414 23.3871C9.25414 23.0949 9.24389 22.3207 9.23876 21.2953C5.81601 22.0377 5.09414 19.6444 5.09414 19.6444C4.53427 18.2243 3.72524 17.8449 3.72524 17.8449C2.61064 17.082 3.81137 17.0973 3.81137 17.0973C5.04697 17.1835 5.69604 18.3647 5.69604 18.3647C6.79321 20.2463 8.57636 19.7029 9.27978 19.3881C9.39052 18.5924 9.70736 18.0499 10.0591 17.7423C7.32641 17.4347 4.45429 16.3765 4.45429 11.6618C4.45429 10.3185 4.9311 9.22133 5.72065 8.36C5.58222 8.04931 5.16694 6.79833 5.82831 5.10337C5.82831 5.10337 6.85883 4.77319 9.2121 6.36459C10.1965 6.09082 11.2424 5.95546 12.2883 5.94931C13.3342 5.95546 14.3801 6.09082 15.3644 6.36459C17.7023 4.77319 18.7328 5.10337 18.7328 5.10337C19.3942 6.79833 18.9789 8.04931 18.8559 8.36C19.6403 9.22133 20.1171 10.3185 20.1171 11.6618C20.1171 16.3888 17.2409 17.4296 14.5031 17.7321C14.9338 18.1012 15.3337 18.8559 15.3337 20.0084C15.3337 21.6552 15.3183 22.978 15.3183 23.3779C15.3183 23.7009 15.5336 24.0854 16.1642 23.9623C21.0871 22.3484 24.6094 17.7341 24.6094 12.3047C24.6094 5.50942 19.0999 0 12.3047 0Z"
/>
</svg>
</a>
<a
href="https://twitter.com/angular"
aria-label="Twitter"
target="_blank"
rel="noopener"
>
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
alt="Twitter"
>
<path
d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"
/>
</svg>
</a>
<a
href="https://www.youtube.com/channel/UCbn1OgGei-DV7aSRo_HaAiw"
aria-label="Youtube"
target="_blank"
rel="noopener"
>
<svg
width="29"
height="20"
viewBox="0 0 29 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
alt="Youtube"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M27.4896 1.52422C27.9301 1.96749 28.2463 2.51866 28.4068 3.12258C29.0004 5.35161 29.0004 10 29.0004 10C29.0004 10 29.0004 14.6484 28.4068 16.8774C28.2463 17.4813 27.9301 18.0325 27.4896 18.4758C27.0492 18.9191 26.5 19.2389 25.8972 19.4032C23.6778 20 14.8068 20 14.8068 20C14.8068 20 5.93586 20 3.71651 19.4032C3.11363 19.2389 2.56449 18.9191 2.12405 18.4758C1.68361 18.0325 1.36732 17.4813 1.20683 16.8774C0.613281 14.6484 0.613281 10 0.613281 10C0.613281 10 0.613281 5.35161 1.20683 3.12258C1.36732 2.51866 1.68361 1.96749 2.12405 1.52422C2.56449 1.08095 3.11363 0.76113 3.71651 0.596774C5.93586 0 14.8068 0 14.8068 0C14.8068 0 23.6778 0 25.8972 0.596774C26.5 0.76113 27.0492 1.08095 27.4896 1.52422ZM19.3229 10L11.9036 5.77905V14.221L19.3229 10Z"
/>
</svg>
</a>
</div>
</div>
</div>
</main>
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * The content above * * * * * * * * * * * * -->
<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * * -->
<!-- * * * * * * * * * * and can be replaced. * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * End of Placeholder * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<router-outlet></router-outlet>

View File

@@ -0,0 +1,29 @@
import { TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AppComponent],
}).compileComponents();
});
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it(`should have the 'holos' title`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual('holos');
});
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, holos');
});
});

View File

@@ -0,0 +1,14 @@
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule, RouterOutlet],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent {
title = 'holos';
}

View File

@@ -0,0 +1,11 @@
import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
import { provideServerRendering } from '@angular/platform-server';
import { appConfig } from './app.config';
const serverConfig: ApplicationConfig = {
providers: [
provideServerRendering()
]
};
export const config = mergeApplicationConfig(appConfig, serverConfig);

View File

@@ -0,0 +1,9 @@
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser';
export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes), provideClientHydration()]
};

View File

@@ -0,0 +1,3 @@
import { Routes } from '@angular/router';
export const routes: Routes = [];

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Holos</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
</html>

View File

@@ -0,0 +1,7 @@
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { config } from './app/app.config.server';
const bootstrap = () => bootstrapApplication(AppComponent, config);
export default bootstrap;

View File

@@ -0,0 +1,6 @@
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { AppComponent } from './app/app.component';
bootstrapApplication(AppComponent, appConfig)
.catch((err) => console.error(err));

View File

@@ -0,0 +1 @@
/* You can add global styles to this file, and also import other style files */

View File

@@ -0,0 +1,18 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": [
"node"
]
},
"files": [
"src/main.ts",
"src/main.server.ts",
"server.ts"
],
"include": [
"src/**/*.d.ts"
]
}

View File

@@ -0,0 +1,33 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"skipLibCheck": true,
"esModuleInterop": true,
"sourceMap": true,
"declaration": false,
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "ES2022",
"module": "ES2022",
"useDefineForClassFields": false,
"lib": [
"ES2022",
"dom"
]
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true
}
}

View File

@@ -0,0 +1,14 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jasmine"
]
},
"include": [
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}

View File

@@ -7,7 +7,7 @@ import (
"time"
"entgo.io/ent/dialect"
"github.com/holos-run/holos/internal/server/ent"
"github.com/holos-run/holos/internal/ent"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
)

View File

@@ -6,7 +6,7 @@ import (
"entgo.io/ent/dialect"
entsql "entgo.io/ent/dialect/sql"
"github.com/holos-run/holos/internal/server/ent"
"github.com/holos-run/holos/internal/ent"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
_ "github.com/jackc/pgx/v5/stdlib"

View File

@@ -7,7 +7,7 @@ import (
"log/slog"
esql "entgo.io/ent/dialect/sql"
"github.com/holos-run/holos/internal/server/ent"
"github.com/holos-run/holos/internal/ent"
"github.com/holos-run/holos/pkg/errors"
"github.com/holos-run/holos/pkg/holos"
"modernc.org/sqlite"

View File

@@ -1,35 +0,0 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
'prettier',
],
overrides: [
{
extends: ['plugin:@typescript-eslint/strict-type-checked'],
files: ['./**/*.{ts,tsx}'],
},
{
extends: ['plugin:@typescript-eslint/disable-type-checked'],
files: ['./vite.config.ts'],
}
],
ignorePatterns: ['dist', 'gen', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: ['./tsconfig.json', './tsconfig.node.json'],
tsconfigRootDir: __dirname,
},
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}

View File

@@ -1,24 +0,0 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@@ -1,4 +0,0 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
make lint

View File

@@ -1,17 +0,0 @@
# Holos Front End
The holos front end is a React + TypeScript single page app with strict type
checking enabled via eslint and prettier.
Frameworks were evaluated, but all were eschewed because they have too many
unnecessary features and make too many assumptions which are distracting for
velocity. Instead, the app is built as a combination of:
1. PatternFly for a consistent design and component library.
2. React Router for client side url routing.
3. SupaBase for authentication (and only auth!)
4. Buf to generate TypeScript types from proto bufs.
5. ConnectRPC + TanStack Query for the client side query rpc.
This stack provides a well integrated, strongly typed, front and backend
service that runs well on top of the Holos Platform.

View File

@@ -1,35 +0,0 @@
// @generated by protoc-gen-connect-query v1.1.3 with parameter "target=ts"
// @generated from file holos/v1alpha1/holos.proto (package holos.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import { MethodKind } from "@bufbuild/protobuf";
import { GetUserClaimsRequest, GetUserClaimsResponse, RegisterUserRequest, RegisterUserResponse } from "./holos_pb.js";
/**
* @generated from rpc holos.v1alpha1.HolosService.GetUserClaims
*/
export const getUserClaims = {
localName: "getUserClaims",
name: "GetUserClaims",
kind: MethodKind.Unary,
I: GetUserClaimsRequest,
O: GetUserClaimsResponse,
service: {
typeName: "holos.v1alpha1.HolosService"
}
} as const;
/**
* @generated from rpc holos.v1alpha1.HolosService.RegisterUser
*/
export const registerUser = {
localName: "registerUser",
name: "RegisterUser",
kind: MethodKind.Unary,
I: RegisterUserRequest,
O: RegisterUserResponse,
service: {
typeName: "holos.v1alpha1.HolosService"
}
} as const;

View File

@@ -1,35 +0,0 @@
// @generated by protoc-gen-connect-es v1.3.0 with parameter "target=ts"
// @generated from file holos/v1alpha1/holos.proto (package holos.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import { GetUserClaimsRequest, GetUserClaimsResponse, RegisterUserRequest, RegisterUserResponse } from "./holos_pb.js";
import { MethodKind } from "@bufbuild/protobuf";
/**
* @generated from service holos.v1alpha1.HolosService
*/
export const HolosService = {
typeName: "holos.v1alpha1.HolosService",
methods: {
/**
* @generated from rpc holos.v1alpha1.HolosService.GetUserClaims
*/
getUserClaims: {
name: "GetUserClaims",
I: GetUserClaimsRequest,
O: GetUserClaimsResponse,
kind: MethodKind.Unary,
},
/**
* @generated from rpc holos.v1alpha1.HolosService.RegisterUser
*/
registerUser: {
name: "RegisterUser",
I: RegisterUserRequest,
O: RegisterUserResponse,
kind: MethodKind.Unary,
},
}
} as const;

View File

@@ -1,296 +0,0 @@
// @generated by protoc-gen-es v1.6.0 with parameter "target=ts"
// @generated from file holos/v1alpha1/holos.proto (package holos.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
import { Message, proto3, Timestamp } from "@bufbuild/protobuf";
/**
* @generated from message holos.v1alpha1.Timestamps
*/
export class Timestamps extends Message<Timestamps> {
/**
* Created at timestamp
*
* @generated from field: google.protobuf.Timestamp created_at = 1;
*/
createdAt?: Timestamp;
/**
* Updated at timestamp
*
* @generated from field: google.protobuf.Timestamp updated_at = 2;
*/
updatedAt?: Timestamp;
constructor(data?: PartialMessage<Timestamps>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.Timestamps";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "created_at", kind: "message", T: Timestamp },
{ no: 2, name: "updated_at", kind: "message", T: Timestamp },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Timestamps {
return new Timestamps().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Timestamps {
return new Timestamps().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Timestamps {
return new Timestamps().fromJsonString(jsonString, options);
}
static equals(a: Timestamps | PlainMessage<Timestamps> | undefined, b: Timestamps | PlainMessage<Timestamps> | undefined): boolean {
return proto3.util.equals(Timestamps, a, b);
}
}
/**
* Empty request, claims are pulled from the id token
*
* @generated from message holos.v1alpha1.GetUserClaimsRequest
*/
export class GetUserClaimsRequest extends Message<GetUserClaimsRequest> {
constructor(data?: PartialMessage<GetUserClaimsRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.GetUserClaimsRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetUserClaimsRequest {
return new GetUserClaimsRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetUserClaimsRequest {
return new GetUserClaimsRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetUserClaimsRequest {
return new GetUserClaimsRequest().fromJsonString(jsonString, options);
}
static equals(a: GetUserClaimsRequest | PlainMessage<GetUserClaimsRequest> | undefined, b: GetUserClaimsRequest | PlainMessage<GetUserClaimsRequest> | undefined): boolean {
return proto3.util.equals(GetUserClaimsRequest, a, b);
}
}
/**
* UserClaims represents id token claims
*
* @generated from message holos.v1alpha1.GetUserClaimsResponse
*/
export class GetUserClaimsResponse extends Message<GetUserClaimsResponse> {
/**
* @generated from field: string iss = 1;
*/
iss = "";
/**
* @generated from field: string sub = 2;
*/
sub = "";
/**
* @generated from field: string email = 3;
*/
email = "";
/**
* @generated from field: bool email_verified = 4;
*/
emailVerified = false;
/**
* @generated from field: string name = 5;
*/
name = "";
constructor(data?: PartialMessage<GetUserClaimsResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.GetUserClaimsResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "iss", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "sub", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 3, name: "email", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 4, name: "email_verified", kind: "scalar", T: 8 /* ScalarType.BOOL */ },
{ no: 5, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetUserClaimsResponse {
return new GetUserClaimsResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetUserClaimsResponse {
return new GetUserClaimsResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetUserClaimsResponse {
return new GetUserClaimsResponse().fromJsonString(jsonString, options);
}
static equals(a: GetUserClaimsResponse | PlainMessage<GetUserClaimsResponse> | undefined, b: GetUserClaimsResponse | PlainMessage<GetUserClaimsResponse> | undefined): boolean {
return proto3.util.equals(GetUserClaimsResponse, a, b);
}
}
/**
* User represents a human user in the system. See db schema in ent/schema/user.go
*
* @generated from message holos.v1alpha1.User
*/
export class User extends Message<User> {
/**
* Unique id assigned by the server.
*
* @generated from field: string id = 1;
*/
id = "";
/**
* @generated from field: string email = 2;
*/
email = "";
/**
* @generated from field: bool email_verified = 3;
*/
emailVerified = false;
/**
* @generated from field: string name = 4;
*/
name = "";
/**
* @generated from field: holos.v1alpha1.Timestamps timestamps = 5;
*/
timestamps?: Timestamps;
constructor(data?: PartialMessage<User>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.User";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "email", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 3, name: "email_verified", kind: "scalar", T: 8 /* ScalarType.BOOL */ },
{ no: 4, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 5, name: "timestamps", kind: "message", T: Timestamps },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): User {
return new User().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): User {
return new User().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): User {
return new User().fromJsonString(jsonString, options);
}
static equals(a: User | PlainMessage<User> | undefined, b: User | PlainMessage<User> | undefined): boolean {
return proto3.util.equals(User, a, b);
}
}
/**
* @generated from message holos.v1alpha1.RegisterUserRequest
*/
export class RegisterUserRequest extends Message<RegisterUserRequest> {
/**
* @generated from field: optional string name = 1;
*/
name?: string;
constructor(data?: PartialMessage<RegisterUserRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.RegisterUserRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): RegisterUserRequest {
return new RegisterUserRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): RegisterUserRequest {
return new RegisterUserRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): RegisterUserRequest {
return new RegisterUserRequest().fromJsonString(jsonString, options);
}
static equals(a: RegisterUserRequest | PlainMessage<RegisterUserRequest> | undefined, b: RegisterUserRequest | PlainMessage<RegisterUserRequest> | undefined): boolean {
return proto3.util.equals(RegisterUserRequest, a, b);
}
}
/**
* @generated from message holos.v1alpha1.RegisterUserResponse
*/
export class RegisterUserResponse extends Message<RegisterUserResponse> {
/**
* @generated from field: holos.v1alpha1.User user = 1;
*/
user?: User;
/**
* @generated from field: bool already_exists = 2;
*/
alreadyExists = false;
constructor(data?: PartialMessage<RegisterUserResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.RegisterUserResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "user", kind: "message", T: User },
{ no: 2, name: "already_exists", kind: "scalar", T: 8 /* ScalarType.BOOL */ },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): RegisterUserResponse {
return new RegisterUserResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): RegisterUserResponse {
return new RegisterUserResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): RegisterUserResponse {
return new RegisterUserResponse().fromJsonString(jsonString, options);
}
static equals(a: RegisterUserResponse | PlainMessage<RegisterUserResponse> | undefined, b: RegisterUserResponse | PlainMessage<RegisterUserResponse> | undefined): boolean {
return proto3.util.equals(RegisterUserResponse, a, b);
}
}

View File

@@ -1,19 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/logos/logo-circle-light.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script>
window.holosAppConfig = {
oidcIssuer: '{{ .OIDCIssuer }}',
}
</script>
<title>Holos Platform</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
<noscript>JavaScript is disabled. Enable JavaScript to use this app.</noscript>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -1,56 +0,0 @@
{
"name": "holos",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"format": "prettier --write src/**/*.{js,jsx,ts,tsx,json,css,scss,md}",
"preview": "vite preview",
"prepare": "cd .. && husky install frontend/.husky"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/**/*.{js,jsx,ts,tsx,json,css,scss,md}": [
"prettier --write"
]
},
"dependencies": {
"@bufbuild/protobuf": "^1.6.0",
"@connectrpc/connect": "^1.3.0",
"@connectrpc/connect-query": "^1.1.3",
"@connectrpc/connect-web": "^1.3.0",
"@patternfly/patternfly": "^5.1.0",
"@patternfly/react-core": "^5.1.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.21.1"
},
"devDependencies": {
"@bufbuild/buf": "^1.28.1",
"@bufbuild/protoc-gen-es": "^1.6.0",
"@connectrpc/protoc-gen-connect-es": "^1.3.0",
"@connectrpc/protoc-gen-connect-query": "^1.1.3",
"@types/react": "^18.2.43",
"@types/react-dom": "^18.2.17",
"@typescript-eslint/eslint-plugin": "^6.14.0",
"@typescript-eslint/parser": "^6.14.0",
"@vitejs/plugin-react": "^4.2.1",
"eslint": "^8.55.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.5",
"husky": "^8.0.3",
"lint-staged": "^15.2.0",
"prettier": "^3.1.1",
"typescript": "^5.2.2",
"vite": "^5.0.8",
"vite-tsconfig-paths": "^4.2.3"
}
}

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Created with Vectornator (http://vectornator.io/) -->
<svg stroke-miterlimit="10" style="fill-rule:nonzero;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;" version="1.1" viewBox="0 0 1024 1024" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:vectornator="http://vectornator.io" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs/>
<g id="Layer-2" vectornator:layerName="Layer 2">
<path d="M0 512C0 229.23 229.23 0 512 0C794.77 0 1024 229.23 1024 512C1024 794.77 794.77 1024 512 1024C229.23 1024 0 794.77 0 512Z" fill="#073642" fill-rule="nonzero" opacity="1" stroke="none"/>
<g opacity="1">
<path d="M933.424 514.808C917.63 433.281 869.3 383.872 788.511 366.382C704.587 348.214 633.302 371.874 572.971 431.41C526.248 477.52 479.93 524.047 433.149 570.083C403.303 599.429 374.27 630.061 335.347 647.878C291.933 667.763 248.771 666.365 210.95 636.595C172.395 606.223 164.207 563.984 176.014 517.591C193.763 447.932 276.41 420.237 340.127 462.341C347.753 467.377 355.263 472.592 362.986 477.841C366.663 474.363 369.296 471.957 371.831 469.451C401.251 440.404 429.704 410.327 460.265 382.533C500.795 345.658 548.448 324.829 604.423 329.266C623.566 330.782 642.437 335.697 665.064 339.704C618.437 295.463 567.165 275.24 506.157 284.845C448.943 293.854 403.632 324.56 365.367 366.442C356.386 376.28 348.295 378.669 335.56 373.882C320.269 368.128 305.249 364.453 290.52 362.674L290.52 362.668C290.5 362.666 290.462 362.666 290.442 362.664C290.268 362.643 290.094 362.614 289.92 362.595C289.9 362.61 289.9 362.622 289.881 362.637C106.548 351.591 88.6638 511.202 88.6638 511.202C71.5924 686.897 191.518 722.839 191.518 722.839L191.576 722.839C206.112 728.585 221.17 732.645 236.519 735.788L236.538 735.819C236.538 735.819 239.325 736.536 244.474 737.335C245.848 737.589 247.222 737.854 248.596 738.095C248.635 738.039 248.674 737.987 248.693 737.931C276.197 741.42 347.405 743.49 432.626 691.86C432.8 691.868 432.994 691.851 433.168 691.866C487.866 637.142 542.603 582.455 597.533 527.979C623.817 501.92 647.721 472.872 682.212 456.086C736.194 429.821 803.008 442.342 834.035 485.929C858.674 520.529 861.578 558.329 843.848 596.118C825.383 635.448 792.131 656.737 748.93 658.027C689.509 659.802 629.992 659.094 570.532 658.976C557.739 658.951 547.809 662.849 538.906 672.148C520.344 691.562 500.989 710.23 482.098 729.338C479.485 731.968 474.937 735.811 470.814 740.441C476.756 741.082 483.782 741.288 487.266 741.292C555.009 741.352 622.753 741.817 690.496 741.12C724.02 740.774 758.414 742.569 790.853 735.916C890.262 715.536 953.012 615.898 933.424 514.808" fill="#839496" fill-rule="nonzero" opacity="1" stroke="none"/>
<path d="M364.692 552.822C364.692 600.053 326.386 638.34 279.119 638.34C231.852 638.34 193.528 600.053 193.528 552.822C193.528 505.592 231.852 467.303 279.119 467.303C326.386 467.303 364.692 505.592 364.692 552.822" fill="#839496" fill-rule="nonzero" opacity="1" stroke="none"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Created with Vectornator (http://vectornator.io/) -->
<svg stroke-miterlimit="10" width="1024px" height="1024px" style="fill-rule:nonzero;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;" version="1.1" viewBox="0 0 1024 1024" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs/>
<g id="Layer-1">
<path d="M0 512C0 229.23 229.23 0 512 0C794.77 0 1024 229.23 1024 512C1024 794.77 794.77 1024 512 1024C229.23 1024 0 794.77 0 512Z" fill="#fdf6e3" fill-rule="nonzero" opacity="1" stroke="none"/>
<g opacity="1">
<path d="M933.424 514.808C917.63 433.281 869.3 383.872 788.511 366.382C704.587 348.214 633.302 371.874 572.971 431.41C526.248 477.52 479.93 524.047 433.149 570.083C403.303 599.429 374.27 630.061 335.347 647.878C291.933 667.763 248.771 666.365 210.95 636.595C172.395 606.223 164.207 563.984 176.014 517.591C193.763 447.932 276.41 420.237 340.127 462.341C347.753 467.377 355.263 472.592 362.986 477.841C366.663 474.363 369.296 471.957 371.831 469.451C401.251 440.404 429.704 410.327 460.265 382.533C500.795 345.658 548.448 324.829 604.423 329.266C623.566 330.782 642.437 335.697 665.064 339.704C618.437 295.463 567.165 275.24 506.157 284.845C448.943 293.854 403.632 324.56 365.367 366.442C356.386 376.28 348.295 378.669 335.56 373.882C320.269 368.128 305.249 364.453 290.52 362.674L290.52 362.668C290.5 362.666 290.462 362.666 290.442 362.664C290.268 362.643 290.094 362.614 289.92 362.595C289.9 362.61 289.9 362.622 289.881 362.637C106.548 351.591 88.6638 511.202 88.6638 511.202C71.5924 686.897 191.518 722.839 191.518 722.839L191.576 722.839C206.112 728.585 221.17 732.645 236.519 735.788L236.538 735.819C236.538 735.819 239.325 736.536 244.474 737.335C245.848 737.589 247.222 737.854 248.596 738.095C248.635 738.039 248.674 737.987 248.693 737.931C276.197 741.42 347.405 743.49 432.626 691.86C432.8 691.868 432.994 691.851 433.168 691.866C487.866 637.142 542.603 582.455 597.533 527.979C623.817 501.92 647.721 472.872 682.212 456.086C736.194 429.821 803.008 442.342 834.035 485.929C858.674 520.529 861.578 558.329 843.848 596.118C825.383 635.448 792.131 656.737 748.93 658.027C689.509 659.802 629.992 659.094 570.532 658.976C557.739 658.951 547.809 662.849 538.906 672.148C520.344 691.562 500.989 710.23 482.098 729.338C479.485 731.968 474.937 735.811 470.814 740.441C476.756 741.082 483.782 741.288 487.266 741.292C555.009 741.352 622.753 741.817 690.496 741.12C724.02 740.774 758.414 742.569 790.853 735.916C890.262 715.536 953.012 615.898 933.424 514.808" fill="#073642" fill-rule="nonzero" opacity="1" stroke="none"/>
<path d="M364.692 552.822C364.692 600.053 326.386 638.34 279.119 638.34C231.852 638.34 193.528 600.053 193.528 552.822C193.528 505.592 231.852 467.303 279.119 467.303C326.386 467.303 364.692 505.592 364.692 552.822" fill="#073642" fill-rule="nonzero" opacity="1" stroke="none"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Created with Vectornator (http://vectornator.io/) -->
<svg stroke-miterlimit="10" style="fill-rule:nonzero;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;" version="1.1" viewBox="0 0 1024 1024" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs/>
<g id="Layer-1">
<path d="M0 512C0 229.23 229.23 0 512 0C794.77 0 1024 229.23 1024 512C1024 794.77 794.77 1024 512 1024C229.23 1024 0 794.77 0 512Z" fill="#fdf6e3" fill-rule="nonzero" opacity="1" stroke="none"/>
<g opacity="1">
<path d="M933.424 514.808C917.63 433.281 869.3 383.872 788.511 366.382C704.587 348.214 633.302 371.874 572.971 431.41C526.248 477.52 479.93 524.047 433.149 570.083C403.303 599.429 374.27 630.061 335.347 647.878C291.933 667.763 248.771 666.365 210.95 636.595C172.395 606.223 164.207 563.984 176.014 517.591C193.763 447.932 276.41 420.237 340.127 462.341C347.753 467.377 355.263 472.592 362.986 477.841C366.663 474.363 369.296 471.957 371.831 469.451C401.251 440.404 429.704 410.327 460.265 382.533C500.795 345.658 548.448 324.829 604.423 329.266C623.566 330.782 642.437 335.697 665.064 339.704C618.437 295.463 567.165 275.24 506.157 284.845C448.943 293.854 403.632 324.56 365.367 366.442C356.386 376.28 348.295 378.669 335.56 373.882C320.269 368.128 305.249 364.453 290.52 362.674L290.52 362.668C290.5 362.666 290.462 362.666 290.442 362.664C290.268 362.643 290.094 362.614 289.92 362.595C289.9 362.61 289.9 362.622 289.881 362.637C106.548 351.591 88.6638 511.202 88.6638 511.202C71.5924 686.897 191.518 722.839 191.518 722.839L191.576 722.839C206.112 728.585 221.17 732.645 236.519 735.788L236.538 735.819C236.538 735.819 239.325 736.536 244.474 737.335C245.848 737.589 247.222 737.854 248.596 738.095C248.635 738.039 248.674 737.987 248.693 737.931C276.197 741.42 347.405 743.49 432.626 691.86C432.8 691.868 432.994 691.851 433.168 691.866C487.866 637.142 542.603 582.455 597.533 527.979C623.817 501.92 647.721 472.872 682.212 456.086C736.194 429.821 803.008 442.342 834.035 485.929C858.674 520.529 861.578 558.329 843.848 596.118C825.383 635.448 792.131 656.737 748.93 658.027C689.509 659.802 629.992 659.094 570.532 658.976C557.739 658.951 547.809 662.849 538.906 672.148C520.344 691.562 500.989 710.23 482.098 729.338C479.485 731.968 474.937 735.811 470.814 740.441C476.756 741.082 483.782 741.288 487.266 741.292C555.009 741.352 622.753 741.817 690.496 741.12C724.02 740.774 758.414 742.569 790.853 735.916C890.262 715.536 953.012 615.898 933.424 514.808" fill="#073642" fill-rule="nonzero" opacity="1" stroke="none"/>
<path d="M364.692 552.822C364.692 600.053 326.386 638.34 279.119 638.34C231.852 638.34 193.528 600.053 193.528 552.822C193.528 505.592 231.852 467.303 279.119 467.303C326.386 467.303 364.692 505.592 364.692 552.822" fill="#073642" fill-rule="nonzero" opacity="1" stroke="none"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Created with Vectornator (http://vectornator.io/) -->
<svg style="fill-rule:nonzero;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;" version="1.1" viewBox="0 0 605.044 336.948" xmlns="http://www.w3.org/2000/svg" xmlns:vectornator="http://vectornator.io" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs/>
<g id="Logo" vectornator:layerName="Logo">
<g opacity="1">
<path d="M591.109 167.89C580.229 111.687 546.936 77.6261 491.282 65.5687C433.469 53.0447 384.362 69.3554 342.802 110.398C310.616 142.185 278.709 174.259 246.482 205.995C225.922 226.226 205.922 247.343 179.109 259.626C149.202 273.334 119.469 272.37 93.4157 251.847C66.8557 230.91 61.2157 201.791 69.349 169.809C81.5757 121.787 138.509 102.695 182.402 131.721C187.656 135.193 192.829 138.787 198.149 142.406C200.682 140.009 202.496 138.35 204.242 136.622C224.509 116.598 244.109 95.8634 265.162 76.7034C293.082 51.2821 325.909 36.9234 364.469 39.9821C377.656 41.0274 390.656 44.4154 406.242 47.1781C374.122 16.6794 338.802 2.73806 296.776 9.35939C257.362 15.5701 226.149 36.7381 199.789 65.6101C193.602 72.3927 188.029 74.0394 179.256 70.7394C168.722 66.7727 158.376 64.2394 148.229 63.0127L148.229 63.0087C148.216 63.0074 148.189 63.0074 148.176 63.0061C148.056 62.9914 147.936 62.9714 147.816 62.9581C147.802 62.9687 147.802 62.9767 147.789 62.9874C21.4957 55.3727 9.17567 165.405 9.17567 165.405C-2.58433 286.525 80.029 311.302 80.029 311.302L80.069 311.302C90.0823 315.263 100.456 318.062 111.029 320.229L111.042 320.25C111.042 320.25 112.962 320.745 116.509 321.295C117.456 321.47 118.402 321.653 119.349 321.819C119.376 321.781 119.402 321.745 119.416 321.706C138.362 324.111 187.416 325.538 246.122 289.946C246.242 289.951 246.376 289.939 246.496 289.95C284.176 252.225 321.882 214.525 359.722 176.97C377.829 159.006 394.296 138.981 418.056 127.409C455.242 109.302 501.269 117.934 522.642 147.982C539.616 171.834 541.616 197.893 529.402 223.943C516.682 251.057 493.776 265.733 464.016 266.622C423.082 267.846 382.082 267.358 341.122 267.277C332.309 267.259 325.469 269.946 319.336 276.357C306.549 289.741 293.216 302.61 280.202 315.782C278.402 317.595 275.269 320.245 272.429 323.437C276.522 323.878 281.362 324.021 283.762 324.023C330.429 324.065 377.096 324.385 423.762 323.905C446.856 323.666 470.549 324.903 492.896 320.317C561.376 306.267 604.602 237.579 591.109 167.89" fill="#142831" fill-rule="nonzero" opacity="1" stroke="none"/>
<path d="M202.896 194.097C202.896 228.629 174.909 256.622 140.376 256.622C105.842 256.622 77.8423 228.629 77.8423 194.097C77.8423 159.565 105.842 131.57 140.376 131.57C174.909 131.57 202.896 159.565 202.896 194.097" fill="#142831" fill-rule="nonzero" opacity="1" stroke="none"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Created with Vectornator (http://vectornator.io/) -->
<svg stroke-miterlimit="10" style="fill-rule:nonzero;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;" version="1.1" viewBox="0 0 605.044 336.948" xmlns="http://www.w3.org/2000/svg" xmlns:vectornator="http://vectornator.io" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs/>
<g id="Logo" vectornator:layerName="Logo">
<g opacity="1">
<path d="M591.109 167.89C580.229 111.687 546.936 77.6261 491.282 65.5687C433.469 53.0447 384.362 69.3554 342.802 110.398C310.616 142.185 278.709 174.259 246.482 205.995C225.922 226.226 205.922 247.343 179.109 259.626C149.202 273.334 119.469 272.37 93.4157 251.847C66.8557 230.91 61.2157 201.791 69.349 169.809C81.5757 121.787 138.509 102.695 182.402 131.721C187.656 135.193 192.829 138.787 198.149 142.406C200.682 140.009 202.496 138.35 204.242 136.622C224.509 116.598 244.109 95.8634 265.162 76.7034C293.082 51.2821 325.909 36.9234 364.469 39.9821C377.656 41.0274 390.656 44.4154 406.242 47.1781C374.122 16.6794 338.802 2.73806 296.776 9.35939C257.362 15.5701 226.149 36.7381 199.789 65.6101C193.602 72.3927 188.029 74.0394 179.256 70.7394C168.722 66.7727 158.376 64.2394 148.229 63.0127L148.229 63.0087C148.216 63.0074 148.189 63.0074 148.176 63.0061C148.056 62.9914 147.936 62.9714 147.816 62.9581C147.802 62.9687 147.802 62.9767 147.789 62.9874C21.4957 55.3727 9.17567 165.405 9.17567 165.405C-2.58433 286.525 80.029 311.302 80.029 311.302L80.069 311.302C90.0823 315.263 100.456 318.062 111.029 320.229L111.042 320.25C111.042 320.25 112.962 320.745 116.509 321.295C117.456 321.47 118.402 321.653 119.349 321.819C119.376 321.781 119.402 321.745 119.416 321.706C138.362 324.111 187.416 325.538 246.122 289.946C246.242 289.951 246.376 289.939 246.496 289.95C284.176 252.225 321.882 214.525 359.722 176.97C377.829 159.006 394.296 138.981 418.056 127.409C455.242 109.302 501.269 117.934 522.642 147.982C539.616 171.834 541.616 197.893 529.402 223.943C516.682 251.057 493.776 265.733 464.016 266.622C423.082 267.846 382.082 267.358 341.122 267.277C332.309 267.259 325.469 269.946 319.336 276.357C306.549 289.741 293.216 302.61 280.202 315.782C278.402 317.595 275.269 320.245 272.429 323.437C276.522 323.878 281.362 324.021 283.762 324.023C330.429 324.065 377.096 324.385 423.762 323.905C446.856 323.666 470.549 324.903 492.896 320.317C561.376 306.267 604.602 237.579 591.109 167.89" fill="#eee8d5" fill-rule="nonzero" opacity="1" stroke="none"/>
<path d="M202.896 194.097C202.896 228.629 174.909 256.622 140.376 256.622C105.842 256.622 77.8423 228.629 77.8423 194.097C77.8423 159.565 105.842 131.57 140.376 131.57C174.909 131.57 202.896 159.565 202.896 194.097" fill="#eee8d5" fill-rule="nonzero" opacity="1" stroke="none"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Created with Vectornator (http://vectornator.io/) -->
<svg stroke-miterlimit="10" style="fill-rule:nonzero;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;" version="1.1" viewBox="0 0 1024 1024" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs/>
<g id="Layer-1">
<path d="M0 512C0 229.23 229.23 0 512 0C794.77 0 1024 229.23 1024 512C1024 794.77 794.77 1024 512 1024C229.23 1024 0 794.77 0 512Z" fill="#fdf6e3" fill-rule="nonzero" opacity="1" stroke="none"/>
<g opacity="1">
<path d="M933.424 514.808C917.63 433.281 869.3 383.872 788.511 366.382C704.587 348.214 633.302 371.874 572.971 431.41C526.248 477.52 479.93 524.047 433.149 570.083C403.303 599.429 374.27 630.061 335.347 647.878C291.933 667.763 248.771 666.365 210.95 636.595C172.395 606.223 164.207 563.984 176.014 517.591C193.763 447.932 276.41 420.237 340.127 462.341C347.753 467.377 355.263 472.592 362.986 477.841C366.663 474.363 369.296 471.957 371.831 469.451C401.251 440.404 429.704 410.327 460.265 382.533C500.795 345.658 548.448 324.829 604.423 329.266C623.566 330.782 642.437 335.697 665.064 339.704C618.437 295.463 567.165 275.24 506.157 284.845C448.943 293.854 403.632 324.56 365.367 366.442C356.386 376.28 348.295 378.669 335.56 373.882C320.269 368.128 305.249 364.453 290.52 362.674L290.52 362.668C290.5 362.666 290.462 362.666 290.442 362.664C290.268 362.643 290.094 362.614 289.92 362.595C289.9 362.61 289.9 362.622 289.881 362.637C106.548 351.591 88.6638 511.202 88.6638 511.202C71.5924 686.897 191.518 722.839 191.518 722.839L191.576 722.839C206.112 728.585 221.17 732.645 236.519 735.788L236.538 735.819C236.538 735.819 239.325 736.536 244.474 737.335C245.848 737.589 247.222 737.854 248.596 738.095C248.635 738.039 248.674 737.987 248.693 737.931C276.197 741.42 347.405 743.49 432.626 691.86C432.8 691.868 432.994 691.851 433.168 691.866C487.866 637.142 542.603 582.455 597.533 527.979C623.817 501.92 647.721 472.872 682.212 456.086C736.194 429.821 803.008 442.342 834.035 485.929C858.674 520.529 861.578 558.329 843.848 596.118C825.383 635.448 792.131 656.737 748.93 658.027C689.509 659.802 629.992 659.094 570.532 658.976C557.739 658.951 547.809 662.849 538.906 672.148C520.344 691.562 500.989 710.23 482.098 729.338C479.485 731.968 474.937 735.811 470.814 740.441C476.756 741.082 483.782 741.288 487.266 741.292C555.009 741.352 622.753 741.817 690.496 741.12C724.02 740.774 758.414 742.569 790.853 735.916C890.262 715.536 953.012 615.898 933.424 514.808" fill="#073642" fill-rule="nonzero" opacity="1" stroke="none"/>
<path d="M364.692 552.822C364.692 600.053 326.386 638.34 279.119 638.34C231.852 638.34 193.528 600.053 193.528 552.822C193.528 505.592 231.852 467.303 279.119 467.303C326.386 467.303 364.692 505.592 364.692 552.822" fill="#073642" fill-rule="nonzero" opacity="1" stroke="none"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1,42 +0,0 @@
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}
@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}
.card {
padding: 2em;
}
.read-the-docs {
color: #888;
}

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