@cardelli/ambit 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/cli/commands/create/index.d.ts +2 -0
- package/esm/cli/commands/create/index.d.ts.map +1 -0
- package/esm/cli/commands/create/index.js +292 -0
- package/esm/cli/commands/create/machine.d.ts +33 -0
- package/esm/cli/commands/create/machine.d.ts.map +1 -0
- package/esm/cli/commands/create/machine.js +162 -0
- package/esm/cli/commands/deploy/index.d.ts +2 -0
- package/esm/cli/commands/deploy/index.d.ts.map +1 -0
- package/esm/cli/commands/deploy/index.js +290 -0
- package/esm/cli/commands/deploy/machine.d.ts +52 -0
- package/esm/cli/commands/deploy/machine.d.ts.map +1 -0
- package/esm/cli/commands/deploy/machine.js +116 -0
- package/esm/cli/commands/deploy/modes.d.ts +18 -0
- package/esm/cli/commands/deploy/modes.d.ts.map +1 -0
- package/esm/cli/commands/deploy/modes.js +152 -0
- package/esm/cli/commands/destroy/app.d.ts +2 -0
- package/esm/cli/commands/destroy/app.d.ts.map +1 -0
- package/esm/cli/commands/destroy/app.js +173 -0
- package/esm/cli/commands/destroy/index.d.ts +2 -0
- package/esm/cli/commands/destroy/index.d.ts.map +1 -0
- package/esm/cli/commands/destroy/index.js +63 -0
- package/esm/cli/commands/destroy/network.d.ts +2 -0
- package/esm/cli/commands/destroy/network.d.ts.map +1 -0
- package/esm/cli/commands/destroy/network.js +210 -0
- package/esm/cli/commands/doctor.d.ts.map +1 -0
- package/esm/cli/commands/doctor.js +295 -0
- package/esm/{src/cli → cli}/commands/list.d.ts.map +1 -1
- package/esm/{src/cli → cli}/commands/list.js +39 -54
- package/esm/cli/commands/status.d.ts.map +1 -0
- package/esm/cli/commands/status.js +331 -0
- package/esm/cli/mod.d.ts.map +1 -0
- package/esm/{src/cli → cli}/mod.js +4 -4
- package/esm/deno.d.ts +4 -18
- package/esm/deno.js +5 -19
- package/esm/deps/jsr.io/@std/path/1.1.4/constants.d.ts +1 -1
- package/esm/deps/jsr.io/@zod/zod/4.3.6/src/v4/core/json-schema-generator.d.ts +1 -1
- package/esm/lib/args.d.ts +11 -0
- package/esm/lib/args.d.ts.map +1 -0
- package/esm/lib/args.js +28 -0
- package/esm/lib/cli.d.ts +0 -2
- package/esm/lib/cli.d.ts.map +1 -1
- package/esm/lib/cli.js +41 -27
- package/esm/lib/command.d.ts +21 -49
- package/esm/lib/command.d.ts.map +1 -1
- package/esm/lib/command.js +55 -95
- package/esm/lib/machine.d.ts +11 -0
- package/esm/lib/machine.d.ts.map +1 -0
- package/esm/lib/machine.js +15 -0
- package/esm/lib/output.d.ts +3 -2
- package/esm/lib/output.d.ts.map +1 -1
- package/esm/lib/output.js +25 -11
- package/esm/lib/result.d.ts +18 -7
- package/esm/lib/result.d.ts.map +1 -1
- package/esm/lib/result.js +46 -1
- package/esm/main.d.ts +6 -6
- package/esm/main.d.ts.map +1 -1
- package/esm/main.js +7 -9
- package/esm/providers/fly.d.ts +81 -0
- package/esm/providers/fly.d.ts.map +1 -0
- package/esm/providers/fly.js +372 -0
- package/esm/providers/tailscale.d.ts +31 -0
- package/esm/providers/tailscale.d.ts.map +1 -0
- package/esm/providers/tailscale.js +150 -0
- package/esm/{src/schemas → schemas}/fly.d.ts +1 -11
- package/esm/schemas/fly.d.ts.map +1 -0
- package/esm/{src/schemas → schemas}/fly.js +14 -56
- package/esm/{src/schemas → schemas}/tailscale.d.ts +1 -2
- package/esm/schemas/tailscale.d.ts.map +1 -0
- package/esm/{src/schemas → schemas}/tailscale.js +2 -3
- package/esm/src/{docker/router → router}/Dockerfile +0 -11
- package/esm/src/router/start.sh +101 -0
- package/esm/util/constants.d.ts +13 -0
- package/esm/util/constants.d.ts.map +1 -0
- package/esm/util/constants.js +34 -0
- package/esm/{src → util}/credentials.d.ts +0 -1
- package/esm/util/credentials.d.ts.map +1 -0
- package/esm/{src → util}/credentials.js +3 -5
- package/esm/{src → util}/discovery.d.ts +20 -4
- package/esm/util/discovery.d.ts.map +1 -0
- package/esm/{src → util}/discovery.js +38 -15
- package/esm/util/fly-transforms.d.ts +27 -0
- package/esm/util/fly-transforms.d.ts.map +1 -0
- package/esm/util/fly-transforms.js +87 -0
- package/esm/{src → util}/guard.d.ts +1 -2
- package/esm/util/guard.d.ts.map +1 -0
- package/esm/{src → util}/guard.js +27 -27
- package/esm/util/naming.d.ts +5 -0
- package/esm/util/naming.d.ts.map +1 -0
- package/esm/util/naming.js +12 -0
- package/esm/{src → util}/resolve.d.ts +2 -3
- package/esm/util/resolve.d.ts.map +1 -0
- package/esm/{src → util}/resolve.js +1 -2
- package/esm/util/session.d.ts +16 -0
- package/esm/util/session.d.ts.map +1 -0
- package/esm/util/session.js +19 -0
- package/esm/util/tailscale-local.d.ts +13 -0
- package/esm/util/tailscale-local.d.ts.map +1 -0
- package/esm/util/tailscale-local.js +63 -0
- package/esm/{src → util}/template.d.ts +2 -4
- package/esm/util/template.d.ts.map +1 -0
- package/esm/{src → util}/template.js +14 -17
- package/package.json +1 -43
- package/esm/lib/paths.d.ts +0 -3
- package/esm/lib/paths.d.ts.map +0 -1
- package/esm/lib/paths.js +0 -5
- package/esm/src/cli/commands/create.d.ts +0 -2
- package/esm/src/cli/commands/create.d.ts.map +0 -1
- package/esm/src/cli/commands/create.js +0 -294
- package/esm/src/cli/commands/deploy.d.ts +0 -2
- package/esm/src/cli/commands/deploy.d.ts.map +0 -1
- package/esm/src/cli/commands/deploy.js +0 -426
- package/esm/src/cli/commands/destroy.d.ts +0 -2
- package/esm/src/cli/commands/destroy.d.ts.map +0 -1
- package/esm/src/cli/commands/destroy.js +0 -340
- package/esm/src/cli/commands/doctor.d.ts.map +0 -1
- package/esm/src/cli/commands/doctor.js +0 -141
- package/esm/src/cli/commands/status.d.ts.map +0 -1
- package/esm/src/cli/commands/status.js +0 -152
- package/esm/src/cli/mod.d.ts.map +0 -1
- package/esm/src/credentials.d.ts.map +0 -1
- package/esm/src/discovery.d.ts.map +0 -1
- package/esm/src/docker/router/start.sh +0 -146
- package/esm/src/guard.d.ts.map +0 -1
- package/esm/src/providers/fly.d.ts +0 -70
- package/esm/src/providers/fly.d.ts.map +0 -1
- package/esm/src/providers/fly.js +0 -411
- package/esm/src/providers/tailscale.d.ts +0 -31
- package/esm/src/providers/tailscale.d.ts.map +0 -1
- package/esm/src/providers/tailscale.js +0 -195
- package/esm/src/resolve.d.ts.map +0 -1
- package/esm/src/schemas/config.d.ts +0 -5
- package/esm/src/schemas/config.d.ts.map +0 -1
- package/esm/src/schemas/config.js +0 -22
- package/esm/src/schemas/fly.d.ts.map +0 -1
- package/esm/src/schemas/tailscale.d.ts.map +0 -1
- package/esm/src/template.d.ts.map +0 -1
- /package/esm/{src/cli → cli}/commands/doctor.d.ts +0 -0
- /package/esm/{src/cli → cli}/commands/list.d.ts +0 -0
- /package/esm/{src/cli → cli}/commands/status.d.ts +0 -0
- /package/esm/{src/cli → cli}/mod.d.ts +0 -0
- /package/esm/src/{docker/router → router}/fly.toml +0 -0
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
set -e
|
|
3
|
-
|
|
4
|
-
# =============================================================================
|
|
5
|
-
# ambit - Self-Configuring Tailscale Subnet Router
|
|
6
|
-
# =============================================================================
|
|
7
|
-
# State is persisted to /var/lib/tailscale via Fly volume.
|
|
8
|
-
# On first run: creates auth key (with tags), authenticates, approves routes.
|
|
9
|
-
# On restart: reuses existing state, no new device created.
|
|
10
|
-
# =============================================================================
|
|
11
|
-
|
|
12
|
-
echo "Router: Enabling IP Forwarding"
|
|
13
|
-
echo 'net.ipv4.ip_forward = 1' | tee -a /etc/sysctl.conf
|
|
14
|
-
echo 'net.ipv6.conf.all.forwarding = 1' | tee -a /etc/sysctl.conf
|
|
15
|
-
sysctl -p /etc/sysctl.conf
|
|
16
|
-
|
|
17
|
-
echo "Router: Starting Tailscaled"
|
|
18
|
-
/usr/local/bin/tailscaled \
|
|
19
|
-
--state=/var/lib/tailscale/tailscaled.state \
|
|
20
|
-
--socket=/var/run/tailscale/tailscaled.sock &
|
|
21
|
-
|
|
22
|
-
# Wait for tailscaled to be ready
|
|
23
|
-
sleep 3
|
|
24
|
-
|
|
25
|
-
echo "Router: Extracting Fly.io Subnet"
|
|
26
|
-
SUBNET=$(grep fly-local-6pn /etc/hosts | awk '{print $1}' | cut -d: -f1-3)::/48
|
|
27
|
-
echo "Router: Subnet ${SUBNET}"
|
|
28
|
-
|
|
29
|
-
if /usr/local/bin/tailscale status --json 2>/dev/null | jq -e '.BackendState == "Running"' > /dev/null 2>&1; then
|
|
30
|
-
echo "Router: Already Authenticated (Using Persisted State)"
|
|
31
|
-
|
|
32
|
-
/usr/local/bin/tailscale up \
|
|
33
|
-
--hostname="${FLY_APP_NAME:-ambit}" \
|
|
34
|
-
--advertise-routes="${SUBNET}"
|
|
35
|
-
else
|
|
36
|
-
# First run - need to authenticate
|
|
37
|
-
if [ -n "${TAILSCALE_API_TOKEN}" ]; then
|
|
38
|
-
echo "Router: Creating Auth Key (First Run)"
|
|
39
|
-
|
|
40
|
-
TAGS_JSON="[]"
|
|
41
|
-
if [ -n "${TAILSCALE_TAGS}" ]; then
|
|
42
|
-
TAGS_JSON=$(echo "${TAILSCALE_TAGS}" | jq -R 'split(",")')
|
|
43
|
-
fi
|
|
44
|
-
|
|
45
|
-
AUTH_KEY_RESPONSE=$(curl -s -X POST \
|
|
46
|
-
-u "${TAILSCALE_API_TOKEN}:" \
|
|
47
|
-
-H "Content-Type: application/json" \
|
|
48
|
-
-d "$(jq -n \
|
|
49
|
-
--argjson tags "${TAGS_JSON}" \
|
|
50
|
-
'{
|
|
51
|
-
capabilities: { devices: { create: {
|
|
52
|
-
reusable: false,
|
|
53
|
-
ephemeral: false,
|
|
54
|
-
preauthorized: true,
|
|
55
|
-
tags: $tags
|
|
56
|
-
}}},
|
|
57
|
-
expirySeconds: 300
|
|
58
|
-
}' | jq 'if .capabilities.devices.create.tags == [] then .capabilities.devices.create |= del(.tags) else . end')" \
|
|
59
|
-
"https://api.tailscale.com/api/v2/tailnet/-/keys")
|
|
60
|
-
|
|
61
|
-
TAILSCALE_AUTHKEY=$(echo "${AUTH_KEY_RESPONSE}" | jq -r '.key')
|
|
62
|
-
|
|
63
|
-
if [ -z "${TAILSCALE_AUTHKEY}" ] || [ "${TAILSCALE_AUTHKEY}" = "null" ]; then
|
|
64
|
-
echo "Router: ERROR - Failed to Create Auth Key"
|
|
65
|
-
echo "${AUTH_KEY_RESPONSE}"
|
|
66
|
-
exit 1
|
|
67
|
-
fi
|
|
68
|
-
|
|
69
|
-
echo "Router: Auth Key Created"
|
|
70
|
-
elif [ -z "${TAILSCALE_AUTHKEY}" ]; then
|
|
71
|
-
echo "Router: ERROR - No TAILSCALE_API_TOKEN or TAILSCALE_AUTHKEY Provided"
|
|
72
|
-
exit 1
|
|
73
|
-
fi
|
|
74
|
-
|
|
75
|
-
echo "Router: Authenticating to Tailscale"
|
|
76
|
-
/usr/local/bin/tailscale up \
|
|
77
|
-
--authkey="${TAILSCALE_AUTHKEY}" \
|
|
78
|
-
--hostname="${FLY_APP_NAME:-ambit}" \
|
|
79
|
-
--advertise-routes="${SUBNET}"
|
|
80
|
-
fi
|
|
81
|
-
|
|
82
|
-
echo "Router: Getting Node Key"
|
|
83
|
-
NODE_KEY=$(/usr/local/bin/tailscale status --json | jq -r '.Self.PublicKey')
|
|
84
|
-
echo "Router: Node Key ${NODE_KEY}"
|
|
85
|
-
|
|
86
|
-
# Self-approve routes if we have API access
|
|
87
|
-
# This is a fallback — if the user has autoApprovers configured in their
|
|
88
|
-
# Tailscale policy file, routes are approved automatically and this block
|
|
89
|
-
# is a no-op (routes are already enabled).
|
|
90
|
-
if [ -n "${TAILSCALE_API_TOKEN}" ]; then
|
|
91
|
-
echo "Router: Finding Device ID"
|
|
92
|
-
|
|
93
|
-
DEVICES_RESPONSE=$(curl -s \
|
|
94
|
-
-u "${TAILSCALE_API_TOKEN}:" \
|
|
95
|
-
"https://api.tailscale.com/api/v2/tailnet/-/devices")
|
|
96
|
-
|
|
97
|
-
DEVICE_ID=$(echo "${DEVICES_RESPONSE}" | jq -r ".devices[] | select(.nodeKey == \"${NODE_KEY}\") | .id")
|
|
98
|
-
|
|
99
|
-
if [ -n "${DEVICE_ID}" ] && [ "${DEVICE_ID}" != "null" ]; then
|
|
100
|
-
echo "Router: Device ID ${DEVICE_ID}"
|
|
101
|
-
echo "Router: Approving Subnet Routes"
|
|
102
|
-
|
|
103
|
-
curl -s -X POST \
|
|
104
|
-
-u "${TAILSCALE_API_TOKEN}:" \
|
|
105
|
-
-H "Content-Type: application/json" \
|
|
106
|
-
-d "{\"routes\": [\"${SUBNET}\"]}" \
|
|
107
|
-
"https://api.tailscale.com/api/v2/device/${DEVICE_ID}/routes" > /dev/null
|
|
108
|
-
|
|
109
|
-
echo "Router: Routes Approved"
|
|
110
|
-
else
|
|
111
|
-
echo "Router: WARNING - Could Not Find Device ID"
|
|
112
|
-
echo "Router: Routes May Need Manual Approval"
|
|
113
|
-
fi
|
|
114
|
-
fi
|
|
115
|
-
|
|
116
|
-
echo "Router: Fully Configured"
|
|
117
|
-
|
|
118
|
-
# Start SOCKS5 proxy for bidirectional tailnet access
|
|
119
|
-
PRIVATE_IP=$(grep fly-local-6pn /etc/hosts | awk '{print $1}')
|
|
120
|
-
echo "Router: Starting SOCKS5 Proxy on [${PRIVATE_IP}]:1080"
|
|
121
|
-
/usr/local/bin/microsocks -i "$PRIVATE_IP" -p 1080 &
|
|
122
|
-
|
|
123
|
-
echo "Router: Starting DNS Proxy"
|
|
124
|
-
|
|
125
|
-
# Generate Corefile for CoreDNS
|
|
126
|
-
# Rewrites NETWORK_NAME TLD to .flycast before forwarding to Fly DNS.
|
|
127
|
-
# .flycast resolves to the Flycast address (private_v6) which routes through
|
|
128
|
-
# Fly Proxy — enabling autostart/autostop and load balancing. The Flycast IP
|
|
129
|
-
# is within the network's /48 subnet so it's routable through the tailnet.
|
|
130
|
-
if [ -n "${NETWORK_NAME}" ]; then
|
|
131
|
-
echo "Router: DNS Rewrite ${NETWORK_NAME} -> flycast"
|
|
132
|
-
cat > /etc/coredns/Corefile <<EOF
|
|
133
|
-
.:53 {
|
|
134
|
-
rewrite name suffix .${NETWORK_NAME}. .flycast. answer auto
|
|
135
|
-
forward . fdaa::3
|
|
136
|
-
}
|
|
137
|
-
EOF
|
|
138
|
-
else
|
|
139
|
-
cat > /etc/coredns/Corefile <<EOF
|
|
140
|
-
.:53 {
|
|
141
|
-
forward . fdaa::3
|
|
142
|
-
}
|
|
143
|
-
EOF
|
|
144
|
-
fi
|
|
145
|
-
|
|
146
|
-
exec /usr/local/bin/coredns -conf /etc/coredns/Corefile
|
package/esm/src/guard.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/src/guard.ts"],"names":[],"mappings":"AAWA,OAAO,sBAAsB,CAAC;AAI9B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAqLtD;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,KAAG,OACN,CAAC;AAMtC,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjE,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAMD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAOjD;AAMD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,CAwDhE;AAMD;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,iBAAiB,CAAC,CAwF5B"}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import "../../_dnt.polyfills.js";
|
|
2
|
-
import { type FlyApp, type FlyAppInfo, type FlyIp, type FlyMachine } from "../schemas/fly.js";
|
|
3
|
-
/**
|
|
4
|
-
* Thrown when a `fly deploy` command fails. Carries the raw stderr so callers
|
|
5
|
-
* can surface it through `out` (respecting JSON mode) instead of printing
|
|
6
|
-
* directly.
|
|
7
|
-
*/
|
|
8
|
-
export declare class FlyDeployError extends Error {
|
|
9
|
-
/** Last meaningful line from flyctl stderr. */
|
|
10
|
-
readonly detail: string;
|
|
11
|
-
constructor(app: string, stderr: string);
|
|
12
|
-
}
|
|
13
|
-
export type MachineSize = "shared-cpu-1x" | "shared-cpu-2x" | "shared-cpu-4x";
|
|
14
|
-
export interface MachineConfig {
|
|
15
|
-
size: MachineSize;
|
|
16
|
-
memoryMb?: number;
|
|
17
|
-
region?: string;
|
|
18
|
-
autoStopSeconds?: number;
|
|
19
|
-
}
|
|
20
|
-
export declare const getSizeConfig: (size: MachineSize) => {
|
|
21
|
-
cpus: number;
|
|
22
|
-
memoryMb: number;
|
|
23
|
-
};
|
|
24
|
-
export interface MachineResult {
|
|
25
|
-
id: string;
|
|
26
|
-
state: string;
|
|
27
|
-
size: string;
|
|
28
|
-
region: string;
|
|
29
|
-
privateIp?: string;
|
|
30
|
-
}
|
|
31
|
-
export interface SafeDeployOptions {
|
|
32
|
-
image?: string;
|
|
33
|
-
config?: string;
|
|
34
|
-
region?: string;
|
|
35
|
-
}
|
|
36
|
-
export interface FlyProvider {
|
|
37
|
-
ensureInstalled(): Promise<void>;
|
|
38
|
-
ensureAuth(options?: {
|
|
39
|
-
interactive?: boolean;
|
|
40
|
-
}): Promise<string>;
|
|
41
|
-
listOrgs(): Promise<Record<string, string>>;
|
|
42
|
-
createApp(name: string, org: string, options?: {
|
|
43
|
-
network?: string;
|
|
44
|
-
}): Promise<void>;
|
|
45
|
-
deleteApp(name: string): Promise<void>;
|
|
46
|
-
listApps(org?: string): Promise<FlyApp[]>;
|
|
47
|
-
appExists(name: string): Promise<boolean>;
|
|
48
|
-
listMachines(app: string): Promise<FlyMachine[]>;
|
|
49
|
-
listMachinesMapped(app: string): Promise<MachineResult[]>;
|
|
50
|
-
createMachine(app: string, config: MachineConfig): Promise<MachineResult>;
|
|
51
|
-
destroyMachine(app: string, machineId: string): Promise<void>;
|
|
52
|
-
setSecrets(app: string, secrets: Record<string, string>, options?: {
|
|
53
|
-
stage?: boolean;
|
|
54
|
-
}): Promise<void>;
|
|
55
|
-
routerDeploy(app: string, dockerfilePath: string, config?: {
|
|
56
|
-
region?: string;
|
|
57
|
-
}): Promise<void>;
|
|
58
|
-
listIps(app: string): Promise<FlyIp[]>;
|
|
59
|
-
releaseIp(app: string, address: string): Promise<void>;
|
|
60
|
-
allocateFlycastIp(app: string, network: string): Promise<void>;
|
|
61
|
-
getConfig(app: string): Promise<Record<string, unknown> | null>;
|
|
62
|
-
deploySafe(app: string, options: SafeDeployOptions): Promise<void>;
|
|
63
|
-
listCerts(app: string): Promise<string[]>;
|
|
64
|
-
removeCert(app: string, hostname: string): Promise<void>;
|
|
65
|
-
getFlyToken(): Promise<string>;
|
|
66
|
-
listAppsWithNetwork(org: string): Promise<FlyAppInfo[]>;
|
|
67
|
-
}
|
|
68
|
-
export declare const createFlyProvider: () => FlyProvider;
|
|
69
|
-
export declare const getRouterAppName: (network: string, randomSuffix: string) => string;
|
|
70
|
-
//# sourceMappingURL=fly.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fly.d.ts","sourceRoot":"","sources":["../../../src/src/providers/fly.ts"],"names":[],"mappings":"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"}
|
package/esm/src/providers/fly.js
DELETED
|
@@ -1,411 +0,0 @@
|
|
|
1
|
-
// =============================================================================
|
|
2
|
-
// Fly.io Provider - Wraps flyctl CLI
|
|
3
|
-
// =============================================================================
|
|
4
|
-
import "../../_dnt.polyfills.js";
|
|
5
|
-
import * as dntShim from "../../_dnt.shims.js";
|
|
6
|
-
import { runCommand, runCommandJson, runInteractive, runQuiet, } from "../../lib/command.js";
|
|
7
|
-
import { commandExists, die, Spinner } from "../../lib/cli.js";
|
|
8
|
-
import { dirname, resolve } from "../../deps/jsr.io/@std/path/1.1.4/mod.js";
|
|
9
|
-
import { FlyAppInfoListSchema, FlyAppsListSchema, FlyAuthSchema, FlyIpListSchema, FlyMachinesListSchema, FlyOrgsSchema, FlyStatusSchema, mapFlyMachineSize, mapFlyMachineState, } from "../schemas/fly.js";
|
|
10
|
-
import { fileExists } from "../../lib/cli.js";
|
|
11
|
-
// =============================================================================
|
|
12
|
-
// Constants
|
|
13
|
-
// =============================================================================
|
|
14
|
-
const ROUTER_APP_PREFIX = "ambit-";
|
|
15
|
-
// =============================================================================
|
|
16
|
-
// Deploy Error
|
|
17
|
-
// =============================================================================
|
|
18
|
-
/**
|
|
19
|
-
* Thrown when a `fly deploy` command fails. Carries the raw stderr so callers
|
|
20
|
-
* can surface it through `out` (respecting JSON mode) instead of printing
|
|
21
|
-
* directly.
|
|
22
|
-
*/
|
|
23
|
-
export class FlyDeployError extends Error {
|
|
24
|
-
/** Last meaningful line from flyctl stderr. */
|
|
25
|
-
detail;
|
|
26
|
-
constructor(app, stderr) {
|
|
27
|
-
const detail = extractErrorDetail(stderr);
|
|
28
|
-
super(`Deploy Failed for '${app}'`);
|
|
29
|
-
this.name = "FlyDeployError";
|
|
30
|
-
this.detail = detail;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Pull the last non-empty, non-decoration line from fly stderr.
|
|
35
|
-
* Fly often prints progress lines then the actual error at the end.
|
|
36
|
-
*/
|
|
37
|
-
const extractErrorDetail = (stderr) => {
|
|
38
|
-
const lines = stderr
|
|
39
|
-
.split("\n")
|
|
40
|
-
.map((l) => l.replace(/\x1b\[[0-9;]*m/g, "").trim())
|
|
41
|
-
.filter((l) => l.length > 0 && !l.startsWith("-->") && l !== "Error");
|
|
42
|
-
return lines[lines.length - 1] ?? "unknown error";
|
|
43
|
-
};
|
|
44
|
-
export const getSizeConfig = (size) => {
|
|
45
|
-
switch (size) {
|
|
46
|
-
case "shared-cpu-1x":
|
|
47
|
-
return { cpus: 1, memoryMb: 1024 };
|
|
48
|
-
case "shared-cpu-2x":
|
|
49
|
-
return { cpus: 2, memoryMb: 2048 };
|
|
50
|
-
case "shared-cpu-4x":
|
|
51
|
-
return { cpus: 4, memoryMb: 4096 };
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
// =============================================================================
|
|
55
|
-
// Create Fly Provider
|
|
56
|
-
// =============================================================================
|
|
57
|
-
export const createFlyProvider = () => {
|
|
58
|
-
return {
|
|
59
|
-
async ensureInstalled() {
|
|
60
|
-
if (!(await commandExists("fly"))) {
|
|
61
|
-
return die("Flyctl Not Found. Install from https://fly.io/docs/flyctl/install/");
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
async ensureAuth(options) {
|
|
65
|
-
const interactive = options?.interactive ?? true;
|
|
66
|
-
const result = await runCommand(["fly", "auth", "whoami", "--json"]);
|
|
67
|
-
if (result.success) {
|
|
68
|
-
try {
|
|
69
|
-
const parsed = FlyAuthSchema.safeParse(JSON.parse(result.stdout));
|
|
70
|
-
if (parsed.success) {
|
|
71
|
-
return parsed.data.email;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
catch {
|
|
75
|
-
// Parse failed, need to authenticate
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
if (!interactive) {
|
|
79
|
-
return die("Not Authenticated with Fly.io. Run 'fly auth login' First");
|
|
80
|
-
}
|
|
81
|
-
const loginResult = await runInteractive(["fly", "auth", "login"]);
|
|
82
|
-
if (!loginResult.success) {
|
|
83
|
-
return die("Fly.io Authentication Failed");
|
|
84
|
-
}
|
|
85
|
-
const checkResult = await runCommand(["fly", "auth", "whoami", "--json"]);
|
|
86
|
-
if (!checkResult.success) {
|
|
87
|
-
return die("Fly.io Authentication Verification Failed");
|
|
88
|
-
}
|
|
89
|
-
const parsed = FlyAuthSchema.safeParse(JSON.parse(checkResult.stdout));
|
|
90
|
-
if (!parsed.success || !parsed.data) {
|
|
91
|
-
return die("Fly.io Authentication Response Invalid");
|
|
92
|
-
}
|
|
93
|
-
return parsed.data.email;
|
|
94
|
-
},
|
|
95
|
-
async listOrgs() {
|
|
96
|
-
const result = await runCommandJson(["fly", "orgs", "list", "--json"]);
|
|
97
|
-
if (!result.success || !result.data) {
|
|
98
|
-
return die("Failed to List Organizations");
|
|
99
|
-
}
|
|
100
|
-
const parsed = FlyOrgsSchema.safeParse(result.data);
|
|
101
|
-
if (!parsed.success) {
|
|
102
|
-
return die("Failed to Parse Organizations");
|
|
103
|
-
}
|
|
104
|
-
return parsed.data;
|
|
105
|
-
},
|
|
106
|
-
async listApps(org) {
|
|
107
|
-
const args = ["fly", "apps", "list", "--json"];
|
|
108
|
-
if (org) {
|
|
109
|
-
args.push("--org", org);
|
|
110
|
-
}
|
|
111
|
-
const result = await runCommand(args);
|
|
112
|
-
if (!result.success) {
|
|
113
|
-
return [];
|
|
114
|
-
}
|
|
115
|
-
try {
|
|
116
|
-
const parsed = FlyAppsListSchema.safeParse(JSON.parse(result.stdout));
|
|
117
|
-
return parsed.success ? parsed.data : [];
|
|
118
|
-
}
|
|
119
|
-
catch {
|
|
120
|
-
return [];
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
async createApp(name, org, options) {
|
|
124
|
-
const args = ["fly", "apps", "create", name, "--org", org, "--json"];
|
|
125
|
-
if (options?.network) {
|
|
126
|
-
args.push("--network", options.network);
|
|
127
|
-
}
|
|
128
|
-
const result = await runQuiet("Creating App", args);
|
|
129
|
-
if (!result.success) {
|
|
130
|
-
return die(`Failed to Create App '${name}'`);
|
|
131
|
-
}
|
|
132
|
-
},
|
|
133
|
-
async deleteApp(name) {
|
|
134
|
-
const result = await runQuiet("Deleting App", [
|
|
135
|
-
"fly",
|
|
136
|
-
"apps",
|
|
137
|
-
"destroy",
|
|
138
|
-
name,
|
|
139
|
-
"--yes",
|
|
140
|
-
]);
|
|
141
|
-
if (!result.success) {
|
|
142
|
-
return die(`Failed to Delete App '${name}'`);
|
|
143
|
-
}
|
|
144
|
-
},
|
|
145
|
-
async appExists(name) {
|
|
146
|
-
const result = await runCommand(["fly", "status", "-a", name, "--json"]);
|
|
147
|
-
if (!result.success)
|
|
148
|
-
return false;
|
|
149
|
-
try {
|
|
150
|
-
const parsed = FlyStatusSchema.safeParse(JSON.parse(result.stdout));
|
|
151
|
-
return parsed.success && !!parsed.data.ID;
|
|
152
|
-
}
|
|
153
|
-
catch {
|
|
154
|
-
return false;
|
|
155
|
-
}
|
|
156
|
-
},
|
|
157
|
-
async listMachines(app) {
|
|
158
|
-
const result = await runCommandJson(["fly", "machines", "list", "-a", app, "--json"]);
|
|
159
|
-
if (!result.success || !result.data) {
|
|
160
|
-
return [];
|
|
161
|
-
}
|
|
162
|
-
const parsed = FlyMachinesListSchema.safeParse(result.data);
|
|
163
|
-
return parsed.success ? parsed.data : [];
|
|
164
|
-
},
|
|
165
|
-
async listMachinesMapped(app) {
|
|
166
|
-
const raw = await this.listMachines(app);
|
|
167
|
-
return raw.map((m) => ({
|
|
168
|
-
id: m.id,
|
|
169
|
-
state: mapFlyMachineState(m.state),
|
|
170
|
-
size: mapFlyMachineSize(m.config?.guest),
|
|
171
|
-
region: m.region,
|
|
172
|
-
privateIp: m.private_ip,
|
|
173
|
-
}));
|
|
174
|
-
},
|
|
175
|
-
async createMachine(app, config) {
|
|
176
|
-
const existingMachines = await this.listMachinesMapped(app);
|
|
177
|
-
if (existingMachines.length === 0) {
|
|
178
|
-
return die("No Existing Machine to Clone. Run 'fly deploy' First");
|
|
179
|
-
}
|
|
180
|
-
const sourceMachine = existingMachines[0];
|
|
181
|
-
const sizeConfig = getSizeConfig(config.size);
|
|
182
|
-
const memoryMb = config.memoryMb ?? sizeConfig.memoryMb;
|
|
183
|
-
const args = [
|
|
184
|
-
"fly",
|
|
185
|
-
"machine",
|
|
186
|
-
"clone",
|
|
187
|
-
sourceMachine.id,
|
|
188
|
-
"-a",
|
|
189
|
-
app,
|
|
190
|
-
"--vm-cpus",
|
|
191
|
-
String(sizeConfig.cpus),
|
|
192
|
-
"--vm-memory",
|
|
193
|
-
String(memoryMb),
|
|
194
|
-
];
|
|
195
|
-
if (config.region) {
|
|
196
|
-
args.push("--region", config.region);
|
|
197
|
-
}
|
|
198
|
-
const spinner = new Spinner();
|
|
199
|
-
spinner.start(`Creating ${config.size} Machine`);
|
|
200
|
-
const result = await runCommand(args);
|
|
201
|
-
if (!result.success) {
|
|
202
|
-
spinner.fail("Machine Creation Failed");
|
|
203
|
-
return die(result.stderr || "Unknown Error");
|
|
204
|
-
}
|
|
205
|
-
spinner.success(`Created ${config.size} Machine`);
|
|
206
|
-
const machines = await this.listMachinesMapped(app);
|
|
207
|
-
const newest = machines[machines.length - 1];
|
|
208
|
-
if (!newest) {
|
|
209
|
-
return die("Created Machine Not Found");
|
|
210
|
-
}
|
|
211
|
-
return newest;
|
|
212
|
-
},
|
|
213
|
-
async destroyMachine(app, machineId) {
|
|
214
|
-
const shortId = machineId.slice(0, 8);
|
|
215
|
-
const result = await runQuiet(`Destroying Machine ${shortId}`, [
|
|
216
|
-
"fly",
|
|
217
|
-
"machines",
|
|
218
|
-
"destroy",
|
|
219
|
-
machineId,
|
|
220
|
-
"-a",
|
|
221
|
-
app,
|
|
222
|
-
"--force",
|
|
223
|
-
]);
|
|
224
|
-
if (!result.success) {
|
|
225
|
-
return die(`Failed to Destroy Machine '${shortId}'`);
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
async setSecrets(app, secrets, options) {
|
|
229
|
-
const pairs = Object.entries(secrets)
|
|
230
|
-
.filter(([_, v]) => v !== undefined && v !== "")
|
|
231
|
-
.map(([k, v]) => `${k}=${v}`);
|
|
232
|
-
if (pairs.length === 0)
|
|
233
|
-
return;
|
|
234
|
-
const args = ["fly", "secrets", "set", ...pairs, "-a", app];
|
|
235
|
-
if (options?.stage) {
|
|
236
|
-
args.push("--stage");
|
|
237
|
-
}
|
|
238
|
-
const result = await runQuiet(`Setting ${pairs.length} Secret(s)`, args);
|
|
239
|
-
if (!result.success) {
|
|
240
|
-
return die("Failed to Set Secrets");
|
|
241
|
-
}
|
|
242
|
-
},
|
|
243
|
-
async routerDeploy(app, dockerDir, config) {
|
|
244
|
-
const args = [
|
|
245
|
-
"fly",
|
|
246
|
-
"deploy",
|
|
247
|
-
dockerDir,
|
|
248
|
-
"-a",
|
|
249
|
-
app,
|
|
250
|
-
"--yes",
|
|
251
|
-
"--ha=false",
|
|
252
|
-
];
|
|
253
|
-
if (config?.region) {
|
|
254
|
-
args.push("--primary-region", config.region);
|
|
255
|
-
}
|
|
256
|
-
const result = await runCommand(args);
|
|
257
|
-
if (!result.success) {
|
|
258
|
-
throw new FlyDeployError(app, result.stderr);
|
|
259
|
-
}
|
|
260
|
-
},
|
|
261
|
-
async listIps(app) {
|
|
262
|
-
const result = await runCommand([
|
|
263
|
-
"fly",
|
|
264
|
-
"ips",
|
|
265
|
-
"list",
|
|
266
|
-
"-a",
|
|
267
|
-
app,
|
|
268
|
-
"--json",
|
|
269
|
-
]);
|
|
270
|
-
if (!result.success)
|
|
271
|
-
return [];
|
|
272
|
-
try {
|
|
273
|
-
const parsed = FlyIpListSchema.safeParse(JSON.parse(result.stdout));
|
|
274
|
-
return parsed.success ? parsed.data : [];
|
|
275
|
-
}
|
|
276
|
-
catch {
|
|
277
|
-
return [];
|
|
278
|
-
}
|
|
279
|
-
},
|
|
280
|
-
async releaseIp(app, address) {
|
|
281
|
-
const result = await runCommand([
|
|
282
|
-
"fly",
|
|
283
|
-
"ips",
|
|
284
|
-
"release",
|
|
285
|
-
address,
|
|
286
|
-
"-a",
|
|
287
|
-
app,
|
|
288
|
-
]);
|
|
289
|
-
if (!result.success) {
|
|
290
|
-
return die(`Failed to Release IP ${address} from '${app}'`);
|
|
291
|
-
}
|
|
292
|
-
},
|
|
293
|
-
async allocateFlycastIp(app, network) {
|
|
294
|
-
const result = await runCommand([
|
|
295
|
-
"fly",
|
|
296
|
-
"ips",
|
|
297
|
-
"allocate-v6",
|
|
298
|
-
"--private",
|
|
299
|
-
"--network",
|
|
300
|
-
network,
|
|
301
|
-
"-a",
|
|
302
|
-
app,
|
|
303
|
-
]);
|
|
304
|
-
if (!result.success) {
|
|
305
|
-
return die(`Failed to Allocate Flycast IP on Network '${network}'`);
|
|
306
|
-
}
|
|
307
|
-
},
|
|
308
|
-
async getConfig(app) {
|
|
309
|
-
const result = await runCommand(["fly", "config", "show", "-a", app]);
|
|
310
|
-
if (!result.success)
|
|
311
|
-
return null;
|
|
312
|
-
try {
|
|
313
|
-
return JSON.parse(result.stdout);
|
|
314
|
-
}
|
|
315
|
-
catch {
|
|
316
|
-
return null;
|
|
317
|
-
}
|
|
318
|
-
},
|
|
319
|
-
async deploySafe(app, options) {
|
|
320
|
-
const args = ["fly", "deploy"];
|
|
321
|
-
// When config is provided, use its parent directory as the build context
|
|
322
|
-
// so fly deploy finds the Dockerfile and COPY picks up the correct files
|
|
323
|
-
if (options.config) {
|
|
324
|
-
const configAbs = resolve(options.config);
|
|
325
|
-
args.push(dirname(configAbs));
|
|
326
|
-
args.push("--config", configAbs);
|
|
327
|
-
}
|
|
328
|
-
args.push("-a", app, "--yes", "--no-public-ips");
|
|
329
|
-
if (options.image) {
|
|
330
|
-
args.push("--image", options.image);
|
|
331
|
-
}
|
|
332
|
-
if (options.region) {
|
|
333
|
-
args.push("--primary-region", options.region);
|
|
334
|
-
}
|
|
335
|
-
const result = await runCommand(args);
|
|
336
|
-
if (!result.success) {
|
|
337
|
-
throw new FlyDeployError(app, result.stderr);
|
|
338
|
-
}
|
|
339
|
-
},
|
|
340
|
-
async listCerts(app) {
|
|
341
|
-
const result = await runCommand([
|
|
342
|
-
"fly",
|
|
343
|
-
"certs",
|
|
344
|
-
"list",
|
|
345
|
-
"-a",
|
|
346
|
-
app,
|
|
347
|
-
"--json",
|
|
348
|
-
]);
|
|
349
|
-
if (!result.success)
|
|
350
|
-
return [];
|
|
351
|
-
try {
|
|
352
|
-
const certs = JSON.parse(result.stdout);
|
|
353
|
-
return certs
|
|
354
|
-
.map((c) => c.Hostname)
|
|
355
|
-
.filter((h) => typeof h === "string");
|
|
356
|
-
}
|
|
357
|
-
catch {
|
|
358
|
-
return [];
|
|
359
|
-
}
|
|
360
|
-
},
|
|
361
|
-
async removeCert(app, hostname) {
|
|
362
|
-
await runCommand([
|
|
363
|
-
"fly",
|
|
364
|
-
"certs",
|
|
365
|
-
"remove",
|
|
366
|
-
hostname,
|
|
367
|
-
"-a",
|
|
368
|
-
app,
|
|
369
|
-
"--yes",
|
|
370
|
-
]);
|
|
371
|
-
},
|
|
372
|
-
async getFlyToken() {
|
|
373
|
-
// Read access_token from ~/.fly/config.yml
|
|
374
|
-
const home = dntShim.Deno.env.get("HOME") || dntShim.Deno.env.get("USERPROFILE") || "";
|
|
375
|
-
const configPath = `${home}/.fly/config.yml`;
|
|
376
|
-
if (!(await fileExists(configPath))) {
|
|
377
|
-
return die("Fly Config Not Found at ~/.fly/config.yml. Run 'fly auth login' First");
|
|
378
|
-
}
|
|
379
|
-
const content = await dntShim.Deno.readTextFile(configPath);
|
|
380
|
-
const match = content.match(/access_token:\s*(.+)/);
|
|
381
|
-
if (!match || !match[1]) {
|
|
382
|
-
return die("No Access Token Found in ~/.fly/config.yml. Run 'fly auth login' First");
|
|
383
|
-
}
|
|
384
|
-
return match[1].trim();
|
|
385
|
-
},
|
|
386
|
-
async listAppsWithNetwork(org) {
|
|
387
|
-
const token = await this.getFlyToken();
|
|
388
|
-
const response = await fetch(`https://api.machines.dev/v1/apps?org_slug=${encodeURIComponent(org)}`, {
|
|
389
|
-
headers: {
|
|
390
|
-
Authorization: `Bearer ${token}`,
|
|
391
|
-
"Content-Type": "application/json",
|
|
392
|
-
},
|
|
393
|
-
});
|
|
394
|
-
if (!response.ok) {
|
|
395
|
-
return die(`Failed to List Apps via REST API: HTTP ${response.status}`);
|
|
396
|
-
}
|
|
397
|
-
const data = await response.json();
|
|
398
|
-
const parsed = FlyAppInfoListSchema.safeParse(data);
|
|
399
|
-
if (!parsed.success) {
|
|
400
|
-
return die("Failed to Parse Apps REST API Response");
|
|
401
|
-
}
|
|
402
|
-
return parsed.data.apps;
|
|
403
|
-
},
|
|
404
|
-
};
|
|
405
|
-
};
|
|
406
|
-
// =============================================================================
|
|
407
|
-
// Router App Naming
|
|
408
|
-
// =============================================================================
|
|
409
|
-
export const getRouterAppName = (network, randomSuffix) => {
|
|
410
|
-
return `${ROUTER_APP_PREFIX}${network}-${randomSuffix}`;
|
|
411
|
-
};
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import "../../_dnt.polyfills.js";
|
|
2
|
-
import { type AuthKeyCapabilities, type TailscaleDevice } from "../schemas/tailscale.js";
|
|
3
|
-
export interface TailscaleProvider {
|
|
4
|
-
validateApiKey(): Promise<boolean>;
|
|
5
|
-
createAuthKey(opts?: AuthKeyCapabilities): Promise<string>;
|
|
6
|
-
listDevices(): Promise<TailscaleDevice[]>;
|
|
7
|
-
getDeviceByHostname(hostname: string): Promise<TailscaleDevice | null>;
|
|
8
|
-
deleteDevice(id: string): Promise<void>;
|
|
9
|
-
approveSubnetRoutes(deviceId: string, routes: string[]): Promise<void>;
|
|
10
|
-
setSplitDns(domain: string, nameservers: string[]): Promise<void>;
|
|
11
|
-
clearSplitDns(domain: string): Promise<void>;
|
|
12
|
-
getPolicyFile(): Promise<Record<string, unknown> | null>;
|
|
13
|
-
isTagOwnerConfigured(tag: string): Promise<boolean>;
|
|
14
|
-
isAutoApproverConfigured(tag: string): Promise<boolean>;
|
|
15
|
-
}
|
|
16
|
-
export declare const createTailscaleProvider: (tailnet: string, apiKey: string) => TailscaleProvider;
|
|
17
|
-
export declare const waitForDevice: (provider: TailscaleProvider, hostname: string, timeoutMs?: number) => Promise<TailscaleDevice>;
|
|
18
|
-
/**
|
|
19
|
-
* Check if the tailscale CLI is installed.
|
|
20
|
-
*/
|
|
21
|
-
export declare const isTailscaleInstalled: () => Promise<boolean>;
|
|
22
|
-
/**
|
|
23
|
-
* Check if accept-routes is enabled on the local client.
|
|
24
|
-
*/
|
|
25
|
-
export declare const isAcceptRoutesEnabled: () => Promise<boolean>;
|
|
26
|
-
/**
|
|
27
|
-
* Enable accept-routes on the local client.
|
|
28
|
-
* Returns true if successful, false if it failed (likely permissions).
|
|
29
|
-
*/
|
|
30
|
-
export declare const enableAcceptRoutes: () => Promise<boolean>;
|
|
31
|
-
//# sourceMappingURL=tailscale.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tailscale.d.ts","sourceRoot":"","sources":["../../../src/src/providers/tailscale.ts"],"names":[],"mappings":"AAGA,OAAO,yBAAyB,CAAC;AAKjC,OAAO,EACL,KAAK,mBAAmB,EAExB,KAAK,eAAe,EAErB,MAAM,yBAAyB,CAAC;AAYjC,MAAM,WAAW,iBAAiB;IAChC,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,aAAa,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3D,WAAW,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IAC1C,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IACvE,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;IACzD,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpD,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACzD;AAiBD,eAAO,MAAM,uBAAuB,GAClC,SAAS,MAAM,EACf,QAAQ,MAAM,KACb,iBAoMF,CAAC;AAMF,eAAO,MAAM,aAAa,GACxB,UAAU,iBAAiB,EAC3B,UAAU,MAAM,EAChB,YAAW,MAAe,KACzB,OAAO,CAAC,eAAe,CAazB,CAAC;AAMF;;GAEG;AACH,eAAO,MAAM,oBAAoB,QAAa,OAAO,CAAC,OAAO,CAE5D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,QAAa,OAAO,CAAC,OAAO,CAY7D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAa,OAAO,CAAC,OAAO,CAG1D,CAAC"}
|