alchemy-effect 0.3.0 → 0.5.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/bin/alchemy-effect.js +618 -260
- package/bin/alchemy-effect.js.map +1 -1
- package/lib/apply.d.ts +4 -4
- package/lib/apply.d.ts.map +1 -1
- package/lib/apply.js +444 -159
- package/lib/apply.js.map +1 -1
- package/lib/aws/dynamodb/table.provider.d.ts.map +1 -1
- package/lib/aws/dynamodb/table.provider.js +11 -2
- package/lib/aws/dynamodb/table.provider.js.map +1 -1
- package/lib/aws/ec2/index.d.ts +8 -0
- package/lib/aws/ec2/index.d.ts.map +1 -1
- package/lib/aws/ec2/index.js +8 -0
- package/lib/aws/ec2/index.js.map +1 -1
- package/lib/aws/ec2/internet-gateway.d.ts +65 -0
- package/lib/aws/ec2/internet-gateway.d.ts.map +1 -0
- package/lib/aws/ec2/internet-gateway.js +4 -0
- package/lib/aws/ec2/internet-gateway.js.map +1 -0
- package/lib/aws/ec2/internet-gateway.provider.d.ts +6 -0
- package/lib/aws/ec2/internet-gateway.provider.d.ts.map +1 -0
- package/lib/aws/ec2/internet-gateway.provider.js +193 -0
- package/lib/aws/ec2/internet-gateway.provider.js.map +1 -0
- package/lib/aws/ec2/route-table-association.d.ts +63 -0
- package/lib/aws/ec2/route-table-association.d.ts.map +1 -0
- package/lib/aws/ec2/route-table-association.js +4 -0
- package/lib/aws/ec2/route-table-association.js.map +1 -0
- package/lib/aws/ec2/route-table-association.provider.d.ts +4 -0
- package/lib/aws/ec2/route-table-association.provider.d.ts.map +1 -0
- package/lib/aws/ec2/route-table-association.provider.js +121 -0
- package/lib/aws/ec2/route-table-association.provider.js.map +1 -0
- package/lib/aws/ec2/route-table.d.ts +159 -0
- package/lib/aws/ec2/route-table.d.ts.map +1 -0
- package/lib/aws/ec2/route-table.js +4 -0
- package/lib/aws/ec2/route-table.js.map +1 -0
- package/lib/aws/ec2/route-table.provider.d.ts +6 -0
- package/lib/aws/ec2/route-table.provider.d.ts.map +1 -0
- package/lib/aws/ec2/route-table.provider.js +213 -0
- package/lib/aws/ec2/route-table.provider.js.map +1 -0
- package/lib/aws/ec2/route.d.ts +155 -0
- package/lib/aws/ec2/route.d.ts.map +1 -0
- package/lib/aws/ec2/route.js +3 -0
- package/lib/aws/ec2/route.js.map +1 -0
- package/lib/aws/ec2/route.provider.d.ts +4 -0
- package/lib/aws/ec2/route.provider.d.ts.map +1 -0
- package/lib/aws/ec2/route.provider.js +166 -0
- package/lib/aws/ec2/route.provider.js.map +1 -0
- package/lib/aws/ec2/subnet.provider.d.ts.map +1 -1
- package/lib/aws/ec2/subnet.provider.js +1 -1
- package/lib/aws/ec2/subnet.provider.js.map +1 -1
- package/lib/aws/ec2/vpc.d.ts +1 -0
- package/lib/aws/ec2/vpc.d.ts.map +1 -1
- package/lib/aws/ec2/vpc.provider.d.ts.map +1 -1
- package/lib/aws/ec2/vpc.provider.js +32 -10
- package/lib/aws/ec2/vpc.provider.js.map +1 -1
- package/lib/aws/index.d.ts +2 -3
- package/lib/aws/index.d.ts.map +1 -1
- package/lib/aws/index.js +2 -1
- package/lib/aws/index.js.map +1 -1
- package/lib/aws/lambda/function.provider.d.ts +2 -2
- package/lib/aws/lambda/function.provider.d.ts.map +1 -1
- package/lib/aws/lambda/function.provider.js +39 -42
- package/lib/aws/lambda/function.provider.js.map +1 -1
- package/lib/aws/sqs/queue.provider.d.ts +3 -4
- package/lib/aws/sqs/queue.provider.d.ts.map +1 -1
- package/lib/aws/sqs/queue.provider.js +17 -9
- package/lib/aws/sqs/queue.provider.js.map +1 -1
- package/lib/cli/index.d.ts +183 -100
- package/lib/cli/index.d.ts.map +1 -1
- package/lib/cloudflare/kv/namespace.client.d.ts +1 -1
- package/lib/cloudflare/kv/namespace.provider.d.ts.map +1 -1
- package/lib/cloudflare/kv/namespace.provider.js +12 -6
- package/lib/cloudflare/kv/namespace.provider.js.map +1 -1
- package/lib/cloudflare/r2/bucket.binding.js +1 -1
- package/lib/cloudflare/r2/bucket.binding.js.map +1 -1
- package/lib/cloudflare/r2/bucket.d.ts +1 -1
- package/lib/cloudflare/r2/bucket.d.ts.map +1 -1
- package/lib/cloudflare/r2/bucket.provider.d.ts +1 -2
- package/lib/cloudflare/r2/bucket.provider.d.ts.map +1 -1
- package/lib/cloudflare/r2/bucket.provider.js +23 -12
- package/lib/cloudflare/r2/bucket.provider.js.map +1 -1
- package/lib/cloudflare/worker/worker.d.ts +2 -2
- package/lib/cloudflare/worker/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker/worker.provider.d.ts +2 -3
- package/lib/cloudflare/worker/worker.provider.d.ts.map +1 -1
- package/lib/cloudflare/worker/worker.provider.js +44 -13
- package/lib/cloudflare/worker/worker.provider.js.map +1 -1
- package/lib/diff.d.ts +8 -6
- package/lib/diff.d.ts.map +1 -1
- package/lib/diff.js +13 -0
- package/lib/diff.js.map +1 -1
- package/lib/event.d.ts +1 -1
- package/lib/event.d.ts.map +1 -1
- package/lib/instance-id.d.ts +12 -0
- package/lib/instance-id.d.ts.map +1 -0
- package/lib/instance-id.js +16 -0
- package/lib/instance-id.js.map +1 -0
- package/lib/output.d.ts +4 -2
- package/lib/output.d.ts.map +1 -1
- package/lib/output.js +18 -4
- package/lib/output.js.map +1 -1
- package/lib/physical-name.d.ts +25 -1
- package/lib/physical-name.d.ts.map +1 -1
- package/lib/physical-name.js +50 -2
- package/lib/physical-name.js.map +1 -1
- package/lib/plan.d.ts +49 -42
- package/lib/plan.d.ts.map +1 -1
- package/lib/plan.js +417 -137
- package/lib/plan.js.map +1 -1
- package/lib/provider.d.ts +26 -10
- package/lib/provider.d.ts.map +1 -1
- package/lib/provider.js +9 -0
- package/lib/provider.js.map +1 -1
- package/lib/resource.d.ts +3 -2
- package/lib/resource.d.ts.map +1 -1
- package/lib/resource.js.map +1 -1
- package/lib/state.d.ts +86 -9
- package/lib/state.d.ts.map +1 -1
- package/lib/state.js +21 -18
- package/lib/state.js.map +1 -1
- package/lib/tags.d.ts +15 -0
- package/lib/tags.d.ts.map +1 -1
- package/lib/tags.js +27 -0
- package/lib/tags.js.map +1 -1
- package/lib/test.d.ts +2 -2
- package/lib/test.d.ts.map +1 -1
- package/lib/test.js +4 -4
- package/lib/test.js.map +1 -1
- package/lib/todo.d.ts +3 -0
- package/lib/todo.d.ts.map +1 -0
- package/lib/todo.js +3 -0
- package/lib/todo.js.map +1 -0
- package/lib/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/apply.ts +742 -348
- package/src/aws/dynamodb/table.provider.ts +16 -4
- package/src/aws/ec2/index.ts +8 -0
- package/src/aws/ec2/internet-gateway.provider.ts +316 -0
- package/src/aws/ec2/internet-gateway.ts +79 -0
- package/src/aws/ec2/route-table-association.provider.ts +214 -0
- package/src/aws/ec2/route-table-association.ts +82 -0
- package/src/aws/ec2/route-table.provider.ts +306 -0
- package/src/aws/ec2/route-table.ts +175 -0
- package/src/aws/ec2/route.provider.ts +213 -0
- package/src/aws/ec2/route.ts +192 -0
- package/src/aws/ec2/subnet.provider.ts +2 -2
- package/src/aws/ec2/vpc.provider.ts +36 -11
- package/src/aws/ec2/vpc.ts +2 -0
- package/src/aws/index.ts +4 -1
- package/src/aws/lambda/function.provider.ts +66 -53
- package/src/aws/sqs/queue.provider.ts +18 -11
- package/src/cloudflare/kv/namespace.provider.ts +19 -14
- package/src/cloudflare/r2/bucket.binding.ts +1 -1
- package/src/cloudflare/r2/bucket.provider.ts +34 -24
- package/src/cloudflare/r2/bucket.ts +1 -1
- package/src/cloudflare/worker/worker.provider.ts +43 -13
- package/src/cloudflare/worker/worker.ts +2 -2
- package/src/diff.ts +35 -17
- package/src/event.ts +6 -0
- package/src/instance-id.ts +20 -0
- package/src/output.ts +29 -5
- package/src/physical-name.ts +79 -2
- package/src/plan.ts +566 -214
- package/src/provider.ts +46 -10
- package/src/resource.ts +65 -8
- package/src/state.ts +150 -35
- package/src/tags.ts +31 -0
- package/src/test.ts +5 -5
- package/src/todo.ts +4 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Context from "effect/Context";
|
|
3
|
+
|
|
4
|
+
/** A 16-byte (128-bit) random hex-encoded string representing an physical instance of a logical resource */
|
|
5
|
+
export class InstanceId extends Context.Tag("instance-id")<
|
|
6
|
+
InstanceId,
|
|
7
|
+
string
|
|
8
|
+
>() {}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @returns Hex-encoded instance ID (16 random bytes)
|
|
12
|
+
*/
|
|
13
|
+
export const generateInstanceId = () =>
|
|
14
|
+
Effect.sync(() => {
|
|
15
|
+
const bytes = new Uint8Array(16);
|
|
16
|
+
crypto.getRandomValues(bytes);
|
|
17
|
+
return Array.from(bytes)
|
|
18
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
19
|
+
.join("");
|
|
20
|
+
});
|
package/src/output.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { pipe } from "effect";
|
|
2
|
-
import * as App from "./app.ts";
|
|
3
2
|
import * as Data from "effect/Data";
|
|
4
3
|
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as App from "./app.ts";
|
|
5
5
|
import { isPrimitive } from "./data.ts";
|
|
6
6
|
import type { From } from "./policy.ts";
|
|
7
|
+
import { getRefMetadata, isRef, ref as stageRef, type Ref } from "./ref.ts";
|
|
7
8
|
import type { AnyResource, Resource } from "./resource.ts";
|
|
8
|
-
import type { IsAny, UnionToIntersection } from "./util.ts";
|
|
9
9
|
import * as State from "./state.ts";
|
|
10
|
-
import
|
|
10
|
+
import type { IsAny, UnionToIntersection } from "./util.ts";
|
|
11
11
|
|
|
12
12
|
// a special symbol only used at runtime to probe the Output proxy
|
|
13
13
|
const ExprSymbol = Symbol.for("alchemy/Expr");
|
|
@@ -125,7 +125,7 @@ const proxy = (self: any): any => {
|
|
|
125
125
|
return new EffectExpr(self.expr, args[0]);
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
|
-
|
|
128
|
+
return undefined;
|
|
129
129
|
},
|
|
130
130
|
},
|
|
131
131
|
);
|
|
@@ -367,7 +367,7 @@ export const evaluate: <A, Upstream extends AnyResource, Req>(
|
|
|
367
367
|
}),
|
|
368
368
|
);
|
|
369
369
|
}
|
|
370
|
-
return resource.
|
|
370
|
+
return resource.attr;
|
|
371
371
|
} else if (Array.isArray(expr)) {
|
|
372
372
|
return yield* Effect.all(expr.map((item) => evaluate(item, upstream)));
|
|
373
373
|
} else if (typeof expr === "object" && expr !== null) {
|
|
@@ -389,6 +389,30 @@ export type Upstream<O extends Output<any, any, any>> =
|
|
|
389
389
|
}
|
|
390
390
|
: never;
|
|
391
391
|
|
|
392
|
+
export const hasOutputs = (value: any): value is Output<any, any, any> =>
|
|
393
|
+
Object.keys(upstreamAny(value)).length > 0;
|
|
394
|
+
|
|
395
|
+
export const upstreamAny = (
|
|
396
|
+
value: any,
|
|
397
|
+
): {
|
|
398
|
+
[ID in string]: Resource;
|
|
399
|
+
} => {
|
|
400
|
+
if (isExpr(value)) {
|
|
401
|
+
return upstream(value);
|
|
402
|
+
} else if (Array.isArray(value)) {
|
|
403
|
+
return Object.assign({}, ...value.map(resolveUpstream));
|
|
404
|
+
} else if (
|
|
405
|
+
value &&
|
|
406
|
+
(typeof value === "object" || typeof value === "function")
|
|
407
|
+
) {
|
|
408
|
+
return Object.assign(
|
|
409
|
+
{},
|
|
410
|
+
...Object.values(value).map((value) => resolveUpstream(value)),
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
return {};
|
|
414
|
+
};
|
|
415
|
+
|
|
392
416
|
export const upstream = <E extends Output<any, AnyResource, any>>(
|
|
393
417
|
expr: E,
|
|
394
418
|
): {
|
package/src/physical-name.ts
CHANGED
|
@@ -1,7 +1,84 @@
|
|
|
1
1
|
import * as Effect from "effect/Effect";
|
|
2
2
|
import { App } from "./app.ts";
|
|
3
|
+
import { InstanceId } from "./instance-id.ts";
|
|
3
4
|
|
|
4
|
-
export const
|
|
5
|
+
export const createPhysicalName = Effect.fn(function* ({
|
|
6
|
+
id,
|
|
7
|
+
// 16 base32 characters = 80 bits of entropy = 4 × 10⁻⁷
|
|
8
|
+
instanceId,
|
|
9
|
+
suffixLength = 16,
|
|
10
|
+
maxLength = 64,
|
|
11
|
+
}: {
|
|
12
|
+
id: string;
|
|
13
|
+
/**
|
|
14
|
+
* Hex-encoded instance ID (16 random bytes)
|
|
15
|
+
*
|
|
16
|
+
* @default - the InstanceID set by the engine in Context
|
|
17
|
+
*/
|
|
18
|
+
instanceId?: string;
|
|
19
|
+
suffixLength?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Maximum length of the physical name.
|
|
22
|
+
*
|
|
23
|
+
* If the name exceeds this length, the human-friendly portion of the name will be truncated to maxLength-suffixLength
|
|
24
|
+
*/
|
|
25
|
+
maxLength?: number;
|
|
26
|
+
}) {
|
|
5
27
|
const app = yield* App;
|
|
6
|
-
|
|
28
|
+
const sanitizedId = id.replace(/[^a-zA-Z0-9-_]/g, "-");
|
|
29
|
+
const prefix = `${app.name}-${sanitizedId}-${app.stage}-`;
|
|
30
|
+
const randomId = base32(
|
|
31
|
+
Buffer.from(instanceId ?? (yield* InstanceId), "hex"),
|
|
32
|
+
);
|
|
33
|
+
const suffix = randomId.slice(0, suffixLength);
|
|
34
|
+
const name = `${prefix}${suffix}`;
|
|
35
|
+
if (maxLength && name.length > maxLength) {
|
|
36
|
+
return `${prefix.slice(0, maxLength - suffix.length)}${suffix}`;
|
|
37
|
+
}
|
|
38
|
+
return name;
|
|
7
39
|
});
|
|
40
|
+
|
|
41
|
+
// Base32 is ideal for physical names because it's denser than hex (5 bits per char vs 4)
|
|
42
|
+
// and compatible with DNS/S3 (as opposed to base64 which contains uppercase letters and symbols).
|
|
43
|
+
|
|
44
|
+
// base32.ts
|
|
45
|
+
// Concise, fast RFC 4648 Base32 encoder (no padding), lowercase output.
|
|
46
|
+
// Charset: a-z2-7 (DNS/S3 friendly)
|
|
47
|
+
const ALPH = "abcdefghijklmnopqrstuvwxyz234567";
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Encode bytes into RFC4648 Base32 (no padding), lowercase.
|
|
51
|
+
*
|
|
52
|
+
* Performance notes:
|
|
53
|
+
* - O(n) single pass, no big-int
|
|
54
|
+
* - Avoids per-byte string concatenation by using a char array
|
|
55
|
+
*/
|
|
56
|
+
export function base32(bytes: Uint8Array): string {
|
|
57
|
+
const n = bytes.length;
|
|
58
|
+
if (n === 0) return "";
|
|
59
|
+
|
|
60
|
+
// Base32 length without padding: ceil(n*8/5)
|
|
61
|
+
const outLen = ((n * 8 + 4) / 5) | 0;
|
|
62
|
+
const out = Array.from<string>({ length: outLen });
|
|
63
|
+
|
|
64
|
+
let buffer = 0;
|
|
65
|
+
let bits = 0;
|
|
66
|
+
let o = 0;
|
|
67
|
+
|
|
68
|
+
for (let i = 0; i < n; i++) {
|
|
69
|
+
buffer = (buffer << 8) | bytes[i];
|
|
70
|
+
bits += 8;
|
|
71
|
+
|
|
72
|
+
while (bits >= 5) {
|
|
73
|
+
out[o++] = ALPH[(buffer >>> (bits - 5)) & 31];
|
|
74
|
+
bits -= 5;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (bits > 0) {
|
|
79
|
+
out[o++] = ALPH[(buffer << (5 - bits)) & 31];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// outLen computed as exact ceiling; o should match, but slice defensively.
|
|
83
|
+
return o === outLen ? out.join("") : out.slice(0, o).join("");
|
|
84
|
+
}
|