@homeflare/alchemy 0.48.1 → 0.50.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 +11 -0
- package/dist/cloudflare/cloudflared-tunnel-api.d.ts +87 -0
- package/dist/cloudflare/cloudflared-tunnel-api.d.ts.map +1 -0
- package/dist/cloudflare/cloudflared-tunnel-form.d.ts +49 -0
- package/dist/cloudflare/cloudflared-tunnel-form.d.ts.map +1 -0
- package/dist/cloudflare/cloudflared-tunnel-harness.d.ts +45 -0
- package/dist/cloudflare/cloudflared-tunnel-harness.d.ts.map +1 -0
- package/dist/cloudflare/cloudflared-tunnel-lifecycle.d.ts +21 -0
- package/dist/cloudflare/cloudflared-tunnel-lifecycle.d.ts.map +1 -0
- package/dist/cloudflare/cloudflared-tunnel.d.ts +39 -0
- package/dist/cloudflare/cloudflared-tunnel.d.ts.map +1 -0
- package/dist/cloudflare/fake-access.d.ts +40 -0
- package/dist/cloudflare/fake-access.d.ts.map +1 -0
- package/dist/cloudflare/fake-mesh.d.ts +7 -2
- package/dist/cloudflare/fake-mesh.d.ts.map +1 -1
- package/dist/cloudflare/fake-tunnel.d.ts +48 -0
- package/dist/cloudflare/fake-tunnel.d.ts.map +1 -0
- package/dist/cloudflare/index.d.ts +15 -4
- package/dist/cloudflare/index.d.ts.map +1 -1
- package/dist/cloudflare/index.js +518 -7
- package/dist/cloudflare/index.js.map +15 -4
- package/dist/cloudflare/providers.d.ts +1 -1
- package/dist/cloudflare/providers.d.ts.map +1 -1
- package/dist/cloudflare/saas-oidc-api.d.ts +88 -0
- package/dist/cloudflare/saas-oidc-api.d.ts.map +1 -0
- package/dist/cloudflare/saas-oidc-consumer.d.ts +22 -0
- package/dist/cloudflare/saas-oidc-consumer.d.ts.map +1 -0
- package/dist/cloudflare/saas-oidc-error.d.ts +22 -0
- package/dist/cloudflare/saas-oidc-error.d.ts.map +1 -0
- package/dist/cloudflare/saas-oidc-form.d.ts +48 -0
- package/dist/cloudflare/saas-oidc-form.d.ts.map +1 -0
- package/dist/cloudflare/saas-oidc-harness.d.ts +50 -0
- package/dist/cloudflare/saas-oidc-harness.d.ts.map +1 -0
- package/dist/cloudflare/saas-oidc-lifecycle.d.ts +14 -0
- package/dist/cloudflare/saas-oidc-lifecycle.d.ts.map +1 -0
- package/dist/cloudflare/saas-oidc-props.d.ts +139 -0
- package/dist/cloudflare/saas-oidc-props.d.ts.map +1 -0
- package/dist/cloudflare/saas-oidc-team.d.ts +9 -0
- package/dist/cloudflare/saas-oidc-team.d.ts.map +1 -0
- package/dist/cloudflare/saas-oidc-wire.d.ts +58 -0
- package/dist/cloudflare/saas-oidc-wire.d.ts.map +1 -0
- package/dist/cloudflare/saas-oidc.d.ts +36 -0
- package/dist/cloudflare/saas-oidc.d.ts.map +1 -0
- package/dist/kubernetes/helm-chart-bounded.d.ts +44 -0
- package/dist/kubernetes/helm-chart-bounded.d.ts.map +1 -0
- package/dist/kubernetes/index.d.ts +12 -0
- package/dist/kubernetes/index.d.ts.map +1 -0
- package/dist/kubernetes/index.js +585 -0
- package/dist/kubernetes/index.js.map +19 -0
- package/dist/kubernetes/ready-checks.d.ts +45 -0
- package/dist/kubernetes/ready-checks.d.ts.map +1 -0
- package/dist/kubernetes/ready-classify.d.ts +23 -0
- package/dist/kubernetes/ready-classify.d.ts.map +1 -0
- package/dist/kubernetes/ready-connect.d.ts +29 -0
- package/dist/kubernetes/ready-connect.d.ts.map +1 -0
- package/dist/kubernetes/ready-declare.d.ts +5 -0
- package/dist/kubernetes/ready-declare.d.ts.map +1 -0
- package/dist/kubernetes/ready-errors.d.ts +80 -0
- package/dist/kubernetes/ready-errors.d.ts.map +1 -0
- package/dist/kubernetes/ready-poll.d.ts +61 -0
- package/dist/kubernetes/ready-poll.d.ts.map +1 -0
- package/dist/kubernetes/ready.d.ts +74 -0
- package/dist/kubernetes/ready.d.ts.map +1 -0
- package/dist/talos/fake-apiserver.d.ts +11 -2
- package/dist/talos/fake-apiserver.d.ts.map +1 -1
- package/docs/cloudflared-tunnel.md +136 -0
- package/docs/credentials.md +1 -1
- package/docs/kubernetes-ready.md +146 -0
- package/docs/ownership.md +3 -2
- package/docs/peers.md +13 -0
- package/docs/provider-standard.md +7 -0
- package/docs/saas-oidc.md +185 -0
- package/docs/upstream-conformance-families.md +1 -1
- package/docs/upstream-conformance.md +3 -0
- package/package.json +7 -1
- package/src/cloudflare/cloudflared-tunnel-api.ts +150 -0
- package/src/cloudflare/cloudflared-tunnel-edges.test.ts +179 -0
- package/src/cloudflare/cloudflared-tunnel-form.ts +78 -0
- package/src/cloudflare/cloudflared-tunnel-harness.ts +126 -0
- package/src/cloudflare/cloudflared-tunnel-lifecycle.ts +146 -0
- package/src/cloudflare/cloudflared-tunnel-state.test.ts +104 -0
- package/src/cloudflare/cloudflared-tunnel.test.ts +164 -0
- package/src/cloudflare/cloudflared-tunnel.ts +116 -0
- package/src/cloudflare/fake-access.ts +196 -0
- package/src/cloudflare/fake-mesh.ts +6 -3
- package/src/cloudflare/fake-tunnel.ts +148 -0
- package/src/cloudflare/index.ts +27 -4
- package/src/cloudflare/providers.ts +16 -3
- package/src/cloudflare/saas-oidc-api.ts +224 -0
- package/src/cloudflare/saas-oidc-consumer.ts +35 -0
- package/src/cloudflare/saas-oidc-error.ts +52 -0
- package/src/cloudflare/saas-oidc-form.test.ts +227 -0
- package/src/cloudflare/saas-oidc-form.ts +190 -0
- package/src/cloudflare/saas-oidc-harness.ts +140 -0
- package/src/cloudflare/saas-oidc-lifecycle.ts +150 -0
- package/src/cloudflare/saas-oidc-parse-error.test.ts +180 -0
- package/src/cloudflare/saas-oidc-props.ts +147 -0
- package/src/cloudflare/saas-oidc-read.test.ts +85 -0
- package/src/cloudflare/saas-oidc-stable.test.ts +38 -0
- package/src/cloudflare/saas-oidc-state.test.ts +128 -0
- package/src/cloudflare/saas-oidc-team.test.ts +88 -0
- package/src/cloudflare/saas-oidc-team.ts +70 -0
- package/src/cloudflare/saas-oidc-wire.ts +116 -0
- package/src/cloudflare/saas-oidc.test.ts +201 -0
- package/src/cloudflare/saas-oidc.ts +107 -0
- package/src/kubernetes/helm-chart-bounded.test.ts +242 -0
- package/src/kubernetes/helm-chart-bounded.ts +110 -0
- package/src/kubernetes/index.ts +28 -0
- package/src/kubernetes/ready-backoff.test.ts +124 -0
- package/src/kubernetes/ready-checks.test.ts +106 -0
- package/src/kubernetes/ready-checks.ts +165 -0
- package/src/kubernetes/ready-classify.ts +76 -0
- package/src/kubernetes/ready-connect.ts +52 -0
- package/src/kubernetes/ready-declare.test.ts +85 -0
- package/src/kubernetes/ready-declare.ts +50 -0
- package/src/kubernetes/ready-errors.ts +102 -0
- package/src/kubernetes/ready-first-install.test.ts +126 -0
- package/src/kubernetes/ready-poll-states.test.ts +92 -0
- package/src/kubernetes/ready-poll.test.ts +194 -0
- package/src/kubernetes/ready-poll.ts +215 -0
- package/src/kubernetes/ready-rollout.test.ts +58 -0
- package/src/kubernetes/ready-secrecy.test.ts +131 -0
- package/src/kubernetes/ready.fixtures.ts +103 -0
- package/src/kubernetes/ready.test.ts +205 -0
- package/src/kubernetes/ready.ts +188 -0
- package/src/talos/fake-apiserver.ts +21 -3
package/dist/cloudflare/index.js
CHANGED
|
@@ -296,16 +296,521 @@ var fetchMeshNodeToken = (ref) => Effect5.gen(function* () {
|
|
|
296
296
|
}
|
|
297
297
|
return Redacted.make(token);
|
|
298
298
|
});
|
|
299
|
-
// src/cloudflare/
|
|
299
|
+
// src/cloudflare/cloudflared-tunnel.ts
|
|
300
|
+
import { Credentials as Credentials4 } from "@distilled.cloud/cloudflare/Credentials";
|
|
300
301
|
import * as Cloudflare2 from "alchemy/Cloudflare";
|
|
302
|
+
import { isResolved as isResolved2 } from "alchemy/Diff";
|
|
301
303
|
import * as Provider3 from "alchemy/Provider";
|
|
304
|
+
import { Resource as Resource3 } from "alchemy/Resource";
|
|
305
|
+
import * as Context3 from "effect/Context";
|
|
306
|
+
import * as Effect8 from "effect/Effect";
|
|
307
|
+
import * as HttpClient5 from "effect/http/HttpClient";
|
|
308
|
+
|
|
309
|
+
// src/cloudflare/cloudflared-tunnel-api.ts
|
|
310
|
+
import * as zeroTrust3 from "@distilled.cloud/cloudflare/zero-trust";
|
|
311
|
+
import * as Data2 from "effect/Data";
|
|
312
|
+
import * as Effect6 from "effect/Effect";
|
|
313
|
+
import * as Stream2 from "effect/Stream";
|
|
314
|
+
|
|
315
|
+
class CloudflaredTunnelError extends Data2.TaggedError("CloudflaredTunnelError") {
|
|
316
|
+
}
|
|
317
|
+
var observe2 = (raw) => {
|
|
318
|
+
if (typeof raw.id !== "string" || raw.id.length === 0)
|
|
319
|
+
return;
|
|
320
|
+
if (raw.deletedAt !== undefined && raw.deletedAt !== null)
|
|
321
|
+
return;
|
|
322
|
+
if (typeof raw.tunType === "string" && raw.tunType !== "cfd_tunnel")
|
|
323
|
+
return;
|
|
324
|
+
const configSrc = raw.configSrc === "cloudflare" || raw.configSrc === "local" ? raw.configSrc : undefined;
|
|
325
|
+
return { id: raw.id, name: raw.name ?? "", configSrc };
|
|
326
|
+
};
|
|
327
|
+
var getTunnel = (accountId2, tunnelId) => zeroTrust3.getTunnelCloudflared({ accountId: accountId2, tunnelId }).pipe(Effect6.map(observe2), Effect6.catchTag("TunnelNotFound", () => Effect6.succeed(undefined)));
|
|
328
|
+
var findTunnelByName = (accountId2, name) => zeroTrust3.listTunnels.items({ accountId: accountId2, name, isDeleted: false, tunTypes: ["cfd_tunnel"] }).pipe(Stream2.map(observe2), Stream2.filter((t) => t !== undefined && t.name === name), Stream2.runCollect, Effect6.flatMap((chunk) => {
|
|
329
|
+
const matches = Array.from(chunk);
|
|
330
|
+
if (matches.length <= 1)
|
|
331
|
+
return Effect6.succeed(matches[0]);
|
|
332
|
+
const ids = matches.map((t) => t.id).join(", ");
|
|
333
|
+
return Effect6.fail(new CloudflaredTunnelError({
|
|
334
|
+
message: `Tunnel name "${name}" matches ${matches.length} live cloudflared tunnels (${ids}). Names are unique per account, so refusing to guess which one is meant.`
|
|
335
|
+
}));
|
|
336
|
+
}));
|
|
337
|
+
var createTunnel = (accountId2, name) => zeroTrust3.createTunnelCloudflared({ accountId: accountId2, name, configSrc: "cloudflare" }).pipe(Effect6.flatMap((raw) => {
|
|
338
|
+
const tunnel = observe2(raw);
|
|
339
|
+
return tunnel === undefined ? Effect6.fail(new CloudflaredTunnelError({ message: `Creating tunnel "${name}" returned no id.` })) : Effect6.succeed(tunnel);
|
|
340
|
+
}));
|
|
341
|
+
var renameTunnel = (accountId2, tunnelId, name) => zeroTrust3.patchTunnelCloudflared({ accountId: accountId2, tunnelId, name }).pipe(Effect6.map((raw) => observe2(raw) ?? { id: tunnelId, name, configSrc: undefined }));
|
|
342
|
+
var isNotFound = (error) => error._tag === "NotFound";
|
|
343
|
+
var deleteTunnel = (accountId2, tunnelId) => Effect6.gen(function* () {
|
|
344
|
+
if (tunnelId.length === 0) {
|
|
345
|
+
return yield* Effect6.fail(new CloudflaredTunnelError({ message: "Refusing to delete a tunnel with an empty id." }));
|
|
346
|
+
}
|
|
347
|
+
const live = yield* getTunnel(accountId2, tunnelId);
|
|
348
|
+
if (live === undefined)
|
|
349
|
+
return;
|
|
350
|
+
yield* zeroTrust3.deleteTunnelCloudflared({ accountId: accountId2, tunnelId }).pipe(Effect6.catchIf(isNotFound, () => Effect6.void));
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
// src/cloudflare/cloudflared-tunnel-form.ts
|
|
354
|
+
var validateCloudflaredTunnel = (props) => {
|
|
355
|
+
if (typeof props.name !== "string" || props.name.trim().length === 0) {
|
|
356
|
+
return new CloudflaredTunnelError({
|
|
357
|
+
message: "CloudflaredTunnel `name` must be a non-empty string."
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
if (props.name !== props.name.trim()) {
|
|
361
|
+
return new CloudflaredTunnelError({
|
|
362
|
+
message: `CloudflaredTunnel name "${props.name}" has leading or trailing whitespace; adoption matches names exactly.`
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
return;
|
|
366
|
+
};
|
|
367
|
+
var diffCloudflaredTunnel = (news, output, accountId2) => {
|
|
368
|
+
if (output === undefined)
|
|
369
|
+
return;
|
|
370
|
+
if (output.accountId !== accountId2)
|
|
371
|
+
return { action: "replace" };
|
|
372
|
+
const name = news.name;
|
|
373
|
+
if (typeof name === "string" && name !== output.name)
|
|
374
|
+
return { action: "update" };
|
|
375
|
+
return;
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
// src/cloudflare/cloudflared-tunnel-lifecycle.ts
|
|
379
|
+
import { Unowned as Unowned3 } from "alchemy/AdoptPolicy";
|
|
380
|
+
import * as Effect7 from "effect/Effect";
|
|
381
|
+
var attributesOf2 = (tunnel, accountId2) => ({
|
|
382
|
+
id: tunnel.id,
|
|
383
|
+
accountId: accountId2,
|
|
384
|
+
name: tunnel.name
|
|
385
|
+
});
|
|
386
|
+
var readCloudflaredTunnel = (accountId2, olds, output) => Effect7.gen(function* () {
|
|
387
|
+
const account = output?.accountId ?? accountId2;
|
|
388
|
+
if (output !== undefined) {
|
|
389
|
+
const tunnel = yield* getTunnel(account, output.id);
|
|
390
|
+
return tunnel === undefined ? undefined : attributesOf2(tunnel, account);
|
|
391
|
+
}
|
|
392
|
+
const name = olds?.name;
|
|
393
|
+
if (name === undefined)
|
|
394
|
+
return;
|
|
395
|
+
const match = yield* findTunnelByName(account, name);
|
|
396
|
+
return match === undefined ? undefined : Unowned3(attributesOf2(match, account));
|
|
397
|
+
});
|
|
398
|
+
var nameHeld = (name, holder) => new CloudflaredTunnelError({
|
|
399
|
+
message: `A tunnel named "${name}" already exists (${holder}) and is not the tunnel this resource ` + "tracks, so it is left alone: names are unique per account. If it is meant to be this " + "one, deploy under adopt(true). Otherwise choose another name; do not delete it."
|
|
400
|
+
});
|
|
401
|
+
var raced2 = (accountId2, name) => findTunnelByName(accountId2, name).pipe(Effect7.flatMap((holder) => Effect7.fail(holder === undefined ? nameHeld(name, "not a live cloudflared tunnel: another tunnel type, or one just deleted") : new CloudflaredTunnelError({
|
|
402
|
+
message: `Tunnel "${name}" (${holder.id}) appeared between this deploy's lookup and its ` + "create. The likeliest cause is this deploy itself: the SDK retries a create " + "whose response was lost. If so, deploy again under adopt(true). Otherwise " + "another creator raced this one."
|
|
403
|
+
}))));
|
|
404
|
+
var createFresh2 = (accountId2, name) => Effect7.gen(function* () {
|
|
405
|
+
const existing = yield* findTunnelByName(accountId2, name);
|
|
406
|
+
if (existing !== undefined)
|
|
407
|
+
return yield* Effect7.fail(nameHeld(name, existing.id));
|
|
408
|
+
const tunnel = yield* createTunnel(accountId2, name).pipe(Effect7.catchTag("DuplicateTunnelName", () => raced2(accountId2, name)));
|
|
409
|
+
return attributesOf2(tunnel, accountId2);
|
|
410
|
+
});
|
|
411
|
+
var requireRemote = (tunnel) => tunnel.configSrc === "local" ? Effect7.fail(new CloudflaredTunnelError({
|
|
412
|
+
message: `Tunnel "${tunnel.name}" (${tunnel.id}) is locally configured (config_src local), which cannot be changed after creation. CloudflaredTunnel manages remotely configured tunnels only; create a new tunnel under another name.`
|
|
413
|
+
})) : Effect7.void;
|
|
414
|
+
var reconcileCloudflaredTunnel = (accountId2, news, output) => Effect7.gen(function* () {
|
|
415
|
+
const invalid = validateCloudflaredTunnel(news);
|
|
416
|
+
if (invalid !== undefined)
|
|
417
|
+
return yield* Effect7.fail(invalid);
|
|
418
|
+
const owned = output !== undefined && output.accountId === accountId2 ? output : undefined;
|
|
419
|
+
const live = owned === undefined ? undefined : yield* getTunnel(accountId2, owned.id);
|
|
420
|
+
if (owned === undefined || live === undefined)
|
|
421
|
+
return yield* createFresh2(accountId2, news.name);
|
|
422
|
+
yield* requireRemote(live);
|
|
423
|
+
if (live.name === news.name)
|
|
424
|
+
return attributesOf2(live, accountId2);
|
|
425
|
+
const renamed = yield* renameTunnel(accountId2, live.id, news.name).pipe(Effect7.catchTag("DuplicateTunnelName", () => Effect7.fail(nameHeld(news.name, "held by another tunnel"))));
|
|
426
|
+
return attributesOf2(renamed, accountId2);
|
|
427
|
+
});
|
|
428
|
+
var deleteCloudflaredTunnel = (output) => deleteTunnel(output.accountId, output.id);
|
|
429
|
+
|
|
430
|
+
// src/cloudflare/cloudflared-tunnel.ts
|
|
431
|
+
var CloudflaredTunnel = Resource3("Cloudflare.CloudflaredTunnel", { defaultRemovalPolicy: "retain" });
|
|
432
|
+
var accountId2 = Effect8.gen(function* () {
|
|
433
|
+
const resolved = yield* yield* Cloudflare2.CloudflareEnvironment;
|
|
434
|
+
return resolved.accountId;
|
|
435
|
+
});
|
|
436
|
+
var CloudflaredTunnelProvider = () => Provider3.effect(CloudflaredTunnel, Effect8.gen(function* () {
|
|
437
|
+
const services = Context3.make(Cloudflare2.CloudflareEnvironment, yield* Cloudflare2.CloudflareEnvironment).pipe(Context3.add(Credentials4, yield* Credentials4), Context3.add(HttpClient5.HttpClient, yield* HttpClient5.HttpClient));
|
|
438
|
+
const run = (effect4) => Effect8.provideContext(effect4, services);
|
|
439
|
+
return CloudflaredTunnel.Provider.of({
|
|
440
|
+
stables: ["id", "accountId"],
|
|
441
|
+
list: () => Effect8.succeed([]),
|
|
442
|
+
nuke: { skip: true },
|
|
443
|
+
diff: ({ news, output }) => run(Effect8.gen(function* () {
|
|
444
|
+
const invalid = isResolved2(news) ? validateCloudflaredTunnel(news) : undefined;
|
|
445
|
+
if (invalid !== undefined)
|
|
446
|
+
return yield* Effect8.fail(invalid);
|
|
447
|
+
return diffCloudflaredTunnel(news, output, yield* accountId2);
|
|
448
|
+
})),
|
|
449
|
+
read: ({ olds, output }) => run(Effect8.flatMap(accountId2, (account) => readCloudflaredTunnel(account, olds, output))),
|
|
450
|
+
reconcile: ({ news, output }) => run(Effect8.flatMap(accountId2, (account) => reconcileCloudflaredTunnel(account, news, output))),
|
|
451
|
+
delete: ({ output }) => run(deleteCloudflaredTunnel(output))
|
|
452
|
+
});
|
|
453
|
+
}));
|
|
454
|
+
// src/cloudflare/saas-oidc.ts
|
|
455
|
+
import { Credentials as Credentials6 } from "@distilled.cloud/cloudflare/Credentials";
|
|
456
|
+
import * as Cloudflare3 from "alchemy/Cloudflare";
|
|
457
|
+
import * as Provider4 from "alchemy/Provider";
|
|
458
|
+
import { Resource as Resource4 } from "alchemy/Resource";
|
|
459
|
+
import * as Context4 from "effect/Context";
|
|
460
|
+
import * as Effect13 from "effect/Effect";
|
|
461
|
+
import * as HttpClient9 from "effect/http/HttpClient";
|
|
462
|
+
|
|
463
|
+
// src/cloudflare/saas-oidc-lifecycle.ts
|
|
464
|
+
import { Unowned as Unowned4 } from "alchemy/AdoptPolicy";
|
|
465
|
+
import { createPhysicalName } from "alchemy/PhysicalName";
|
|
466
|
+
import * as Effect12 from "effect/Effect";
|
|
467
|
+
|
|
468
|
+
// src/cloudflare/saas-oidc-api.ts
|
|
469
|
+
import { Credentials as Credentials5, formatHeaders } from "@distilled.cloud/cloudflare/Credentials";
|
|
470
|
+
import * as zeroTrust4 from "@distilled.cloud/cloudflare/zero-trust";
|
|
471
|
+
import * as Effect10 from "effect/Effect";
|
|
472
|
+
import * as Schedule from "effect/Schedule";
|
|
473
|
+
import * as Stream3 from "effect/Stream";
|
|
474
|
+
import * as HttpClient7 from "effect/http/HttpClient";
|
|
475
|
+
import * as HttpClientRequest from "effect/http/HttpClientRequest";
|
|
476
|
+
|
|
477
|
+
// src/cloudflare/saas-oidc-error.ts
|
|
478
|
+
import * as Data3 from "effect/Data";
|
|
479
|
+
import * as Effect9 from "effect/Effect";
|
|
480
|
+
|
|
481
|
+
class SaasOidcError extends Data3.TaggedError("SaasOidcError") {
|
|
482
|
+
}
|
|
483
|
+
var withheld = (operation) => () => Effect9.fail(new SaasOidcError({
|
|
484
|
+
message: `Access ${operation} succeeded at the HTTP level but the SDK could not validate the response. The response is withheld on purpose (a create response carries the client secret). Check the application in the Zero Trust dashboard, then run again.`
|
|
485
|
+
}));
|
|
486
|
+
|
|
487
|
+
// src/cloudflare/saas-oidc-wire.ts
|
|
488
|
+
var str = (value2) => typeof value2 === "string" ? value2 : undefined;
|
|
489
|
+
var bool = (value2) => typeof value2 === "boolean" ? value2 : undefined;
|
|
490
|
+
var strings = (value2) => Array.isArray(value2) && value2.every((item) => typeof item === "string") ? value2 : undefined;
|
|
491
|
+
var record = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2) ? value2 : undefined;
|
|
492
|
+
var policyIds = (policies) => {
|
|
493
|
+
const entries = policies.flatMap((policy, index) => {
|
|
494
|
+
const id = str(record(policy)?.["id"]);
|
|
495
|
+
const precedence = record(policy)?.["precedence"];
|
|
496
|
+
return id === undefined ? [] : [{ id, index, precedence: typeof precedence === "number" ? precedence : undefined }];
|
|
497
|
+
});
|
|
498
|
+
if (!entries.every((entry) => entry.precedence !== undefined))
|
|
499
|
+
return entries.map((e) => e.id);
|
|
500
|
+
return [...entries].sort((a, b) => (a.precedence ?? 0) - (b.precedence ?? 0) || a.index - b.index).map((entry) => entry.id);
|
|
501
|
+
};
|
|
502
|
+
var parseApp = (raw) => {
|
|
503
|
+
const saas = record(raw["saas_app"]);
|
|
504
|
+
const refresh = record(saas?.["refresh_token_options"]);
|
|
505
|
+
const policies = Array.isArray(raw["policies"]) ? raw["policies"] : [];
|
|
506
|
+
return {
|
|
507
|
+
id: str(raw["id"]),
|
|
508
|
+
aud: str(raw["aud"]),
|
|
509
|
+
type: str(raw["type"]),
|
|
510
|
+
name: str(raw["name"]),
|
|
511
|
+
domain: str(raw["domain"]),
|
|
512
|
+
createdAt: str(raw["created_at"]),
|
|
513
|
+
updatedAt: str(raw["updated_at"]),
|
|
514
|
+
policyIds: policyIds(policies),
|
|
515
|
+
saasApp: saas === undefined ? undefined : {
|
|
516
|
+
authType: str(saas["auth_type"]),
|
|
517
|
+
clientId: str(saas["client_id"]),
|
|
518
|
+
redirectUris: strings(saas["redirect_uris"]),
|
|
519
|
+
scopes: strings(saas["scopes"]),
|
|
520
|
+
grantTypes: strings(saas["grant_types"]),
|
|
521
|
+
accessTokenLifetime: str(saas["access_token_lifetime"]),
|
|
522
|
+
refreshTokenLifetime: str(refresh?.["lifetime"]),
|
|
523
|
+
allowPkceWithoutClientSecret: bool(saas["allow_pkce_without_client_secret"])
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
// src/cloudflare/saas-oidc-api.ts
|
|
529
|
+
var sdkWrites = {
|
|
530
|
+
create: zeroTrust4.createAccessApplicationForAccount,
|
|
531
|
+
update: zeroTrust4.updateAccessApplicationForAccount
|
|
532
|
+
};
|
|
533
|
+
var TRANSIENT_STATUS = (status) => status === 403 || status === 429 || status >= 500;
|
|
534
|
+
var retryTransient = (effect4) => effect4.pipe(Effect10.retry({
|
|
535
|
+
while: (e) => e._tag === "AccessReferenceNotFound" || e._tag === "Forbidden" || e._tag === "SaasOidcError" && TRANSIENT_STATUS(e.status ?? 0),
|
|
536
|
+
schedule: Schedule.max([
|
|
537
|
+
Schedule.min([Schedule.exponential("1 second", 1.5), Schedule.spaced("5 seconds")]),
|
|
538
|
+
Schedule.recurs(12)
|
|
539
|
+
])
|
|
540
|
+
}));
|
|
541
|
+
var refuseDebugHttp = Effect10.suspend(() => (globalThis.process?.env?.["DISTILLED_DEBUG_HTTP"] ?? "") === "" ? Effect10.void : Effect10.fail(new SaasOidcError({
|
|
542
|
+
message: "Refusing to write a SaaS OIDC application while DISTILLED_DEBUG_HTTP is set: the SDK would print the response, which carries the client secret, to stderr. Unset it and run again."
|
|
543
|
+
})));
|
|
544
|
+
var getApp = (accountId3, appId) => Effect10.gen(function* () {
|
|
545
|
+
const credentials = yield* yield* Credentials5;
|
|
546
|
+
const client = yield* HttpClient7.HttpClient;
|
|
547
|
+
const request = HttpClientRequest.get(`${credentials.apiBaseUrl}/accounts/${accountId3}/access/apps/${appId}`).pipe(HttpClientRequest.setHeaders(formatHeaders(credentials)), HttpClientRequest.acceptJson);
|
|
548
|
+
const transport = (cause) => new SaasOidcError({ message: `Access application GET failed: ${cause.message}`, status: 0 });
|
|
549
|
+
const response = yield* client.execute(request).pipe(Effect10.mapError(transport));
|
|
550
|
+
if (response.status === 404)
|
|
551
|
+
return;
|
|
552
|
+
if (response.status < 200 || response.status >= 300) {
|
|
553
|
+
return yield* Effect10.fail(new SaasOidcError({
|
|
554
|
+
message: `Access application GET returned ${response.status}`,
|
|
555
|
+
status: response.status
|
|
556
|
+
}));
|
|
557
|
+
}
|
|
558
|
+
const text = yield* response.text.pipe(Effect10.mapError(transport));
|
|
559
|
+
const body = yield* Effect10.try({
|
|
560
|
+
try: () => record(JSON.parse(text)),
|
|
561
|
+
catch: () => new SaasOidcError({ message: "Access application GET was not JSON", status: 200 })
|
|
562
|
+
});
|
|
563
|
+
const result = record(body?.["result"]);
|
|
564
|
+
return result === undefined ? undefined : parseApp(result);
|
|
565
|
+
}).pipe(retryTransient);
|
|
566
|
+
var findSaasByName = (accountId3, name) => zeroTrust4.listAccessApplicationsForAccount.items({ accountId: accountId3 }).pipe(Stream3.filter((app) => app.type === "saas" && app.name === name), Stream3.runCollect, Effect10.catchTag("CloudflareParseError", withheld("application list")), retryTransient, Effect10.flatMap((chunk) => {
|
|
567
|
+
const ids = Array.from(chunk).flatMap((app) => app.id == null ? [] : [app.id]);
|
|
568
|
+
if (ids.length <= 1)
|
|
569
|
+
return Effect10.succeed(ids[0]);
|
|
570
|
+
return Effect10.fail(new SaasOidcError({
|
|
571
|
+
message: `SaaS application name "${name}" matches ${ids.length} live apps (${ids.join(", ")}). Refusing to guess which one is meant; set \`applicationId\`.`
|
|
572
|
+
}));
|
|
573
|
+
}));
|
|
574
|
+
var sdkBody = (write) => ({
|
|
575
|
+
type: "saas",
|
|
576
|
+
name: write.name,
|
|
577
|
+
sessionDuration: write.sessionDuration,
|
|
578
|
+
...write.allowedIdps === undefined ? {} : { allowedIdps: [...write.allowedIdps] },
|
|
579
|
+
...write.autoRedirectToIdentity === undefined ? {} : { autoRedirectToIdentity: write.autoRedirectToIdentity },
|
|
580
|
+
appLauncherVisible: write.appLauncherVisible,
|
|
581
|
+
policies: [...write.policies],
|
|
582
|
+
saasApp: {
|
|
583
|
+
authType: write.saasApp.authType,
|
|
584
|
+
redirectUris: [...write.saasApp.redirectUris],
|
|
585
|
+
scopes: [...write.saasApp.scopes],
|
|
586
|
+
grantTypes: [...write.saasApp.grantTypes],
|
|
587
|
+
accessTokenLifetime: write.saasApp.accessTokenLifetime,
|
|
588
|
+
allowPkceWithoutClientSecret: write.saasApp.allowPkceWithoutClientSecret,
|
|
589
|
+
...write.saasApp.refreshTokenOptions === undefined ? {} : { refreshTokenOptions: write.saasApp.refreshTokenOptions },
|
|
590
|
+
...write.saasApp.appLauncherUrl === undefined ? {} : { appLauncherUrl: write.saasApp.appLauncherUrl }
|
|
591
|
+
}
|
|
592
|
+
});
|
|
593
|
+
var createApp = (accountId3, write) => refuseDebugHttp.pipe(Effect10.andThen(sdkWrites.create({ accountId: accountId3, ...sdkBody(write) }).pipe(Effect10.catchTag("CloudflareParseError", withheld("application create")), retryTransient)), Effect10.flatMap((created) => created.id == null ? Effect10.fail(new SaasOidcError({ message: "SaaS OIDC create did not return an id." })) : Effect10.succeed(created.id)));
|
|
594
|
+
var updateApp = (accountId3, appId, write) => refuseDebugHttp.pipe(Effect10.andThen(sdkWrites.update({ accountId: accountId3, appId, ...sdkBody(write) }).pipe(Effect10.catchTag("CloudflareParseError", withheld("application update")), retryTransient)), Effect10.asVoid);
|
|
595
|
+
var deleteApp = (accountId3, appId) => zeroTrust4.deleteAccessApplicationForAccount({ accountId: accountId3, appId }).pipe(Effect10.asVoid, Effect10.catchTags({
|
|
596
|
+
AccessApplicationNotFound: () => Effect10.void,
|
|
597
|
+
CloudflareParseError: withheld("application delete")
|
|
598
|
+
}));
|
|
599
|
+
|
|
600
|
+
// src/cloudflare/saas-oidc-form.ts
|
|
601
|
+
var HOSTNAME = /^[a-z0-9]+(?:[.-][a-z0-9]+)+$/;
|
|
602
|
+
var validateSaasOidc = (props) => {
|
|
603
|
+
const fail10 = (message) => new SaasOidcError({ message });
|
|
604
|
+
if (typeof props.teamDomain !== "string" || !HOSTNAME.test(props.teamDomain)) {
|
|
605
|
+
return fail10(`SaasOidcApplication \`teamDomain\` must be a bare lowercase hostname such as "example.cloudflareaccess.com" (no scheme, no path); got ${JSON.stringify(props.teamDomain)}.`);
|
|
606
|
+
}
|
|
607
|
+
if (props.name !== undefined && props.name.trim() === "") {
|
|
608
|
+
return fail10("SaasOidcApplication `name`, when set, must not be empty.");
|
|
609
|
+
}
|
|
610
|
+
if (props.saasApp.allowPkceWithoutClientSecret === true && !props.saasApp.grantTypes.includes("authorization_code_with_pkce")) {
|
|
611
|
+
return fail10("`allowPkceWithoutClientSecret: true` only applies to the `authorization_code_with_pkce` grant; add it to `grantTypes` or drop the flag.");
|
|
612
|
+
}
|
|
613
|
+
return;
|
|
614
|
+
};
|
|
615
|
+
var issuerFor = (teamDomain, clientId) => `https://${teamDomain}/cdn-cgi/access/sso/oidc/${clientId}`;
|
|
616
|
+
var hostOf = (domain) => domain.split("/")[0]?.toLowerCase() ?? "";
|
|
617
|
+
var checkTeam = (teamDomain, app, knownTeam) => {
|
|
618
|
+
if (app.domain === undefined) {
|
|
619
|
+
return knownTeam === undefined || knownTeam.toLowerCase() === teamDomain.toLowerCase() ? undefined : new SaasOidcError({
|
|
620
|
+
message: `SaasOidcApplication declares teamDomain "${teamDomain}" but the row recorded "${knownTeam}" and Cloudflare reports no domain for the app to confirm the change. The issuer cannot move; revert the declaration.`
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
return hostOf(app.domain) === teamDomain.toLowerCase() ? undefined : new SaasOidcError({
|
|
624
|
+
message: `SaasOidcApplication declares teamDomain "${teamDomain}" but Cloudflare reports the app on "${hostOf(app.domain)}".`
|
|
625
|
+
});
|
|
626
|
+
};
|
|
627
|
+
var refreshLifetime = (props) => props.saasApp.refreshTokenLifetime ?? "";
|
|
628
|
+
var writeBody = (news, name) => ({
|
|
629
|
+
name,
|
|
630
|
+
sessionDuration: news.sessionDuration ?? "24h",
|
|
631
|
+
allowedIdps: news.allowedIdps,
|
|
632
|
+
autoRedirectToIdentity: news.autoRedirectToIdentity,
|
|
633
|
+
appLauncherVisible: news.appLauncherVisible ?? false,
|
|
634
|
+
policies: news.policies,
|
|
635
|
+
saasApp: {
|
|
636
|
+
authType: "oidc",
|
|
637
|
+
redirectUris: news.saasApp.redirectUris,
|
|
638
|
+
scopes: news.saasApp.scopes,
|
|
639
|
+
grantTypes: news.saasApp.grantTypes,
|
|
640
|
+
accessTokenLifetime: news.saasApp.accessTokenLifetime,
|
|
641
|
+
...news.saasApp.refreshTokenLifetime === undefined ? {} : { refreshTokenOptions: { lifetime: news.saasApp.refreshTokenLifetime } },
|
|
642
|
+
allowPkceWithoutClientSecret: news.saasApp.allowPkceWithoutClientSecret ?? false,
|
|
643
|
+
appLauncherUrl: news.saasApp.appLauncherUrl
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
var sameSet = (a, b) => JSON.stringify([...a].sort()) === JSON.stringify([...b ?? []].sort());
|
|
647
|
+
var sameList = (a, b) => {
|
|
648
|
+
const other = b ?? [];
|
|
649
|
+
return a.length === other.length && a.every((item, index) => item === other[index]);
|
|
650
|
+
};
|
|
651
|
+
var needsSync = (news, observed, name) => {
|
|
652
|
+
const saas = observed.saasApp;
|
|
653
|
+
return (observed.name ?? "") !== name || (saas?.authType ?? "") !== "oidc" || !sameSet(news.saasApp.redirectUris, saas?.redirectUris) || !sameSet(news.saasApp.scopes, saas?.scopes) || !sameSet(news.saasApp.grantTypes, saas?.grantTypes) || (saas?.accessTokenLifetime ?? "") !== news.saasApp.accessTokenLifetime || refreshLifetime(news) !== (saas?.refreshTokenLifetime ?? "") || (saas?.allowPkceWithoutClientSecret ?? false) !== (news.saasApp.allowPkceWithoutClientSecret ?? false) || !sameList(news.policies, observed.policyIds);
|
|
654
|
+
};
|
|
655
|
+
var toAttributes = (app, accountId3, fallbackName, declaredTeam) => {
|
|
656
|
+
const clientId = app.saasApp?.clientId;
|
|
657
|
+
const teamDomain = declaredTeam ?? (app.domain === undefined ? undefined : hostOf(app.domain));
|
|
658
|
+
if (app.id === undefined || app.aud === undefined || clientId === undefined)
|
|
659
|
+
return;
|
|
660
|
+
if (teamDomain === undefined || teamDomain === "")
|
|
661
|
+
return;
|
|
662
|
+
const issuer = issuerFor(teamDomain, clientId);
|
|
663
|
+
const saas = app.saasApp;
|
|
664
|
+
return {
|
|
665
|
+
applicationId: app.id,
|
|
666
|
+
aud: app.aud,
|
|
667
|
+
domain: app.domain ?? issuer.replace("https://", ""),
|
|
668
|
+
name: app.name ?? fallbackName,
|
|
669
|
+
accountId: accountId3,
|
|
670
|
+
teamDomain,
|
|
671
|
+
clientId,
|
|
672
|
+
issuer,
|
|
673
|
+
authorizationEndpoint: `${issuer}/authorization`,
|
|
674
|
+
tokenEndpoint: `${issuer}/token`,
|
|
675
|
+
jwksEndpoint: `${issuer}/jwks`,
|
|
676
|
+
userinfoEndpoint: `${issuer}/userinfo`,
|
|
677
|
+
configurationEndpoint: `${issuer}/.well-known/openid-configuration`,
|
|
678
|
+
redirectUris: saas?.redirectUris ?? [],
|
|
679
|
+
scopes: saas?.scopes ?? [],
|
|
680
|
+
grantTypes: saas?.grantTypes ?? [],
|
|
681
|
+
accessTokenLifetime: saas?.accessTokenLifetime ?? "",
|
|
682
|
+
refreshTokenLifetime: saas?.refreshTokenLifetime ?? "",
|
|
683
|
+
createdAt: app.createdAt,
|
|
684
|
+
updatedAt: app.updatedAt
|
|
685
|
+
};
|
|
686
|
+
};
|
|
687
|
+
|
|
688
|
+
// src/cloudflare/saas-oidc-team.ts
|
|
689
|
+
import * as Retry from "@distilled.cloud/cloudflare/Retry";
|
|
690
|
+
import * as zeroTrust5 from "@distilled.cloud/cloudflare/zero-trust";
|
|
691
|
+
import * as Effect11 from "effect/Effect";
|
|
692
|
+
var cannotRead = (error) => error._tag === "Unauthorized" || error._tag === "Forbidden" || error._tag === "OrganizationNotFound";
|
|
693
|
+
var readAuthDomain = (accountId3) => zeroTrust5.listOrganizationsForAccount({ accountId: accountId3 }).pipe(Retry.none, Effect11.map((organization) => organization.authDomain ?? undefined), Effect11.catchTag("CloudflareParseError", withheld("organization read")), Effect11.catchIf(cannotRead, () => Effect11.succeed(undefined)));
|
|
694
|
+
var checkTeamBeforeCreate = (accountId3, teamDomain) => readAuthDomain(accountId3).pipe(Effect11.map((authDomain) => authDomain === undefined || authDomain.toLowerCase() === teamDomain.toLowerCase() ? undefined : new SaasOidcError({
|
|
695
|
+
message: `SaasOidcApplication declares teamDomain "${teamDomain}" but this account's Zero Trust organization is "${authDomain}". Refused before any write; no application was created.`
|
|
696
|
+
})));
|
|
697
|
+
|
|
698
|
+
// src/cloudflare/saas-oidc-lifecycle.ts
|
|
699
|
+
var resolveName = (id, name) => name !== undefined && name !== "" ? Effect12.succeed(name) : createPhysicalName({ id });
|
|
700
|
+
var observe3 = (accountId3, knownId, name, options = {}) => Effect12.gen(function* () {
|
|
701
|
+
const byId = knownId === undefined ? undefined : yield* getApp(accountId3, knownId);
|
|
702
|
+
if (byId !== undefined) {
|
|
703
|
+
if (byId.type !== "saas") {
|
|
704
|
+
return yield* Effect12.fail(new SaasOidcError({
|
|
705
|
+
message: `Access application ${knownId} is type "${byId.type ?? "unknown"}", not "saas". Refusing to rewrite it as a SaaS OIDC app.`
|
|
706
|
+
}));
|
|
707
|
+
}
|
|
708
|
+
return byId;
|
|
709
|
+
}
|
|
710
|
+
if (options.byIdOnly === true)
|
|
711
|
+
return;
|
|
712
|
+
const foundId = yield* findSaasByName(accountId3, name);
|
|
713
|
+
return foundId === undefined ? undefined : yield* getApp(accountId3, foundId);
|
|
714
|
+
});
|
|
715
|
+
var readSaasOidc = (accountId3, id, olds, output) => Effect12.gen(function* () {
|
|
716
|
+
const name = yield* resolveName(id, output?.name ?? olds?.name);
|
|
717
|
+
const owned = output?.applicationId;
|
|
718
|
+
const observed = yield* observe3(accountId3, owned ?? olds?.applicationId, name, {
|
|
719
|
+
byIdOnly: owned !== undefined
|
|
720
|
+
});
|
|
721
|
+
if (observed === undefined)
|
|
722
|
+
return;
|
|
723
|
+
const attributes = toAttributes(observed, output?.accountId ?? accountId3, name, output?.teamDomain ?? olds?.teamDomain);
|
|
724
|
+
if (attributes === undefined)
|
|
725
|
+
return;
|
|
726
|
+
return owned !== undefined ? attributes : Unowned4(attributes);
|
|
727
|
+
});
|
|
728
|
+
var missing = (what) => Effect12.fail(new SaasOidcError({
|
|
729
|
+
message: `SaaS OIDC ${what} succeeded but the GET did not return the app.`
|
|
730
|
+
}));
|
|
731
|
+
var reconcileSaasOidc = (accountId3, id, news, output) => Effect12.gen(function* () {
|
|
732
|
+
const invalid = validateSaasOidc(news);
|
|
733
|
+
if (invalid !== undefined)
|
|
734
|
+
return yield* Effect12.fail(invalid);
|
|
735
|
+
const name = yield* resolveName(id, news.name);
|
|
736
|
+
const ownedId = output?.applicationId;
|
|
737
|
+
let observed = yield* observe3(accountId3, ownedId ?? news.applicationId, name, { byIdOnly: ownedId !== undefined });
|
|
738
|
+
const wrongTeam = observed === undefined ? undefined : checkTeam(news.teamDomain, observed, output?.teamDomain);
|
|
739
|
+
if (wrongTeam !== undefined)
|
|
740
|
+
return yield* Effect12.fail(wrongTeam);
|
|
741
|
+
const write = writeBody(news, name);
|
|
742
|
+
if (observed === undefined) {
|
|
743
|
+
const wrongOrganization = yield* checkTeamBeforeCreate(accountId3, news.teamDomain);
|
|
744
|
+
if (wrongOrganization !== undefined)
|
|
745
|
+
return yield* Effect12.fail(wrongOrganization);
|
|
746
|
+
const createdId = yield* createApp(accountId3, write);
|
|
747
|
+
observed = yield* getApp(accountId3, createdId);
|
|
748
|
+
if (observed === undefined)
|
|
749
|
+
return yield* missing("create");
|
|
750
|
+
} else if (needsSync(news, observed, name)) {
|
|
751
|
+
const appId = observed.id;
|
|
752
|
+
if (appId === undefined) {
|
|
753
|
+
return yield* Effect12.fail(new SaasOidcError({ message: "SaaS OIDC app has no id." }));
|
|
754
|
+
}
|
|
755
|
+
yield* updateApp(accountId3, appId, write);
|
|
756
|
+
observed = yield* getApp(accountId3, appId);
|
|
757
|
+
if (observed === undefined)
|
|
758
|
+
return yield* missing("update");
|
|
759
|
+
}
|
|
760
|
+
const teamAfterWrite = checkTeam(news.teamDomain, observed, output?.teamDomain);
|
|
761
|
+
if (teamAfterWrite !== undefined)
|
|
762
|
+
return yield* Effect12.fail(teamAfterWrite);
|
|
763
|
+
const attributes = toAttributes(observed, accountId3, name, news.teamDomain);
|
|
764
|
+
if (attributes === undefined) {
|
|
765
|
+
return yield* Effect12.fail(new SaasOidcError({
|
|
766
|
+
message: "Cloudflare returned a SaaS OIDC application without an id, aud or client id."
|
|
767
|
+
}));
|
|
768
|
+
}
|
|
769
|
+
return attributes;
|
|
770
|
+
});
|
|
771
|
+
var deleteSaasOidc = (output) => deleteApp(output.accountId, output.applicationId);
|
|
772
|
+
|
|
773
|
+
// src/cloudflare/saas-oidc.ts
|
|
774
|
+
var SaasOidcApplication = Resource4("HomeFlare.Access.SaasOidcApplication", {
|
|
775
|
+
defaultRemovalPolicy: "retain"
|
|
776
|
+
});
|
|
777
|
+
var accountId3 = Effect13.gen(function* () {
|
|
778
|
+
const resolved = yield* yield* Cloudflare3.CloudflareEnvironment;
|
|
779
|
+
return resolved.accountId;
|
|
780
|
+
});
|
|
781
|
+
var SaasOidcApplicationProvider = () => Provider4.effect(SaasOidcApplication, Effect13.gen(function* () {
|
|
782
|
+
const services = Context4.make(Cloudflare3.CloudflareEnvironment, yield* Cloudflare3.CloudflareEnvironment).pipe(Context4.add(Credentials6, yield* Credentials6), Context4.add(HttpClient9.HttpClient, yield* HttpClient9.HttpClient));
|
|
783
|
+
const run = (effect5) => Effect13.provideContext(effect5, services);
|
|
784
|
+
return SaasOidcApplication.Provider.of({
|
|
785
|
+
stables: [
|
|
786
|
+
"applicationId",
|
|
787
|
+
"aud",
|
|
788
|
+
"clientId",
|
|
789
|
+
"accountId",
|
|
790
|
+
"issuer",
|
|
791
|
+
"authorizationEndpoint",
|
|
792
|
+
"tokenEndpoint",
|
|
793
|
+
"jwksEndpoint",
|
|
794
|
+
"userinfoEndpoint",
|
|
795
|
+
"configurationEndpoint"
|
|
796
|
+
],
|
|
797
|
+
list: () => Effect13.succeed([]),
|
|
798
|
+
nuke: { skip: true },
|
|
799
|
+
read: ({ id, olds, output }) => run(Effect13.flatMap(accountId3, (account) => readSaasOidc(account, id, olds, output))),
|
|
800
|
+
reconcile: ({ id, news, output }) => run(Effect13.flatMap(accountId3, (account) => reconcileSaasOidc(account, id, news, output))),
|
|
801
|
+
delete: ({ output }) => run(deleteSaasOidc(output))
|
|
802
|
+
});
|
|
803
|
+
}));
|
|
804
|
+
// src/cloudflare/providers.ts
|
|
805
|
+
import * as Cloudflare4 from "alchemy/Cloudflare";
|
|
806
|
+
import * as Provider5 from "alchemy/Provider";
|
|
302
807
|
import * as Layer from "effect/Layer";
|
|
303
|
-
class Providers extends
|
|
808
|
+
class Providers extends Provider5.ProviderCollection()("HomeflareCloudflare") {
|
|
304
809
|
}
|
|
305
|
-
var providers = () => Layer.effect(Providers,
|
|
810
|
+
var providers = () => Layer.effect(Providers, Provider5.collection([R2BucketLock, MeshNode, CloudflaredTunnel, SaasOidcApplication])).pipe(Layer.provide(Layer.mergeAll(R2BucketLockProvider().pipe(Layer.provide(Cloudflare4.CloudflareApiLive()), Layer.orDie), MeshNodeProvider().pipe(Layer.provide(Cloudflare4.CloudflareApiLive()), Layer.orDie), CloudflaredTunnelProvider().pipe(Layer.provide(Cloudflare4.CloudflareApiLive()), Layer.orDie), SaasOidcApplicationProvider().pipe(Layer.provide(Cloudflare4.CloudflareApiLive()), Layer.orDie))));
|
|
306
811
|
// src/cloudflare/website.ts
|
|
307
812
|
import * as AdoptPolicy from "alchemy/AdoptPolicy";
|
|
308
|
-
import * as
|
|
813
|
+
import * as Cloudflare5 from "alchemy/Cloudflare";
|
|
309
814
|
import * as RemovalPolicy from "alchemy/RemovalPolicy";
|
|
310
815
|
var ASTRO_FLAGS = ["nodejs_compat", "disable_nodejs_process_v2"];
|
|
311
816
|
function astroWebsite(name, props) {
|
|
@@ -316,22 +821,28 @@ function astroWebsite(name, props) {
|
|
|
316
821
|
sessionKVBindingName: props.sessionKVBindingName ?? false,
|
|
317
822
|
compatibility: { ...props.compatibility, flags: [...flags] }
|
|
318
823
|
};
|
|
319
|
-
return
|
|
824
|
+
return Cloudflare5.Website.Astro(name, merged).pipe(AdoptPolicy.adopt(true), RemovalPolicy.retain());
|
|
320
825
|
}
|
|
321
826
|
function viteWebsite(name, props) {
|
|
322
827
|
const merged = { ...props, name: props?.name ?? name };
|
|
323
|
-
return
|
|
828
|
+
return Cloudflare5.Website.Vite(name, merged).pipe(AdoptPolicy.adopt(true), RemovalPolicy.retain());
|
|
324
829
|
}
|
|
325
830
|
export {
|
|
831
|
+
CloudflaredTunnel,
|
|
832
|
+
CloudflaredTunnelError,
|
|
833
|
+
CloudflaredTunnelProvider,
|
|
326
834
|
MeshNode,
|
|
327
835
|
MeshNodeError,
|
|
328
836
|
MeshNodeProvider,
|
|
329
837
|
R2BucketLock,
|
|
838
|
+
SaasOidcApplication,
|
|
839
|
+
SaasOidcApplicationProvider,
|
|
840
|
+
SaasOidcError,
|
|
330
841
|
astroWebsite,
|
|
331
842
|
fetchMeshNodeToken,
|
|
332
843
|
providers,
|
|
333
844
|
viteWebsite
|
|
334
845
|
};
|
|
335
846
|
|
|
336
|
-
//# debugId=
|
|
847
|
+
//# debugId=C4EF78F8A64F7A6064756E2164756E21
|
|
337
848
|
//# sourceMappingURL=index.js.map
|