1import * as Effect from "effect/Effect";
2import * as Binding from "../../Binding.ts";
3import { isBindingHost } from "../Lambda/Function.ts";
4import type { LicenseConfiguration } from "./LicenseConfiguration.ts";
5
6/**
7 * Shared HTTP scaffolding for the AWS License Manager runtime bindings.
8 *
9 * NOT exported from `index.ts` — every `{Op}Http.ts` in this service is a
10 * thin `Layer.effect(Cap, make…HttpBinding({ … }))` over one of the builders
11 * below. Everything except the operation, the IAM action, and (for the
12 * configuration-scoped builder) the injected ARN is boilerplate.
13 *
14 * Per the `license-manager` service authorization reference, only the
15 * `license-configuration` resource type supports resource-level scoping;
16 * every other action (the checkout data plane, license/grant reads, the
17 * resource inventory) authorizes on `Resource: ["*"]`.
18 */
19
20/**
21 * Build the impl Effect for an account-level License Manager operation (the
22 * license checkout data plane, license/grant reads, resource inventory, and
23 * license-specification operations — none of which are resource-scoped in
24 * IAM).
25 */
26export const makeLicenseManagerHttpBinding = <
27 I extends object,
28 A,
29 E,
30 R,
31>(options: {
32 /**
33 * Short capability name used in the binding sid and runtime span, e.g.
34 * `"CheckoutLicense"`.
35 */
36 capability: string;
37 /** IAM actions granted on `Resource: ["*"]`. */
38 iamActions: readonly string[];
39 /** The distilled operation implementing the capability. */
40 operation: Effect.Effect<(input: I) => Effect.Effect<A, E>, never, R>;
41}) =>
42 Effect.gen(function* () {
43 const op = yield* options.operation;
44
45 return Effect.fn(function* () {
46 if (!globalThis.__ALCHEMY_RUNTIME__) {
47 const host = yield* Binding.Host;
48 if (isBindingHost(host)) {
49 yield* host.bind`Allow(${host}, AWS.LicenseManager.${options.capability}())`(
50 {
51 policyStatements: [
52 {
53 Effect: "Allow",
54 Action: [...options.iamActions],
55 Resource: ["*"],
56 },
57 ],
58 },
59 );
60 }
61 }
62 return Effect.fn(`AWS.LicenseManager.${options.capability}`)(function* (
63 request?: I,
64 ) {
65 return yield* op((request ?? {}) as I);
66 });
67 });
68 });
69
70/**
71 * Build the impl Effect for a License Manager operation scoped to one
72 * {@link LicenseConfiguration}: the deploy-time half grants `iamActions` on
73 * the bound configuration's ARN (the `license-configuration` resource type
74 * supports resource-level authorization), and the runtime half injects the
75 * configuration's ARN as the request's `LicenseConfigurationArn`.
76 */
77export const makeLicenseConfigurationHttpBinding = <
78 I extends { LicenseConfigurationArn?: string },
79 A,
80 E,
81 R,
82>(options: {
83 /**
84 * Short capability name used in the binding sid and runtime span, e.g.
85 * `"ListUsageForLicenseConfiguration"`.
86 */
87 capability: string;
88 /** IAM actions granted on the bound configuration's ARN. */
89 iamActions: readonly string[];
90 /** The distilled operation; `LicenseConfigurationArn` is injected. */
91 operation: Effect.Effect<(input: I) => Effect.Effect<A, E>, never, R>;
92}) =>
93 Effect.gen(function* () {
94 const op = yield* options.operation;
95
96 return Effect.fn(function* (configuration: LicenseConfiguration) {
97 // Output yields a DEFERRED effect — resolve again per invocation below.
98 const ConfigurationArn = yield* configuration.licenseConfigurationArn;
99 if (!globalThis.__ALCHEMY_RUNTIME__) {
100 const host = yield* Binding.Host;
101 if (isBindingHost(host)) {
102 yield* host.bind`Allow(${host}, AWS.LicenseManager.${options.capability}(${configuration}))`(
103 {
104 policyStatements: [
105 {
106 Effect: "Allow",
107 Action: [...options.iamActions],
108 Resource: [configuration.licenseConfigurationArn],
109 },
110 ],
111 },
112 );
113 }
114 }
115 return Effect.fn(
116 `AWS.LicenseManager.${options.capability}(${configuration.LogicalId})`,
117 )(function* (request?: Omit<I, "LicenseConfigurationArn">) {
118 return yield* op({
119 ...request,
120 LicenseConfigurationArn: yield* ConfigurationArn,
121 } as I);
122 });
123 });
124 });