@homeflare/alchemy 0.36.0 → 0.37.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/README.md +14 -0
- package/dist/argocd/cluster.d.ts +102 -0
- package/dist/argocd/cluster.d.ts.map +1 -0
- package/dist/argocd/credentials.d.ts +37 -0
- package/dist/argocd/credentials.d.ts.map +1 -0
- package/dist/argocd/fake-argocd.d.ts +42 -0
- package/dist/argocd/fake-argocd.d.ts.map +1 -0
- package/dist/argocd/git-credentials.d.ts +29 -0
- package/dist/argocd/git-credentials.d.ts.map +1 -0
- package/dist/argocd/index.d.ts +19 -0
- package/dist/argocd/index.d.ts.map +1 -0
- package/dist/argocd/index.js +306 -0
- package/dist/argocd/index.js.map +17 -0
- package/dist/argocd/providers.d.ts +13 -0
- package/dist/argocd/providers.d.ts.map +1 -0
- package/dist/argocd/repo-creds.d.ts +67 -0
- package/dist/argocd/repo-creds.d.ts.map +1 -0
- package/dist/argocd/repository.d.ts +87 -0
- package/dist/argocd/repository.d.ts.map +1 -0
- package/dist/argocd/resource.d.ts +90 -0
- package/dist/argocd/resource.d.ts.map +1 -0
- package/dist/cloudflare/index.js +4 -4
- package/dist/cloudflare/index.js.map +3 -3
- package/dist/cloudflare/r2-bucket-lock.d.ts +14 -5
- package/dist/cloudflare/r2-bucket-lock.d.ts.map +1 -1
- package/dist/litellm/index.js.map +2 -2
- package/dist/litellm/operations.d.ts.map +1 -1
- package/dist/proxmox/ceph-daemon-form.d.ts +4 -5
- package/dist/proxmox/ceph-daemon-form.d.ts.map +1 -1
- package/dist/proxmox/ceph-daemon-wire.d.ts +33 -0
- package/dist/proxmox/ceph-daemon-wire.d.ts.map +1 -0
- package/dist/proxmox/ceph-daemon.d.ts +35 -0
- package/dist/proxmox/ceph-daemon.d.ts.map +1 -1
- package/dist/proxmox/ceph-fs-distilled.d.ts +14 -0
- package/dist/proxmox/ceph-fs-distilled.d.ts.map +1 -0
- package/dist/proxmox/ceph-fs-wire.d.ts +20 -11
- package/dist/proxmox/ceph-fs-wire.d.ts.map +1 -1
- package/dist/proxmox/ceph-fs.d.ts +31 -6
- package/dist/proxmox/ceph-fs.d.ts.map +1 -1
- package/dist/proxmox/ceph-osd-tree.d.ts +12 -3
- package/dist/proxmox/ceph-osd-tree.d.ts.map +1 -1
- package/dist/proxmox/ceph-osd-write.d.ts +17 -2
- package/dist/proxmox/ceph-osd-write.d.ts.map +1 -1
- package/dist/proxmox/ceph-osd.d.ts +6 -0
- package/dist/proxmox/ceph-osd.d.ts.map +1 -1
- package/dist/proxmox/ceph-pool-settle.d.ts +10 -4
- package/dist/proxmox/ceph-pool-settle.d.ts.map +1 -1
- package/dist/proxmox/ceph-pool-wire.d.ts +46 -0
- package/dist/proxmox/ceph-pool-wire.d.ts.map +1 -0
- package/dist/proxmox/ceph-pool.d.ts +10 -5
- package/dist/proxmox/ceph-pool.d.ts.map +1 -1
- package/dist/proxmox/group-wire.d.ts +1 -1
- package/dist/proxmox/group-wire.d.ts.map +1 -1
- package/dist/proxmox/index.js +611 -477
- package/dist/proxmox/index.js.map +15 -12
- package/dist/proxmox/storage-wire.d.ts +8 -1
- package/dist/proxmox/storage-wire.d.ts.map +1 -1
- package/dist/proxmox/user-wire.d.ts +1 -1
- package/dist/proxmox/user-wire.d.ts.map +1 -1
- package/docs/argocd-kubernetes.md +100 -0
- package/docs/argocd.md +139 -0
- package/docs/credentials.md +9 -0
- package/docs/litellm.md +17 -0
- package/docs/peers.md +7 -0
- package/docs/unifi.md +45 -0
- package/package.json +8 -3
- package/src/argocd/cluster.test.ts +120 -0
- package/src/argocd/cluster.ts +222 -0
- package/src/argocd/credentials.ts +38 -0
- package/src/argocd/fake-argocd.ts +60 -0
- package/src/argocd/git-credentials.ts +71 -0
- package/src/argocd/index.ts +40 -0
- package/src/argocd/providers.ts +17 -0
- package/src/argocd/repo-creds.test.ts +123 -0
- package/src/argocd/repo-creds.ts +115 -0
- package/src/argocd/repository.test.ts +167 -0
- package/src/argocd/repository.ts +165 -0
- package/src/argocd/resource.ts +150 -0
- package/src/cloudflare/r2-bucket-lock.test.ts +54 -18
- package/src/cloudflare/r2-bucket-lock.ts +25 -18
- package/src/litellm/operations.ts +8 -4
- package/src/proxmox/ceph-daemon-form.ts +7 -8
- package/src/proxmox/ceph-daemon-wire.ts +115 -0
- package/src/proxmox/ceph-daemon-write.test.ts +158 -0
- package/src/proxmox/ceph-daemon.ts +65 -47
- package/src/proxmox/ceph-fs-delete.test.ts +81 -0
- package/src/proxmox/ceph-fs-distilled.ts +102 -0
- package/src/proxmox/ceph-fs-wire.ts +17 -31
- package/src/proxmox/ceph-fs-write.test.ts +67 -0
- package/src/proxmox/ceph-fs.ts +66 -69
- package/src/proxmox/ceph-osd-tree.ts +14 -5
- package/src/proxmox/ceph-osd-write.test.ts +61 -0
- package/src/proxmox/ceph-osd-write.ts +33 -6
- package/src/proxmox/ceph-osd.ts +6 -0
- package/src/proxmox/ceph-pool-settle.ts +13 -7
- package/src/proxmox/ceph-pool-wire.ts +110 -0
- package/src/proxmox/ceph-pool-write.test.ts +145 -0
- package/src/proxmox/ceph-pool.ts +87 -98
- package/src/proxmox/distilled-task-await.test.ts +0 -124
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ bun add @homeflare/alchemy alchemy@2.0.0-beta.79 effect@4.0.0-rc.115 \
|
|
|
7
7
|
@effect/platform-node@4.0.0-rc.115 mime@4.1.0 \
|
|
8
8
|
@distilled.cloud/cloudflare@1.0.0-rc.12 @distilled.cloud/forgejo@1.0.0-rc.12 \
|
|
9
9
|
@distilled.cloud/discord@1.0.0-rc.12 @distilled.cloud/google-workspace@1.0.0-rc.12 \
|
|
10
|
+
@distilled.cloud/argocd@1.0.0-rc.12 \
|
|
10
11
|
@effect/sql-pg@4.0.0-rc.115
|
|
11
12
|
```
|
|
12
13
|
|
|
@@ -288,6 +289,19 @@ export const help =
|
|
|
288
289
|
});
|
|
289
290
|
```
|
|
290
291
|
|
|
292
|
+
## Argo CD — `@homeflare/alchemy/argocd`
|
|
293
|
+
|
|
294
|
+
`Argocd.Repository`, `Argocd.RepoCreds` and `Argocd.Cluster` declare Argo CD's own REST-managed
|
|
295
|
+
objects (backed by labeled `Secret`s, not CRDs), generated from `@distilled.cloud/argocd`. Built
|
|
296
|
+
2026-09-24, **ahead of need** — no Talos-on-PVE cluster or Argo CD instance exists yet; every test
|
|
297
|
+
runs against a fake. `Application`/`AppProject` are genuinely Kubernetes CRDs and are deliberately
|
|
298
|
+
NOT here — declare them with upstream Alchemy's own `Kubernetes.Manifest` instead:
|
|
299
|
+
[docs/argocd.md](./docs/argocd.md) and [docs/argocd-kubernetes.md](./docs/argocd-kubernetes.md).
|
|
300
|
+
|
|
301
|
+
```ts
|
|
302
|
+
import { ArgocdRepository, providers } from '@homeflare/alchemy/argocd';
|
|
303
|
+
```
|
|
304
|
+
|
|
291
305
|
## UniFi Network — `@homeflare/alchemy/unifi`
|
|
292
306
|
|
|
293
307
|
`Unifi.Network` and `Unifi.FirewallZone`, generated from Ubiquiti's own UniFi Network
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Argocd.Cluster` — a target Kubernetes cluster registered with an Argo CD instance
|
|
3
|
+
* (`/api/v1/clusters`) so Applications can deploy onto it. REST-managed, not a CRD; see
|
|
4
|
+
* `docs/argocd.md`. This is how the house will register the Talos-on-PVE cluster itself with
|
|
5
|
+
* Argo CD once both exist — Argo CD's own control-plane cluster (where Argo CD is installed) is
|
|
6
|
+
* registered implicitly as `https://kubernetes.default.svc` and never needs this resource.
|
|
7
|
+
*
|
|
8
|
+
* ⚠️ ONLY BEARER-TOKEN AND STATIC TLS CLIENT-CERT AUTH ARE SUPPORTED. `V1alpha1ClusterConfig` also
|
|
9
|
+
* carries `awsAuthConfig` (EKS IAM) and `execProviderConfig` (an exec plugin) — measured in
|
|
10
|
+
* `services/argocd.ts`, distilled homeflare/base — neither of which applies to a Talos cluster;
|
|
11
|
+
* left unbuilt rather than modeled and untested.
|
|
12
|
+
*
|
|
13
|
+
* ⚠️ NO LIVE ARGO CD INSTANCE EXISTS ON THE ESTATE (2026-09-24) — see `docs/argocd.md`.
|
|
14
|
+
*
|
|
15
|
+
* ⛔ `defaultRemovalPolicy: 'retain'` — deregistering a cluster Applications still target breaks
|
|
16
|
+
* their sync. `delete` below is fully implemented; opt in with `.pipe(RemovalPolicy.destroy())`.
|
|
17
|
+
*/
|
|
18
|
+
import { Resource } from 'alchemy';
|
|
19
|
+
import * as Provider from 'alchemy/Provider';
|
|
20
|
+
import * as argocd from '@distilled.cloud/argocd/argocd';
|
|
21
|
+
import * as Effect from 'effect/Effect';
|
|
22
|
+
import { type FromEnv } from '../secrets/write-only.ts';
|
|
23
|
+
import { type ArgocdRequirements, type ArgocdSpec } from './resource.ts';
|
|
24
|
+
export interface ClusterCredentialRefs {
|
|
25
|
+
readonly password?: FromEnv;
|
|
26
|
+
readonly bearerToken?: FromEnv;
|
|
27
|
+
readonly tlsClientKeyData?: FromEnv;
|
|
28
|
+
}
|
|
29
|
+
export interface ClusterProps {
|
|
30
|
+
/** The cluster's API server URL — identity key; changing it is a replace. */
|
|
31
|
+
server: string;
|
|
32
|
+
name?: string;
|
|
33
|
+
/** Restricts this cluster to one Argo CD project; omit for every project. */
|
|
34
|
+
project?: string;
|
|
35
|
+
namespaces?: readonly string[];
|
|
36
|
+
clusterResources?: boolean;
|
|
37
|
+
labels?: Readonly<Record<string, string>>;
|
|
38
|
+
annotations?: Readonly<Record<string, string>>;
|
|
39
|
+
proxyUrl?: string;
|
|
40
|
+
username?: string;
|
|
41
|
+
tlsCaData?: string;
|
|
42
|
+
/** The client certificate itself — public, unlike its key. */
|
|
43
|
+
tlsCertData?: string;
|
|
44
|
+
tlsInsecure?: boolean;
|
|
45
|
+
tlsServerName?: string;
|
|
46
|
+
/** Write-only — never a value here, only env var names. See the module header. */
|
|
47
|
+
credentials?: ClusterCredentialRefs;
|
|
48
|
+
}
|
|
49
|
+
export interface ClusterAttributes {
|
|
50
|
+
server: string;
|
|
51
|
+
name: string | undefined;
|
|
52
|
+
project: string | undefined;
|
|
53
|
+
namespaces: readonly string[] | undefined;
|
|
54
|
+
clusterResources: boolean | undefined;
|
|
55
|
+
labels: Readonly<Record<string, string>> | undefined;
|
|
56
|
+
annotations: Readonly<Record<string, string>> | undefined;
|
|
57
|
+
proxyUrl: string | undefined;
|
|
58
|
+
username: string | undefined;
|
|
59
|
+
tlsCaData: string | undefined;
|
|
60
|
+
tlsCertData: string | undefined;
|
|
61
|
+
tlsInsecure: boolean | undefined;
|
|
62
|
+
tlsServerName: string | undefined;
|
|
63
|
+
}
|
|
64
|
+
export interface ArgocdCluster extends Resource<'Argocd.Cluster', ClusterProps, ClusterAttributes, never, ArgocdRequirements> {
|
|
65
|
+
}
|
|
66
|
+
export declare const ArgocdCluster: import("alchemy").ResourceClass<ArgocdCluster>;
|
|
67
|
+
declare const ArgocdClusterSecretEnvUnsetError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
68
|
+
readonly _tag: "ArgocdClusterSecretEnvUnsetError";
|
|
69
|
+
} & Readonly<A>;
|
|
70
|
+
/** Domain refusal, not a distilled error — a declared credential's env var is unset at call time. */
|
|
71
|
+
export declare class ArgocdClusterSecretEnvUnsetError extends ArgocdClusterSecretEnvUnsetError_base<{
|
|
72
|
+
readonly message: string;
|
|
73
|
+
}> {
|
|
74
|
+
}
|
|
75
|
+
type ClusterError = argocd.GetClusterServiceError | argocd.CreateClusterServiceError | argocd.DeleteClusterServiceError | ArgocdClusterSecretEnvUnsetError;
|
|
76
|
+
/** ★ EXPORTED for direct testing against `fake-argocd.ts` — see `cluster.test.ts`. */
|
|
77
|
+
export declare const spec: ArgocdSpec<ClusterProps, argocd.V1alpha1Cluster, ClusterAttributes, ClusterError>;
|
|
78
|
+
export declare const handlers: {
|
|
79
|
+
list: () => Effect.Effect<never[], never, never>;
|
|
80
|
+
read: ({ olds }: {
|
|
81
|
+
olds: ClusterProps;
|
|
82
|
+
}) => Effect.Effect<ClusterAttributes | undefined, ClusterError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
83
|
+
diff: ({ news, output }: {
|
|
84
|
+
news: import("alchemy").Input<ClusterProps>;
|
|
85
|
+
output: ClusterAttributes | undefined;
|
|
86
|
+
}) => Effect.Effect<{
|
|
87
|
+
readonly action: 'replace';
|
|
88
|
+
} | {
|
|
89
|
+
readonly action: 'update';
|
|
90
|
+
} | {
|
|
91
|
+
readonly action: 'noop';
|
|
92
|
+
} | undefined, ClusterError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
93
|
+
reconcile: ({ news }: {
|
|
94
|
+
news: ClusterProps;
|
|
95
|
+
}) => Effect.Effect<ClusterAttributes, ClusterError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
96
|
+
delete: ({ olds }: {
|
|
97
|
+
olds: ClusterProps;
|
|
98
|
+
}) => Effect.Effect<void, ClusterError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
99
|
+
};
|
|
100
|
+
export declare const ArgocdClusterProvider: () => import("effect/Layer").Layer<Provider.Provider<ArgocdCluster>, never, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
101
|
+
export {};
|
|
102
|
+
//# sourceMappingURL=cluster.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../../src/argocd/cluster.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Argo CD credentials — a bearer-token REFERENCE, resolved lazily, never a prop.
|
|
3
|
+
*
|
|
4
|
+
* ⛔ NO TOKEN IS EVER A PROP OR AN ATTRIBUTE. Alchemy persists Attributes unencrypted
|
|
5
|
+
* (State/StateEncoding.ts@v2.0.0-beta.79#encodeState), so nothing a stack file holds may be a
|
|
6
|
+
* credential. `@distilled.cloud/argocd/Credentials` already ships exactly the shape this asks
|
|
7
|
+
* for: `Credentials` is a lazy `Context.Service<Credentials, Effect.Effect<Config>>`, resolved
|
|
8
|
+
* on the calling fiber inside each operation (`ArgocdProtocol`'s `credentials:` field), never at
|
|
9
|
+
* layer build. This file re-exports it rather than re-implementing it — the same choice
|
|
10
|
+
* `../discord/credentials.ts` and `../forgejo` (via `@distilled.cloud/forgejo/Credentials`) made.
|
|
11
|
+
*
|
|
12
|
+
* ★ `CredentialsFromEnv` reads `ARGOCD_TOKEN` (required) and `ARGOCD_SERVER` (optional instance
|
|
13
|
+
* origin, default `https://localhost:8080`) — the distilled package's own names, unchanged here
|
|
14
|
+
* so a consumer never has to guess which var this family reads.
|
|
15
|
+
*
|
|
16
|
+
* ⚠️ NO `credentials(...)` FACTORY EXISTS ON THIS SDK, unlike Discord/Grafana's — measured against
|
|
17
|
+
* `packages/argocd/src/credentials.ts` (distilled homeflare/base): only `fromToken({ token,
|
|
18
|
+
* apiBaseUrl? })` and `CredentialsFromEnv`. `fake-argocd.ts` builds its test layer from
|
|
19
|
+
* `fromToken` directly.
|
|
20
|
+
*
|
|
21
|
+
* ⚠️ NO OpenBao MINT YET, same as every other family in this kit today (`Alchemy.Stack({ secrets
|
|
22
|
+
* })` is unreleased, PR 1728, `main`-only). A deploy process exports `ARGOCD_TOKEN` itself —
|
|
23
|
+
* this package never reads it from a file.
|
|
24
|
+
*
|
|
25
|
+
* ⚠️ NO LIVE ARGO CD INSTANCE EXISTS ON THE ESTATE YET (2026-09-24) — this family is built ahead
|
|
26
|
+
* of the Talos-on-PVE cluster it targets, per Tim's "get the providers ready even if we don't
|
|
27
|
+
* use it yet but we know we will." Nothing here has been exercised against a real server; every
|
|
28
|
+
* test in this family runs against `fake-argocd.ts`.
|
|
29
|
+
*/
|
|
30
|
+
import type { Config } from '@distilled.cloud/argocd/Credentials';
|
|
31
|
+
import { Credentials, CredentialsFromEnv, fromToken } from '@distilled.cloud/argocd/Credentials';
|
|
32
|
+
/** Re-exported so a consumer never has to reach into `@distilled.cloud/argocd` by hand. */
|
|
33
|
+
export { Credentials, CredentialsFromEnv, fromToken };
|
|
34
|
+
export type { Config as ArgocdCredentialsConfig };
|
|
35
|
+
/** `ArgocdCredentials.fromEnv()` — the layer every `argocdProviders()` stack uses by default. */
|
|
36
|
+
export declare const fromEnv: () => import("effect/Layer").Layer<Credentials, never, never>;
|
|
37
|
+
//# sourceMappingURL=credentials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/argocd/credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AAEjG,2FAA2F;AAC3F,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,SAAS,EAAE,CAAC;AACtD,YAAY,EAAE,MAAM,IAAI,uBAAuB,EAAE,CAAC;AAElD,iGAAiG;AACjG,eAAO,MAAM,OAAO,+DAA2B,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A minimal in-memory Argo CD REST API for this family's tests — an in-memory `fetch` handed to
|
|
3
|
+
* Effect's real `FetchHttpClient` through its `Fetch` reference, mirroring `../discord/fake-discord.ts`
|
|
4
|
+
* (itself mirroring `../forgejo/fake-forgejo.ts` and `cloudflare/fake-mesh.ts`). Tests exercise
|
|
5
|
+
* distilled's REAL path assembly, JSON encode/decode and status→typed-error matching — nothing
|
|
6
|
+
* about any of that is re-implemented here, only the wire responses a scenario needs.
|
|
7
|
+
*
|
|
8
|
+
* ⛔ TEST-ONLY, AND NO NETWORK. No provider imports this file. The base URL is RFC 2606
|
|
9
|
+
* `argocd.example.com`, and the token is a placeholder. NO LIVE ARGO CD INSTANCE EXISTS ON THE
|
|
10
|
+
* ESTATE (2026-09-24) — this is the only server any test in this family talks to.
|
|
11
|
+
*/
|
|
12
|
+
import { type Credentials } from '@distilled.cloud/argocd/Credentials';
|
|
13
|
+
import * as Layer from 'effect/Layer';
|
|
14
|
+
export declare const FAKE_BASE = "https://argocd.example.com";
|
|
15
|
+
export declare const FAKE_TOKEN = "placeholder-argocd-token";
|
|
16
|
+
export type Seen = {
|
|
17
|
+
readonly method: string;
|
|
18
|
+
readonly path: string;
|
|
19
|
+
readonly body: unknown;
|
|
20
|
+
};
|
|
21
|
+
/** Argo CD's grpc-gateway `{ code?, message, error? }` failure envelope. */
|
|
22
|
+
export declare const fakeFailure: (status: number, message: string, code?: number) => Response;
|
|
23
|
+
/**
|
|
24
|
+
* `route` decides every response; this wrapper only records what was sent and adapts to
|
|
25
|
+
* `globalThis.fetch`'s signature. A test that expects no request at all asserts `seen` is empty.
|
|
26
|
+
*/
|
|
27
|
+
export declare const fakeArgocd: (route: (method: string, url: URL, body: unknown, callNumber: number) => Response) => {
|
|
28
|
+
fetch: typeof fetch;
|
|
29
|
+
seen: Seen[];
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* distilled Credentials + the real FetchHttpClient over the fake — `ArgocdOpContext`, what every
|
|
33
|
+
* resource file's exported `spec.fetchLive`/`spec.upsert`/`spec.destroy` needs.
|
|
34
|
+
*
|
|
35
|
+
* ⚠️ NOT PAIRED WITH `handlers` (each resource file's `argocdHandlers(spec)` export). `handlers`
|
|
36
|
+
* bakes in `CredentialsFromEnv`, which resolves through Effect's `Config` snapshot of
|
|
37
|
+
* `process.env` — untestable against a fake server without mutating the real environment. So a
|
|
38
|
+
* test calls `spec.fetchLive`/`spec.upsert`/`spec.destroy` directly, with this explicit layer,
|
|
39
|
+
* exercising exactly the same production code without that env seam.
|
|
40
|
+
*/
|
|
41
|
+
export declare const fakeArgocdLayer: (fetchFn: typeof globalThis.fetch, creds?: Layer.Layer<Credentials>) => Layer.Layer<Credentials | import("effect/unstable/http/HttpClient").HttpClient, never, never>;
|
|
42
|
+
//# sourceMappingURL=fake-argocd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake-argocd.d.ts","sourceRoot":"","sources":["../../src/argocd/fake-argocd.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,KAAK,WAAW,EAAa,MAAM,qCAAqC,CAAC;AAClF,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC,eAAO,MAAM,SAAS,+BAA+B,CAAC;AACtD,eAAO,MAAM,UAAU,6BAA6B,CAAC;AAErD,MAAM,MAAM,IAAI,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAE9F,4EAA4E;AAC5E,eAAO,MAAM,WAAW,WAAY,MAAM,WAAW,MAAM,SAAS,MAAM,aACZ,CAAC;AAE/D;;;GAGG;AACH,eAAO,MAAM,UAAU,UACd,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,KAAK,QAAQ;;;CAejF,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,YACjB,OAAO,UAAU,CAAC,KAAK,UACzB,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,kGAC+D,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as Effect from 'effect/Effect';
|
|
2
|
+
import { type FromEnv } from '../secrets/write-only.ts';
|
|
3
|
+
export interface GitCredentialRefs {
|
|
4
|
+
readonly password?: FromEnv;
|
|
5
|
+
readonly sshPrivateKey?: FromEnv;
|
|
6
|
+
readonly bearerToken?: FromEnv;
|
|
7
|
+
readonly tlsClientCertKey?: FromEnv;
|
|
8
|
+
}
|
|
9
|
+
export interface ResolvedGitCredentials {
|
|
10
|
+
readonly password?: string;
|
|
11
|
+
readonly sshPrivateKey?: string;
|
|
12
|
+
readonly bearerToken?: string;
|
|
13
|
+
readonly tlsClientCertKey?: string;
|
|
14
|
+
}
|
|
15
|
+
declare const ArgocdSecretEnvUnsetError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
16
|
+
readonly _tag: "ArgocdSecretEnvUnsetError";
|
|
17
|
+
} & Readonly<A>;
|
|
18
|
+
/** Domain refusal, not a distilled error — a declared credential's env var is unset at call time. */
|
|
19
|
+
export declare class ArgocdSecretEnvUnsetError extends ArgocdSecretEnvUnsetError_base<{
|
|
20
|
+
readonly message: string;
|
|
21
|
+
}> {
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Resolves every declared ref from the deploying process's own environment, or fails with the
|
|
25
|
+
* names of whichever are missing — never a value, in the failure or anywhere else.
|
|
26
|
+
*/
|
|
27
|
+
export declare const resolveGitCredentials: (refs: GitCredentialRefs) => Effect.Effect<ResolvedGitCredentials, ArgocdSecretEnvUnsetError>;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=git-credentials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-credentials.d.ts","sourceRoot":"","sources":["../../src/argocd/git-credentials.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,KAAK,OAAO,EAAc,MAAM,0BAA0B,CAAC;AAEpE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;;;;AAED,qGAAqG;AACrG,qBAAa,yBAA0B,SAAQ,+BAA8C;IAC3F,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;AAYL;;;GAGG;AACH,eAAO,MAAM,qBAAqB,SAC1B,iBAAiB,KACtB,MAAM,CAAC,MAAM,CAAC,sBAAsB,EAAE,yBAAyB,CAYjE,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Argo CD providers for Alchemy.
|
|
3
|
+
*
|
|
4
|
+
* ⛔ THIS BARREL IS THE PUBLIC API, AND IT IS DELIBERATELY SMALLER THAN THE DIRECTORY. `resource.ts`
|
|
5
|
+
* and `git-credentials.ts` are internals the three resource files share — a consumer builds
|
|
6
|
+
* against the resources and `providers()`, not the engine underneath.
|
|
7
|
+
*
|
|
8
|
+
* ★ `Application` AND `AppProject` ARE NOT HERE — they are Kubernetes CRDs, not Argo CD REST-only
|
|
9
|
+
* objects, and the upstream-correct owner is Alchemy's own `Kubernetes.Manifest`
|
|
10
|
+
* (`alchemy/Kubernetes`, v2.0.0-beta.79). See `docs/argocd.md#applications-and-appprojects` for
|
|
11
|
+
* the measured reasoning and worked examples — no code for those two lives in this kit.
|
|
12
|
+
*/
|
|
13
|
+
export { ArgocdCluster, ArgocdClusterProvider, type ClusterAttributes, type ClusterCredentialRefs, type ClusterProps, } from './cluster.ts';
|
|
14
|
+
export { type ArgocdCredentialsConfig, Credentials, CredentialsFromEnv, fromEnv, fromToken, } from './credentials.ts';
|
|
15
|
+
export { type ArgocdSecretEnvUnsetError, type GitCredentialRefs } from './git-credentials.ts';
|
|
16
|
+
export { providers } from './providers.ts';
|
|
17
|
+
export { ArgocdRepoCreds, ArgocdRepoCredsProvider, type RepoCredsAttributes, type RepoCredsProps, } from './repo-creds.ts';
|
|
18
|
+
export { ArgocdRepository, ArgocdRepositoryProvider, type RepositoryAttributes, type RepositoryProps, } from './repository.ts';
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/argocd/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,YAAY,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,KAAK,uBAAuB,EAC5B,WAAW,EACX,kBAAkB,EAClB,OAAO,EACP,SAAS,GACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,yBAAyB,EAAE,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9F,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,KAAK,mBAAmB,EACxB,KAAK,cAAc,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,gBAAgB,EAChB,wBAAwB,EACxB,KAAK,oBAAoB,EACzB,KAAK,eAAe,GACrB,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
// src/argocd/cluster.ts
|
|
2
|
+
import { Resource } from "alchemy";
|
|
3
|
+
import * as Provider from "alchemy/Provider";
|
|
4
|
+
import * as argocd from "@distilled.cloud/argocd/argocd";
|
|
5
|
+
import * as Data from "effect/Data";
|
|
6
|
+
import * as Effect2 from "effect/Effect";
|
|
7
|
+
|
|
8
|
+
// src/secrets/write-only.ts
|
|
9
|
+
import { Buffer } from "node:buffer";
|
|
10
|
+
import { randomBytes, scryptSync, timingSafeEqual } from "node:crypto";
|
|
11
|
+
var resolveAll = (refs, env = process.env) => {
|
|
12
|
+
const values = {};
|
|
13
|
+
const missing = [];
|
|
14
|
+
for (const [key, ref] of Object.entries(refs)) {
|
|
15
|
+
const value = env[ref.fromEnv];
|
|
16
|
+
if (value === undefined || value === "")
|
|
17
|
+
missing.push(ref.fromEnv);
|
|
18
|
+
else
|
|
19
|
+
values[key] = value;
|
|
20
|
+
}
|
|
21
|
+
return { missing: [...new Set(missing)].sort(), values };
|
|
22
|
+
};
|
|
23
|
+
var COST = { N: 16384, maxmem: 64 * 1024 * 1024, p: 1, r: 8 };
|
|
24
|
+
var PREFIX = "scrypt";
|
|
25
|
+
var canonical = (values) => JSON.stringify(Object.keys(values).sort().map((key) => [key, values[key]]));
|
|
26
|
+
var digest = (salt, values) => scryptSync(canonical(values), salt, 32, COST);
|
|
27
|
+
var seal = (values, salt) => {
|
|
28
|
+
if (Object.keys(values).length === 0)
|
|
29
|
+
return "";
|
|
30
|
+
const bytes = salt === undefined ? randomBytes(16) : Buffer.from(salt, "utf8");
|
|
31
|
+
return `${PREFIX}:${bytes.toString("base64url")}:${digest(bytes, values).toString("base64url")}`;
|
|
32
|
+
};
|
|
33
|
+
var sealMatches = (sealed, values) => {
|
|
34
|
+
if (sealed === "")
|
|
35
|
+
return Object.keys(values).length === 0;
|
|
36
|
+
const [prefix, salt, stored, extra] = sealed.split(":");
|
|
37
|
+
if (prefix !== PREFIX || salt === undefined || stored === undefined || extra !== undefined) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const expected = Buffer.from(stored, "base64url");
|
|
41
|
+
const actual = digest(Buffer.from(salt, "base64url"), values);
|
|
42
|
+
return expected.length === actual.length && timingSafeEqual(expected, actual);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// src/argocd/resource.ts
|
|
46
|
+
import { isResolved } from "alchemy/Diff";
|
|
47
|
+
import { CredentialsFromEnv } from "@distilled.cloud/argocd/Credentials";
|
|
48
|
+
import * as Effect from "effect/Effect";
|
|
49
|
+
var present = (obj) => Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined));
|
|
50
|
+
var argocdOperations = (spec) => {
|
|
51
|
+
const read = (props) => spec.fetchLive(props).pipe(Effect.map((live) => live === undefined ? undefined : spec.attributes(live, props)));
|
|
52
|
+
return {
|
|
53
|
+
read,
|
|
54
|
+
diff: (news, output) => Effect.gen(function* () {
|
|
55
|
+
if (output === undefined || !isResolved(news))
|
|
56
|
+
return;
|
|
57
|
+
if (spec.identityOfProps(news) !== spec.identityOfAttributes(output)) {
|
|
58
|
+
return { action: "replace" };
|
|
59
|
+
}
|
|
60
|
+
const live = yield* read(news);
|
|
61
|
+
if (live === undefined)
|
|
62
|
+
return { action: "update" };
|
|
63
|
+
return spec.matches(live, news) ? { action: "noop" } : { action: "update" };
|
|
64
|
+
}),
|
|
65
|
+
reconcile: (news) => Effect.gen(function* () {
|
|
66
|
+
const before = yield* read(news);
|
|
67
|
+
if (before === undefined || !spec.matches(before, news)) {
|
|
68
|
+
yield* spec.upsert(news);
|
|
69
|
+
}
|
|
70
|
+
const after = yield* read(news);
|
|
71
|
+
if (after === undefined) {
|
|
72
|
+
return yield* Effect.die(new Error("the write returned no error but the object is still absent — read back rather " + "than trust the status code."));
|
|
73
|
+
}
|
|
74
|
+
return after;
|
|
75
|
+
}),
|
|
76
|
+
destroy: (olds) => Effect.gen(function* () {
|
|
77
|
+
const live = yield* spec.fetchLive(olds);
|
|
78
|
+
if (live === undefined)
|
|
79
|
+
return;
|
|
80
|
+
yield* spec.destroy(olds, live);
|
|
81
|
+
})
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
var argocdHandlers = (spec) => {
|
|
85
|
+
const ops = argocdOperations(spec);
|
|
86
|
+
const withCredentials = (effect) => Effect.provide(effect, CredentialsFromEnv);
|
|
87
|
+
return {
|
|
88
|
+
list: () => Effect.succeed([]),
|
|
89
|
+
read: ({ olds }) => withCredentials(ops.read(olds)),
|
|
90
|
+
diff: ({ news, output }) => withCredentials(ops.diff(news, output)),
|
|
91
|
+
reconcile: ({ news }) => withCredentials(ops.reconcile(news)),
|
|
92
|
+
delete: ({ olds }) => withCredentials(ops.destroy(olds))
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// src/argocd/cluster.ts
|
|
97
|
+
var ArgocdCluster = Resource("Argocd.Cluster", {
|
|
98
|
+
defaultRemovalPolicy: "retain"
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
class ArgocdClusterSecretEnvUnsetError extends Data.TaggedError("ArgocdClusterSecretEnvUnsetError") {
|
|
102
|
+
}
|
|
103
|
+
var resolveClusterCredentials = (refs) => {
|
|
104
|
+
const declared = {};
|
|
105
|
+
if (refs.password !== undefined)
|
|
106
|
+
declared.password = refs.password;
|
|
107
|
+
if (refs.bearerToken !== undefined)
|
|
108
|
+
declared.bearerToken = refs.bearerToken;
|
|
109
|
+
if (refs.tlsClientKeyData !== undefined)
|
|
110
|
+
declared.tlsClientKeyData = refs.tlsClientKeyData;
|
|
111
|
+
const { values, missing } = resolveAll(declared);
|
|
112
|
+
if (missing.length > 0) {
|
|
113
|
+
return Effect2.fail(new ArgocdClusterSecretEnvUnsetError({
|
|
114
|
+
message: `credential write requires ${missing.join(", ")}, unset or empty in the ` + "deploying environment. Export it and deploy again."
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
return Effect2.succeed(values);
|
|
118
|
+
};
|
|
119
|
+
var attributesOf = (live) => ({
|
|
120
|
+
annotations: live.annotations,
|
|
121
|
+
clusterResources: live.clusterResources,
|
|
122
|
+
labels: live.labels,
|
|
123
|
+
name: live.name,
|
|
124
|
+
namespaces: live.namespaces,
|
|
125
|
+
project: live.project,
|
|
126
|
+
proxyUrl: live.config?.proxyUrl,
|
|
127
|
+
server: live.server ?? "",
|
|
128
|
+
tlsCaData: live.config?.tlsClientConfig?.caData,
|
|
129
|
+
tlsCertData: live.config?.tlsClientConfig?.certData,
|
|
130
|
+
tlsInsecure: live.config?.tlsClientConfig?.insecure,
|
|
131
|
+
tlsServerName: live.config?.tlsClientConfig?.serverName,
|
|
132
|
+
username: live.config?.username
|
|
133
|
+
});
|
|
134
|
+
var sameRecord = (a, b) => JSON.stringify(Object.entries(a ?? {}).sort()) === JSON.stringify(Object.entries(b ?? {}).sort());
|
|
135
|
+
var sameList = (a, b) => JSON.stringify([...a ?? []].sort()) === JSON.stringify([...b ?? []].sort());
|
|
136
|
+
var plainMatches = (attrs, props) => (props.name ?? undefined) === (attrs.name ?? undefined) && (props.project ?? undefined) === (attrs.project ?? undefined) && sameList(props.namespaces, attrs.namespaces) && Boolean(props.clusterResources) === Boolean(attrs.clusterResources) && sameRecord(props.labels, attrs.labels) && sameRecord(props.annotations, attrs.annotations) && (props.proxyUrl ?? undefined) === (attrs.proxyUrl ?? undefined) && (props.username ?? undefined) === (attrs.username ?? undefined) && (props.tlsCaData ?? undefined) === (attrs.tlsCaData ?? undefined) && (props.tlsCertData ?? undefined) === (attrs.tlsCertData ?? undefined) && Boolean(props.tlsInsecure) === Boolean(attrs.tlsInsecure) && (props.tlsServerName ?? undefined) === (attrs.tlsServerName ?? undefined);
|
|
137
|
+
var spec = {
|
|
138
|
+
attributes: (live) => attributesOf(live),
|
|
139
|
+
destroy: (props) => argocd.deleteClusterService({ id_value: props.server }).pipe(Effect2.catchTag("NotFound", () => Effect2.void)),
|
|
140
|
+
identityOfAttributes: (attrs) => attrs.server,
|
|
141
|
+
identityOfProps: (props) => props.server,
|
|
142
|
+
fetchLive: (props) => argocd.getClusterService({ id_value: props.server }).pipe(Effect2.catchTag("NotFound", () => Effect2.succeed(undefined))),
|
|
143
|
+
matches: plainMatches,
|
|
144
|
+
upsert: (props) => resolveClusterCredentials(props.credentials ?? {}).pipe(Effect2.flatMap((creds) => argocd.createClusterService(present({
|
|
145
|
+
upsert: true,
|
|
146
|
+
annotations: props.annotations,
|
|
147
|
+
clusterResources: props.clusterResources,
|
|
148
|
+
config: present({
|
|
149
|
+
bearerToken: creds.bearerToken,
|
|
150
|
+
password: creds.password,
|
|
151
|
+
proxyUrl: props.proxyUrl,
|
|
152
|
+
tlsClientConfig: present({
|
|
153
|
+
caData: props.tlsCaData,
|
|
154
|
+
certData: props.tlsCertData,
|
|
155
|
+
insecure: props.tlsInsecure,
|
|
156
|
+
keyData: creds.tlsClientKeyData,
|
|
157
|
+
serverName: props.tlsServerName
|
|
158
|
+
}),
|
|
159
|
+
username: props.username
|
|
160
|
+
}),
|
|
161
|
+
labels: props.labels,
|
|
162
|
+
name: props.name,
|
|
163
|
+
namespaces: props.namespaces === undefined ? undefined : [...props.namespaces],
|
|
164
|
+
project: props.project,
|
|
165
|
+
server: props.server
|
|
166
|
+
}))))
|
|
167
|
+
};
|
|
168
|
+
var handlers = argocdHandlers(spec);
|
|
169
|
+
var ArgocdClusterProvider = () => Provider.effect(ArgocdCluster, Effect2.succeed(ArgocdCluster.Provider.of(handlers)));
|
|
170
|
+
// src/argocd/credentials.ts
|
|
171
|
+
import { Credentials, CredentialsFromEnv as CredentialsFromEnv2, fromToken } from "@distilled.cloud/argocd/Credentials";
|
|
172
|
+
var fromEnv = () => CredentialsFromEnv2;
|
|
173
|
+
// src/argocd/providers.ts
|
|
174
|
+
import * as Layer from "effect/Layer";
|
|
175
|
+
|
|
176
|
+
// src/argocd/repo-creds.ts
|
|
177
|
+
import { Resource as Resource2 } from "alchemy";
|
|
178
|
+
import * as Provider2 from "alchemy/Provider";
|
|
179
|
+
import * as argocd2 from "@distilled.cloud/argocd/argocd";
|
|
180
|
+
import * as Effect4 from "effect/Effect";
|
|
181
|
+
|
|
182
|
+
// src/argocd/git-credentials.ts
|
|
183
|
+
import * as Data2 from "effect/Data";
|
|
184
|
+
import * as Effect3 from "effect/Effect";
|
|
185
|
+
class ArgocdSecretEnvUnsetError extends Data2.TaggedError("ArgocdSecretEnvUnsetError") {
|
|
186
|
+
}
|
|
187
|
+
var declaredRefs = (refs) => {
|
|
188
|
+
const out = {};
|
|
189
|
+
if (refs.password !== undefined)
|
|
190
|
+
out.password = refs.password;
|
|
191
|
+
if (refs.sshPrivateKey !== undefined)
|
|
192
|
+
out.sshPrivateKey = refs.sshPrivateKey;
|
|
193
|
+
if (refs.bearerToken !== undefined)
|
|
194
|
+
out.bearerToken = refs.bearerToken;
|
|
195
|
+
if (refs.tlsClientCertKey !== undefined)
|
|
196
|
+
out.tlsClientCertKey = refs.tlsClientCertKey;
|
|
197
|
+
return out;
|
|
198
|
+
};
|
|
199
|
+
var resolveGitCredentials = (refs) => {
|
|
200
|
+
const { values, missing } = resolveAll(declaredRefs(refs));
|
|
201
|
+
if (missing.length > 0) {
|
|
202
|
+
return Effect3.fail(new ArgocdSecretEnvUnsetError({
|
|
203
|
+
message: `credential write requires ${missing.join(", ")}, unset or empty in the ` + "deploying environment. Export it and deploy again."
|
|
204
|
+
}));
|
|
205
|
+
}
|
|
206
|
+
return Effect3.succeed(values);
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
// src/argocd/repo-creds.ts
|
|
210
|
+
var ArgocdRepoCreds = Resource2("Argocd.RepoCreds");
|
|
211
|
+
var attributesOf2 = (live) => ({
|
|
212
|
+
tlsClientCertData: live.tlsClientCertData,
|
|
213
|
+
type: live.type,
|
|
214
|
+
url: live.url ?? "",
|
|
215
|
+
username: live.username
|
|
216
|
+
});
|
|
217
|
+
var plainMatches2 = (attrs, props) => (props.type ?? "git") === (attrs.type ?? "git") && (props.username ?? undefined) === (attrs.username ?? undefined) && (props.tlsClientCertData ?? undefined) === (attrs.tlsClientCertData ?? undefined);
|
|
218
|
+
var spec2 = {
|
|
219
|
+
attributes: (live) => attributesOf2(live),
|
|
220
|
+
destroy: (props) => argocd2.deleteRepoCredsServiceRepositoryCredentials({ url: props.url }).pipe(Effect4.catchTag("NotFound", () => Effect4.void)),
|
|
221
|
+
identityOfAttributes: (attrs) => attrs.url,
|
|
222
|
+
identityOfProps: (props) => props.url,
|
|
223
|
+
fetchLive: (props) => argocd2.listRepoCredsServiceRepositoryCredentials({ url: props.url }).pipe(Effect4.map((page) => (page.items ?? []).find((row) => row.url === props.url)), Effect4.catchTag("NotFound", () => Effect4.succeed(undefined))),
|
|
224
|
+
matches: plainMatches2,
|
|
225
|
+
upsert: (props) => resolveGitCredentials(props.credentials ?? {}).pipe(Effect4.flatMap((creds) => argocd2.createRepoCredsServiceRepositoryCredentials(present({
|
|
226
|
+
upsert: true,
|
|
227
|
+
tlsClientCertData: props.tlsClientCertData,
|
|
228
|
+
type: props.type,
|
|
229
|
+
url: props.url,
|
|
230
|
+
username: props.username,
|
|
231
|
+
...creds
|
|
232
|
+
}))))
|
|
233
|
+
};
|
|
234
|
+
var handlers2 = argocdHandlers(spec2);
|
|
235
|
+
var ArgocdRepoCredsProvider = () => Provider2.effect(ArgocdRepoCreds, Effect4.succeed(ArgocdRepoCreds.Provider.of(handlers2)));
|
|
236
|
+
|
|
237
|
+
// src/argocd/repository.ts
|
|
238
|
+
import { Resource as Resource3 } from "alchemy";
|
|
239
|
+
import * as Provider3 from "alchemy/Provider";
|
|
240
|
+
import * as argocd3 from "@distilled.cloud/argocd/argocd";
|
|
241
|
+
import * as Effect5 from "effect/Effect";
|
|
242
|
+
var ArgocdRepository = Resource3("Argocd.Repository", {
|
|
243
|
+
defaultRemovalPolicy: "retain"
|
|
244
|
+
});
|
|
245
|
+
var attributesOf3 = (live) => ({
|
|
246
|
+
enableLfs: live.enableLfs,
|
|
247
|
+
enableOCI: live.enableOCI,
|
|
248
|
+
forceHttpBasicAuth: live.forceHttpBasicAuth,
|
|
249
|
+
insecure: live.insecure,
|
|
250
|
+
insecureIgnoreHostKey: live.insecureIgnoreHostKey,
|
|
251
|
+
name: live.name,
|
|
252
|
+
noProxy: live.noProxy,
|
|
253
|
+
project: live.project,
|
|
254
|
+
proxy: live.proxy,
|
|
255
|
+
repo: live.repo ?? "",
|
|
256
|
+
tlsClientCertData: live.tlsClientCertData,
|
|
257
|
+
type: live.type,
|
|
258
|
+
username: live.username
|
|
259
|
+
});
|
|
260
|
+
var plainMatches3 = (attrs, props) => (props.type ?? "git") === (attrs.type ?? "git") && (props.name ?? undefined) === (attrs.name ?? undefined) && (props.project ?? undefined) === (attrs.project ?? undefined) && (props.username ?? undefined) === (attrs.username ?? undefined) && Boolean(props.insecure) === Boolean(attrs.insecure) && Boolean(props.insecureIgnoreHostKey) === Boolean(attrs.insecureIgnoreHostKey) && Boolean(props.enableLfs) === Boolean(attrs.enableLfs) && Boolean(props.enableOCI) === Boolean(attrs.enableOCI) && Boolean(props.forceHttpBasicAuth) === Boolean(attrs.forceHttpBasicAuth) && (props.proxy ?? undefined) === (attrs.proxy ?? undefined) && (props.noProxy ?? undefined) === (attrs.noProxy ?? undefined) && (props.tlsClientCertData ?? undefined) === (attrs.tlsClientCertData ?? undefined);
|
|
261
|
+
var spec3 = {
|
|
262
|
+
attributes: (live) => attributesOf3(live),
|
|
263
|
+
destroy: (props) => argocd3.deleteRepositoryServiceRepository({ repo: props.repo }).pipe(Effect5.catchTag("NotFound", () => Effect5.void)),
|
|
264
|
+
identityOfAttributes: (attrs) => attrs.repo,
|
|
265
|
+
identityOfProps: (props) => props.repo,
|
|
266
|
+
fetchLive: (props) => argocd3.getRepositoryService({ repo: props.repo }).pipe(Effect5.catchTag("NotFound", () => Effect5.succeed(undefined))),
|
|
267
|
+
matches: plainMatches3,
|
|
268
|
+
upsert: (props) => resolveGitCredentials(props.credentials ?? {}).pipe(Effect5.flatMap((creds) => argocd3.createRepositoryServiceRepository(present({
|
|
269
|
+
upsert: true,
|
|
270
|
+
enableLfs: props.enableLfs,
|
|
271
|
+
enableOCI: props.enableOCI,
|
|
272
|
+
forceHttpBasicAuth: props.forceHttpBasicAuth,
|
|
273
|
+
insecure: props.insecure,
|
|
274
|
+
insecureIgnoreHostKey: props.insecureIgnoreHostKey,
|
|
275
|
+
name: props.name,
|
|
276
|
+
noProxy: props.noProxy,
|
|
277
|
+
project: props.project,
|
|
278
|
+
proxy: props.proxy,
|
|
279
|
+
repo: props.repo,
|
|
280
|
+
tlsClientCertData: props.tlsClientCertData,
|
|
281
|
+
type: props.type,
|
|
282
|
+
username: props.username,
|
|
283
|
+
...creds
|
|
284
|
+
}))))
|
|
285
|
+
};
|
|
286
|
+
var handlers3 = argocdHandlers(spec3);
|
|
287
|
+
var ArgocdRepositoryProvider = () => Provider3.effect(ArgocdRepository, Effect5.succeed(ArgocdRepository.Provider.of(handlers3)));
|
|
288
|
+
|
|
289
|
+
// src/argocd/providers.ts
|
|
290
|
+
var providers = () => Layer.mergeAll(ArgocdRepositoryProvider(), ArgocdRepoCredsProvider(), ArgocdClusterProvider());
|
|
291
|
+
export {
|
|
292
|
+
ArgocdCluster,
|
|
293
|
+
ArgocdClusterProvider,
|
|
294
|
+
ArgocdRepoCreds,
|
|
295
|
+
ArgocdRepoCredsProvider,
|
|
296
|
+
ArgocdRepository,
|
|
297
|
+
ArgocdRepositoryProvider,
|
|
298
|
+
Credentials,
|
|
299
|
+
CredentialsFromEnv2 as CredentialsFromEnv,
|
|
300
|
+
fromEnv,
|
|
301
|
+
fromToken,
|
|
302
|
+
providers
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
//# debugId=0D501C98E7FA3B6C64756E2164756E21
|
|
306
|
+
//# sourceMappingURL=index.js.map
|