@alchemy.run/fly 2.0.0-beta.85 → 2.0.0-beta.87

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.
Files changed (271) hide show
  1. package/lib/App.d.ts +26 -4
  2. package/lib/App.d.ts.map +1 -1
  3. package/lib/App.js +25 -2
  4. package/lib/App.js.map +1 -1
  5. package/lib/AuthProvider.d.ts +1 -1
  6. package/lib/AuthProvider.d.ts.map +1 -1
  7. package/lib/AuthProvider.js.map +1 -1
  8. package/lib/BindService.d.ts +7 -7
  9. package/lib/BindService.d.ts.map +1 -1
  10. package/lib/BindService.js +20 -27
  11. package/lib/BindService.js.map +1 -1
  12. package/lib/Bootstrap.d.ts.map +1 -1
  13. package/lib/Bootstrap.js +2 -1
  14. package/lib/Bootstrap.js.map +1 -1
  15. package/lib/Bucket.d.ts +36 -2
  16. package/lib/Bucket.d.ts.map +1 -1
  17. package/lib/Bucket.js +181 -28
  18. package/lib/Bucket.js.map +1 -1
  19. package/lib/BucketBinding.d.ts.map +1 -1
  20. package/lib/BucketBinding.js.map +1 -1
  21. package/lib/Catalog.d.ts.map +1 -1
  22. package/lib/Catalog.js.map +1 -1
  23. package/lib/Certificate.d.ts +25 -1
  24. package/lib/Certificate.d.ts.map +1 -1
  25. package/lib/Certificate.js +18 -0
  26. package/lib/Certificate.js.map +1 -1
  27. package/lib/Checkpoint.d.ts.map +1 -1
  28. package/lib/Checkpoint.js.map +1 -1
  29. package/lib/CheckpointHttp.d.ts.map +1 -1
  30. package/lib/CheckpointHttp.js.map +1 -1
  31. package/lib/ConnectPostgres.d.ts.map +1 -1
  32. package/lib/ConnectPostgres.js.map +1 -1
  33. package/lib/ConnectPostgresHttp.d.ts.map +1 -1
  34. package/lib/ConnectPostgresHttp.js.map +1 -1
  35. package/lib/Contributions.d.ts +1 -1
  36. package/lib/Contributions.d.ts.map +1 -1
  37. package/lib/Contributions.js.map +1 -1
  38. package/lib/Credentials.d.ts +4 -3
  39. package/lib/Credentials.d.ts.map +1 -1
  40. package/lib/Credentials.js +9 -5
  41. package/lib/Credentials.js.map +1 -1
  42. package/lib/Decrypt.d.ts.map +1 -1
  43. package/lib/Decrypt.js.map +1 -1
  44. package/lib/DecryptHttp.d.ts.map +1 -1
  45. package/lib/DecryptHttp.js.map +1 -1
  46. package/lib/DeleteObject.d.ts.map +1 -1
  47. package/lib/DeleteObject.js.map +1 -1
  48. package/lib/DeleteObjectHttp.d.ts.map +1 -1
  49. package/lib/DeleteObjectHttp.js.map +1 -1
  50. package/lib/Deployment.d.ts.map +1 -1
  51. package/lib/Deployment.js.map +1 -1
  52. package/lib/DeploymentImages.d.ts.map +1 -1
  53. package/lib/DeploymentImages.js.map +1 -1
  54. package/lib/DeploymentState.d.ts.map +1 -1
  55. package/lib/DeploymentState.js.map +1 -1
  56. package/lib/Encrypt.d.ts.map +1 -1
  57. package/lib/Encrypt.js.map +1 -1
  58. package/lib/EncryptHttp.d.ts.map +1 -1
  59. package/lib/EncryptHttp.js.map +1 -1
  60. package/lib/Environment.d.ts.map +1 -1
  61. package/lib/Environment.js.map +1 -1
  62. package/lib/Errors.d.ts.map +1 -1
  63. package/lib/Errors.js.map +1 -1
  64. package/lib/Exec.d.ts.map +1 -1
  65. package/lib/Exec.js.map +1 -1
  66. package/lib/ExecHttp.d.ts.map +1 -1
  67. package/lib/ExecHttp.js.map +1 -1
  68. package/lib/GetObject.d.ts.map +1 -1
  69. package/lib/GetObject.js.map +1 -1
  70. package/lib/GetObjectHttp.d.ts.map +1 -1
  71. package/lib/GetObjectHttp.js.map +1 -1
  72. package/lib/GetSecret.d.ts.map +1 -1
  73. package/lib/GetSecret.js.map +1 -1
  74. package/lib/GetSecretHttp.d.ts.map +1 -1
  75. package/lib/GetSecretHttp.js.map +1 -1
  76. package/lib/HeadObject.d.ts.map +1 -1
  77. package/lib/HeadObject.js.map +1 -1
  78. package/lib/HeadObjectHttp.d.ts.map +1 -1
  79. package/lib/HeadObjectHttp.js.map +1 -1
  80. package/lib/IpAssignment.d.ts +24 -1
  81. package/lib/IpAssignment.d.ts.map +1 -1
  82. package/lib/IpAssignment.js +17 -0
  83. package/lib/IpAssignment.js.map +1 -1
  84. package/lib/ListObjectsV2.d.ts.map +1 -1
  85. package/lib/ListObjectsV2.js.map +1 -1
  86. package/lib/ListObjectsV2Http.d.ts.map +1 -1
  87. package/lib/ListObjectsV2Http.js.map +1 -1
  88. package/lib/ListSecrets.d.ts.map +1 -1
  89. package/lib/ListSecrets.js.map +1 -1
  90. package/lib/ListSecretsHttp.d.ts.map +1 -1
  91. package/lib/ListSecretsHttp.js.map +1 -1
  92. package/lib/Machine.d.ts +26 -1
  93. package/lib/Machine.d.ts.map +1 -1
  94. package/lib/Machine.js +16 -1
  95. package/lib/Machine.js.map +1 -1
  96. package/lib/MachineContainers.d.ts.map +1 -1
  97. package/lib/MachineContainers.js.map +1 -1
  98. package/lib/Metadata.d.ts.map +1 -1
  99. package/lib/Metadata.js.map +1 -1
  100. package/lib/MountVolume.d.ts +7 -2
  101. package/lib/MountVolume.d.ts.map +1 -1
  102. package/lib/MountVolume.js.map +1 -1
  103. package/lib/Postgres.d.ts +33 -1
  104. package/lib/Postgres.d.ts.map +1 -1
  105. package/lib/Postgres.js +20 -0
  106. package/lib/Postgres.js.map +1 -1
  107. package/lib/PostgresMigrations.d.ts.map +1 -1
  108. package/lib/PostgresMigrations.js.map +1 -1
  109. package/lib/Providers.d.ts +1 -1
  110. package/lib/Providers.d.ts.map +1 -1
  111. package/lib/Providers.js.map +1 -1
  112. package/lib/PutObject.d.ts.map +1 -1
  113. package/lib/PutObject.js.map +1 -1
  114. package/lib/PutObjectHttp.d.ts.map +1 -1
  115. package/lib/PutObjectHttp.js.map +1 -1
  116. package/lib/ReadRedis.d.ts.map +1 -1
  117. package/lib/ReadRedis.js.map +1 -1
  118. package/lib/ReadRedisHttp.d.ts.map +1 -1
  119. package/lib/ReadRedisHttp.js.map +1 -1
  120. package/lib/ReadWriteRedis.d.ts.map +1 -1
  121. package/lib/ReadWriteRedis.js.map +1 -1
  122. package/lib/ReadWriteRedisHttp.d.ts.map +1 -1
  123. package/lib/ReadWriteRedisHttp.js.map +1 -1
  124. package/lib/Redis.d.ts +21 -1
  125. package/lib/Redis.d.ts.map +1 -1
  126. package/lib/Redis.js +28 -0
  127. package/lib/Redis.js.map +1 -1
  128. package/lib/RedisBinding.d.ts.map +1 -1
  129. package/lib/RedisBinding.js.map +1 -1
  130. package/lib/RedisHttp.d.ts.map +1 -1
  131. package/lib/RedisHttp.js.map +1 -1
  132. package/lib/Region.d.ts.map +1 -1
  133. package/lib/Region.js.map +1 -1
  134. package/lib/Secret.d.ts +22 -1
  135. package/lib/Secret.d.ts.map +1 -1
  136. package/lib/Secret.js +15 -0
  137. package/lib/Secret.js.map +1 -1
  138. package/lib/SecretHttp.d.ts.map +1 -1
  139. package/lib/SecretHttp.js.map +1 -1
  140. package/lib/SecretKey.d.ts +22 -1
  141. package/lib/SecretKey.d.ts.map +1 -1
  142. package/lib/SecretKey.js +15 -0
  143. package/lib/SecretKey.js.map +1 -1
  144. package/lib/SecretKeyHttp.d.ts.map +1 -1
  145. package/lib/SecretKeyHttp.js.map +1 -1
  146. package/lib/Service.d.ts +96 -21
  147. package/lib/Service.d.ts.map +1 -1
  148. package/lib/Service.js +251 -37
  149. package/lib/Service.js.map +1 -1
  150. package/lib/Sign.d.ts.map +1 -1
  151. package/lib/Sign.js.map +1 -1
  152. package/lib/SignHttp.d.ts.map +1 -1
  153. package/lib/SignHttp.js.map +1 -1
  154. package/lib/Sprite.d.ts +22 -3
  155. package/lib/Sprite.d.ts.map +1 -1
  156. package/lib/Sprite.js +15 -0
  157. package/lib/Sprite.js.map +1 -1
  158. package/lib/SpriteHttp.d.ts.map +1 -1
  159. package/lib/SpriteHttp.js.map +1 -1
  160. package/lib/Verify.d.ts.map +1 -1
  161. package/lib/Verify.js.map +1 -1
  162. package/lib/VerifyHttp.d.ts.map +1 -1
  163. package/lib/VerifyHttp.js.map +1 -1
  164. package/lib/Volume.d.ts +3 -3
  165. package/lib/Volume.d.ts.map +1 -1
  166. package/lib/Volume.js +17 -1
  167. package/lib/Volume.js.map +1 -1
  168. package/lib/VolumeSnapshot.d.ts +32 -1
  169. package/lib/VolumeSnapshot.d.ts.map +1 -1
  170. package/lib/VolumeSnapshot.js +23 -0
  171. package/lib/VolumeSnapshot.js.map +1 -1
  172. package/lib/Website/AssetDeployment.d.ts.map +1 -1
  173. package/lib/Website/AssetDeployment.js.map +1 -1
  174. package/lib/Website/Astro.d.ts.map +1 -1
  175. package/lib/Website/Astro.js.map +1 -1
  176. package/lib/Website/Foldkit.d.ts.map +1 -1
  177. package/lib/Website/Foldkit.js.map +1 -1
  178. package/lib/Website/FrameworkSite.d.ts.map +1 -1
  179. package/lib/Website/FrameworkSite.js.map +1 -1
  180. package/lib/Website/Nextjs.d.ts.map +1 -1
  181. package/lib/Website/Nextjs.js.map +1 -1
  182. package/lib/Website/Nuxt.d.ts.map +1 -1
  183. package/lib/Website/Nuxt.js.map +1 -1
  184. package/lib/Website/Octane.d.ts.map +1 -1
  185. package/lib/Website/Octane.js.map +1 -1
  186. package/lib/Website/ReactRouter.d.ts.map +1 -1
  187. package/lib/Website/ReactRouter.js.map +1 -1
  188. package/lib/Website/SolidStart.d.ts.map +1 -1
  189. package/lib/Website/SolidStart.js.map +1 -1
  190. package/lib/Website/StaticSite.d.ts.map +1 -1
  191. package/lib/Website/StaticSite.js.map +1 -1
  192. package/lib/Website/SvelteKit.d.ts.map +1 -1
  193. package/lib/Website/SvelteKit.js.map +1 -1
  194. package/lib/Website/TanStackStart.d.ts.map +1 -1
  195. package/lib/Website/TanStackStart.js.map +1 -1
  196. package/lib/Website/Vinext.d.ts.map +1 -1
  197. package/lib/Website/Vinext.js.map +1 -1
  198. package/lib/Website/Vite.d.ts.map +1 -1
  199. package/lib/Website/Vite.js.map +1 -1
  200. package/lib/Website/Vocs.d.ts.map +1 -1
  201. package/lib/Website/Vocs.js.map +1 -1
  202. package/lib/Website/Waku.d.ts.map +1 -1
  203. package/lib/Website/Waku.js.map +1 -1
  204. package/lib/Website/index.d.ts.map +1 -1
  205. package/lib/Website/index.js.map +1 -1
  206. package/lib/WriteCertificates.d.ts.map +1 -1
  207. package/lib/WriteCertificates.js.map +1 -1
  208. package/lib/WriteCertificatesHttp.d.ts.map +1 -1
  209. package/lib/WriteCertificatesHttp.js.map +1 -1
  210. package/lib/WriteRedis.d.ts.map +1 -1
  211. package/lib/WriteRedis.js.map +1 -1
  212. package/lib/WriteRedisHttp.d.ts.map +1 -1
  213. package/lib/WriteRedisHttp.js.map +1 -1
  214. package/lib/WriteSecret.d.ts.map +1 -1
  215. package/lib/WriteSecret.js.map +1 -1
  216. package/lib/WriteSecretHttp.d.ts.map +1 -1
  217. package/lib/WriteSecretHttp.js.map +1 -1
  218. package/lib/bluegreen.d.ts +5 -4
  219. package/lib/bluegreen.d.ts.map +1 -1
  220. package/lib/bluegreen.js +1 -1
  221. package/lib/bluegreen.js.map +1 -1
  222. package/lib/hosted.d.ts +16 -0
  223. package/lib/hosted.d.ts.map +1 -1
  224. package/lib/hosted.js +101 -11
  225. package/lib/hosted.js.map +1 -1
  226. package/lib/index.d.ts.map +1 -1
  227. package/lib/index.js.map +1 -1
  228. package/lib/internal/Oidc.d.ts +15 -0
  229. package/lib/internal/Oidc.d.ts.map +1 -0
  230. package/lib/internal/Oidc.js +73 -0
  231. package/lib/internal/Oidc.js.map +1 -0
  232. package/lib/internal/RemoteBuilder.d.ts.map +1 -1
  233. package/lib/internal/RemoteBuilder.js.map +1 -1
  234. package/lib/leases.d.ts +6 -2
  235. package/lib/leases.d.ts.map +1 -1
  236. package/lib/leases.js +25 -5
  237. package/lib/leases.js.map +1 -1
  238. package/lib/ports.d.ts.map +1 -1
  239. package/lib/ports.js.map +1 -1
  240. package/lib/replicas.d.ts +38 -26
  241. package/lib/replicas.d.ts.map +1 -1
  242. package/lib/replicas.js +57 -2
  243. package/lib/replicas.js.map +1 -1
  244. package/lib/rpc.d.ts +14 -12
  245. package/lib/rpc.d.ts.map +1 -1
  246. package/lib/rpc.js +38 -40
  247. package/lib/rpc.js.map +1 -1
  248. package/package.json +15 -15
  249. package/src/App.ts +36 -3
  250. package/src/BindService.ts +27 -34
  251. package/src/Bootstrap.ts +2 -0
  252. package/src/Bucket.ts +264 -33
  253. package/src/Certificate.ts +32 -1
  254. package/src/Credentials.ts +9 -5
  255. package/src/IpAssignment.ts +31 -1
  256. package/src/Machine.ts +34 -1
  257. package/src/MountVolume.ts +5 -2
  258. package/src/Postgres.ts +43 -1
  259. package/src/Redis.ts +43 -1
  260. package/src/Secret.ts +29 -1
  261. package/src/SecretKey.ts +29 -1
  262. package/src/Service.ts +389 -70
  263. package/src/Sprite.ts +34 -8
  264. package/src/Volume.ts +25 -1
  265. package/src/VolumeSnapshot.ts +39 -1
  266. package/src/bluegreen.ts +4 -1
  267. package/src/hosted.ts +118 -13
  268. package/src/internal/Oidc.ts +99 -0
  269. package/src/leases.ts +35 -7
  270. package/src/replicas.ts +63 -2
  271. package/src/rpc.ts +37 -40
package/src/Machine.ts CHANGED
@@ -33,6 +33,7 @@ import type { Providers } from "./Providers.ts";
33
33
  import {
34
34
  deleteReplicaSet,
35
35
  listReplicaSets,
36
+ lookupReplicaSet,
36
37
  observeReplicaSet,
37
38
  reconcileReplicas,
38
39
  resolveCount,
@@ -379,9 +380,25 @@ export type Machine = Resource<
379
380
  replicas: Replica[];
380
381
  },
381
382
  ServiceBinding,
382
- Providers
383
+ Providers,
384
+ MachineLookup
383
385
  >;
384
386
 
387
+ /**
388
+ * Props for {@link Machine.lookup}: find Machines this stack doesn't
389
+ * manage by their App and name.
390
+ */
391
+ export interface MachineLookup {
392
+ /** Fly App name the Machines run in. */
393
+ appName: string;
394
+ /**
395
+ * Machine name (unique per App). Replicas named `{name}-{N}` are
396
+ * found with it, as are the replicas of an Alchemy Machine whose base
397
+ * name it is.
398
+ */
399
+ name: string;
400
+ }
401
+
385
402
  /**
386
403
  * A Fly.Machine is a Firecracker VM running one image or a named container group.
387
404
  *
@@ -838,6 +855,17 @@ export type Machine = Resource<
838
855
  * discovers unfinished owned generations.
839
856
  * See the [deployment guide](/fly/compute/deployments) for recovery and limits.
840
857
  *
858
+ * ### Looking up existing Machines
859
+ * `Machine.lookup` references Machines Alchemy doesn't manage (started with
860
+ * `fly machine run` or by another stack). It is read during plan/deploy,
861
+ * never created, updated or deleted.
862
+ *
863
+ * **Example:** Reference an existing Machine
864
+ * ```typescript
865
+ * const worker = Fly.Machine.lookup({ appName: "my-app", name: "worker" });
866
+ * const address = worker.privateIp;
867
+ * ```
868
+ *
841
869
  * @resource
842
870
  * @product Machine
843
871
  */
@@ -1154,6 +1182,11 @@ export const MachineProvider = () =>
1154
1182
  return output.rolloutPending ? { action: "update" as const } : undefined;
1155
1183
  }),
1156
1184
 
1185
+ lookup: Effect.fn(function* ({ appName, name }) {
1186
+ const found = yield* lookupReplicaSet({ appName, name });
1187
+ return found === undefined ? undefined : toAttrs(found);
1188
+ }),
1189
+
1157
1190
  read: Effect.fn(function* ({ id, fqn, instanceId, olds, output }) {
1158
1191
  const appName = appNameOf(olds?.app) ?? output?.appName;
1159
1192
  const name = yield* resolveMachineName(id, olds?.name, output?.baseName ?? output?.name);
@@ -116,6 +116,11 @@ export interface ServiceBinding {
116
116
  * published.
117
117
  */
118
118
  target?: BoundTarget;
119
+ /**
120
+ * A Service that calls this one, recorded on the target by
121
+ * `Fly.bindService`. Only the Apps recorded here may call its methods.
122
+ */
123
+ caller?: { appName: string };
119
124
  }
120
125
 
121
126
  /** A Service bound by `Fly.bindService` or `Fly.bindEndpoint`. */
@@ -128,8 +133,6 @@ export interface BoundTarget {
128
133
  network: string | undefined;
129
134
  /** The bound Service's private address; `undefined` when it publishes nothing. */
130
135
  privateUrl: string | undefined;
131
- /** The bound Service's caller token. */
132
- rpcToken?: import("effect/Redacted").Redacted<string>;
133
136
  /** Port `Fly.bindEndpoint` targets; the binding port for `bindService`. */
134
137
  port?: number;
135
138
  /** Ports the bound Service publishes, for `Fly.bindEndpoint`. */
package/src/Postgres.ts CHANGED
@@ -93,6 +93,13 @@ export interface PostgresProps {
93
93
  * is reachable on the org private network; deploy-time apply needs a
94
94
  * route to that network (a WireGuard peer, `fly mpg proxy`, or a
95
95
  * machine already on 6PN).
96
+ *
97
+ * History is forward-only and linear. A new file must sort after every
98
+ * applied one, or the deploy fails with `NonLinearMigrationHistoryError`;
99
+ * an edited or deleted applied file fails with
100
+ * `RewrittenMigrationHistoryError`. Renaming an applied file without
101
+ * changing its contents keeps it applied. See
102
+ * [Migrations](https://alchemy.run/sql/effect-sql/migrations#change-migration-history-safely).
96
103
  */
97
104
  migrations?: MigrationsInput;
98
105
  /**
@@ -143,9 +150,24 @@ export type Postgres = Resource<
143
150
  importHashes: Record<string, string>;
144
151
  },
145
152
  never,
146
- Providers
153
+ Providers,
154
+ PostgresLookup
147
155
  >;
148
156
 
157
+ /**
158
+ * Props for {@link Postgres.lookup}: find a Managed Postgres cluster
159
+ * this stack doesn't manage by its name.
160
+ */
161
+ export interface PostgresLookup {
162
+ /** Cluster name (unique in the org). */
163
+ name: string;
164
+ /**
165
+ * Organization slug.
166
+ * @default the current token's org
167
+ */
168
+ orgSlug?: string;
169
+ }
170
+
149
171
  /**
150
172
  * A Fly.Postgres is a Managed Postgres (MPG) cluster. It is billed.
151
173
  * Do not wrap unmanaged `fly postgres`.
@@ -280,6 +302,18 @@ export type Postgres = Resource<
280
302
  * });
281
303
  * ```
282
304
  *
305
+ * ### Looking up an existing cluster
306
+ * `Postgres.lookup` references a cluster Alchemy doesn't manage (created
307
+ * with `fly mpg create` or by another stack). It is read during
308
+ * plan/deploy, never created, updated or deleted, and its connection URIs
309
+ * come from Fly like a declared cluster's.
310
+ *
311
+ * **Example:** Connect to an existing cluster
312
+ * ```typescript
313
+ * const db = Fly.Postgres.lookup({ name: "my-db" });
314
+ * const sql = yield* Fly.ConnectPostgres(db);
315
+ * ```
316
+ *
283
317
  * @resource
284
318
  * @product Postgres
285
319
  */
@@ -602,6 +636,14 @@ export const PostgresProvider = () =>
602
636
  return undefined;
603
637
  }),
604
638
 
639
+ lookup: Effect.fn(function* ({ name, orgSlug }) {
640
+ const org = orgSlug ?? (yield* resolveOrgSlug());
641
+ const found = yield* findByName(org, name);
642
+ if (found === undefined) return undefined;
643
+ const hydrated = found.id !== undefined ? yield* getClusterResponse(found.id) : undefined;
644
+ return toAttrs(hydrated?.data ?? found, { name, orgSlug: org }, hydrated?.credentials);
645
+ }),
646
+
605
647
  read: Effect.fn(function* ({ id, olds, output }) {
606
648
  const found =
607
649
  output?.clusterId !== undefined && output.clusterId.length > 0
package/src/Redis.ts CHANGED
@@ -31,6 +31,10 @@ export {
31
31
  CommandError as RedisCommandError,
32
32
  UrlMissing as RedisUrlMissing,
33
33
  } from "@alchemy.run/redis/Errors";
34
+ // Clients' runtime effects require redis's `RuntimeContext` twin, so it shows
35
+ // up in users' inferred types. Exporting it here lets TypeScript name it
36
+ // through this package without users depending on @alchemy.run/redis.
37
+ export type { RuntimeContext as RedisRuntimeContext } from "@alchemy.run/redis/RuntimeContext";
34
38
 
35
39
  export interface RedisProps {
36
40
  /**
@@ -108,9 +112,19 @@ export type Redis = Resource<
108
112
  url: Redacted.Redacted<string> | undefined;
109
113
  },
110
114
  never,
111
- Providers
115
+ Providers,
116
+ RedisLookup
112
117
  >;
113
118
 
119
+ /**
120
+ * Props for {@link Redis.lookup}: find an Upstash Redis this stack
121
+ * doesn't manage by its name.
122
+ */
123
+ export interface RedisLookup {
124
+ /** Upstash Redis name. */
125
+ name: string;
126
+ }
127
+
114
128
  /**
115
129
  * Managed Upstash Redis in a Fly org. Bind {@link ReadRedis},
116
130
  * {@link WriteRedis}, or {@link ReadWriteRedis} on a {@link Service}.
@@ -219,6 +233,17 @@ export type Redis = Resource<
219
233
  * need a specific size.
220
234
  * :::
221
235
  *
236
+ * ### Looking up an existing Redis
237
+ * `Redis.lookup` references a Redis Alchemy doesn't manage (created with
238
+ * `fly redis create` or by another stack). It is read during plan/deploy,
239
+ * never created, updated or deleted. Bind it like a declared Redis.
240
+ *
241
+ * **Example:** Read an existing Redis
242
+ * ```typescript
243
+ * const cache = Fly.Redis.lookup({ name: "my-cache" });
244
+ * const redis = yield* Fly.ReadRedis(cache);
245
+ * ```
246
+ *
222
247
  * @resource
223
248
  * @product Redis
224
249
  */
@@ -654,6 +679,23 @@ export const RedisProvider = () =>
654
679
  return undefined;
655
680
  }),
656
681
 
682
+ lookup: Effect.fn(function* ({ name }) {
683
+ const found = yield* findRedisAddOn({ name });
684
+ if (found === undefined) return undefined;
685
+ let url = unwrapSensitive(found.publicUrl);
686
+ if ((url === undefined || url.length === 0) && found.id !== undefined) {
687
+ const detail = yield* addons
688
+ .addOn({ id: found.id })
689
+ .pipe(Effect.catchTag("FlyIoParseError", () => Effect.undefined));
690
+ url = unwrapSensitive(detail?.publicUrl);
691
+ }
692
+ return toAttrs(found, {
693
+ name,
694
+ primaryRegion: DEFAULT_REDIS_REGION,
695
+ url: url === undefined || url.length === 0 ? undefined : Redacted.make(url),
696
+ });
697
+ }),
698
+
657
699
  read: Effect.fn(function* ({ id, olds, output }) {
658
700
  const name = yield* resolveName(id, olds?.name, output?.name);
659
701
  const found =
package/src/Secret.ts CHANGED
@@ -54,9 +54,21 @@ export type Secret = Resource<
54
54
  updatedAt: string | undefined;
55
55
  },
56
56
  never,
57
- Providers
57
+ Providers,
58
+ SecretLookup
58
59
  >;
59
60
 
61
+ /**
62
+ * Props for {@link Secret.lookup}: find a secret this stack doesn't
63
+ * manage by its App and name.
64
+ */
65
+ export interface SecretLookup {
66
+ /** Fly App name the secret belongs to. */
67
+ appName: string;
68
+ /** Secret name (case-sensitive). */
69
+ name: string;
70
+ }
71
+
60
72
  const resolveSecretProps = (
61
73
  props: SecretProps | Effect.Effect<SecretProps, never, Providers>,
62
74
  ): Effect.Effect<SecretProps, never, Providers> =>
@@ -196,6 +208,17 @@ const SecretResource = Resource<Secret>("Fly.Secret");
196
208
  * );
197
209
  * ```
198
210
  *
211
+ * ### Looking up an existing secret
212
+ * `Secret.lookup` references a secret Alchemy doesn't manage (set with
213
+ * `fly secrets set` or by another stack). It is read during plan/deploy,
214
+ * never set or unset. Its value is never read; `digest` changes when the
215
+ * value does.
216
+ *
217
+ * **Example:** Reference an existing secret
218
+ * ```typescript
219
+ * const token = Fly.Secret.lookup({ appName: "my-site", name: "API_TOKEN" });
220
+ * ```
221
+ *
199
222
  * @resource
200
223
  * @product Secret
201
224
  */
@@ -295,6 +318,11 @@ export const SecretProvider = () =>
295
318
  return undefined;
296
319
  }),
297
320
 
321
+ lookup: Effect.fn(function* ({ appName, name }) {
322
+ const found = yield* getByName(appName, name);
323
+ return found === undefined ? undefined : toAttrs(appName, found, name);
324
+ }),
325
+
298
326
  read: Effect.fn(function* ({ id, olds, output }) {
299
327
  const appName = output?.appName ?? (olds !== undefined ? appNameOf(olds.app) : undefined);
300
328
  if (appName === undefined) return undefined;
package/src/SecretKey.ts CHANGED
@@ -64,9 +64,21 @@ export type SecretKey = Resource<
64
64
  updatedAt: string | undefined;
65
65
  },
66
66
  never,
67
- Providers
67
+ Providers,
68
+ SecretKeyLookup
68
69
  >;
69
70
 
71
+ /**
72
+ * Props for {@link SecretKey.lookup}: find a secret key this stack
73
+ * doesn't manage by its App and name.
74
+ */
75
+ export interface SecretKeyLookup {
76
+ /** Fly App name the key belongs to. */
77
+ appName: string;
78
+ /** Secret key name. */
79
+ name: string;
80
+ }
81
+
70
82
  const resolveSecretKeyProps = (
71
83
  props: SecretKeyProps | Effect.Effect<SecretKeyProps, never, Providers>,
72
84
  ): Effect.Effect<SecretKeyProps, never, Providers> =>
@@ -173,6 +185,17 @@ const SecretKeyResource = Resource<SecretKey>("Fly.SecretKey");
173
185
  * const { valid } = yield* verify({ plaintext, signature });
174
186
  * ```
175
187
  *
188
+ * ### Looking up an existing key
189
+ * `SecretKey.lookup` references a key Alchemy doesn't manage (created with
190
+ * `fly secrets keys` or by another stack). It is read during plan/deploy,
191
+ * never generated or deleted. Bind it like a declared key.
192
+ *
193
+ * **Example:** Verify with an existing key
194
+ * ```typescript
195
+ * const Signing = Fly.SecretKey.lookup({ appName: "my-site", name: "signing" });
196
+ * const verify = yield* Fly.Verify(Signing);
197
+ * ```
198
+ *
176
199
  * @resource
177
200
  * @product Secret Key
178
201
  */
@@ -285,6 +308,11 @@ export const SecretKeyProvider = () =>
285
308
  return undefined;
286
309
  }),
287
310
 
311
+ lookup: Effect.fn(function* ({ appName, name }) {
312
+ const found = yield* getByName(appName, name);
313
+ return found === undefined ? undefined : toAttrs(appName, found, name);
314
+ }),
315
+
288
316
  read: Effect.fn(function* ({ id, olds, output }) {
289
317
  const appName = output?.appName ?? (olds !== undefined ? appNameOf(olds.app) : undefined);
290
318
  if (appName === undefined) return undefined;