@infracraft/pulumi 1.26.0 → 1.28.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.
Files changed (189) hide show
  1. package/dist/commands/deploy.cjs +1 -1
  2. package/dist/commands/deploy.mjs +1 -1
  3. package/dist/dynamic/is-resolved-string.cjs +20 -0
  4. package/dist/dynamic/is-resolved-string.cjs.map +1 -0
  5. package/dist/dynamic/is-resolved-string.d.cts +14 -0
  6. package/dist/dynamic/is-resolved-string.d.cts.map +1 -0
  7. package/dist/dynamic/is-resolved-string.d.mts +14 -0
  8. package/dist/dynamic/is-resolved-string.d.mts.map +1 -0
  9. package/dist/dynamic/is-resolved-string.mjs +18 -0
  10. package/dist/dynamic/is-resolved-string.mjs.map +1 -0
  11. package/dist/fly/app.cjs.map +1 -1
  12. package/dist/fly/app.d.cts +5 -1
  13. package/dist/fly/app.d.cts.map +1 -1
  14. package/dist/fly/app.d.mts +5 -1
  15. package/dist/fly/app.d.mts.map +1 -1
  16. package/dist/fly/app.mjs.map +1 -1
  17. package/dist/fly/certificate.cjs +3 -0
  18. package/dist/fly/certificate.cjs.map +1 -1
  19. package/dist/fly/certificate.d.cts +32 -1
  20. package/dist/fly/certificate.d.cts.map +1 -1
  21. package/dist/fly/certificate.d.mts +32 -1
  22. package/dist/fly/certificate.d.mts.map +1 -1
  23. package/dist/fly/certificate.mjs +3 -1
  24. package/dist/fly/certificate.mjs.map +1 -1
  25. package/dist/fly/deploy.cjs +4 -0
  26. package/dist/fly/deploy.cjs.map +1 -1
  27. package/dist/fly/deploy.d.cts +4 -0
  28. package/dist/fly/deploy.d.cts.map +1 -1
  29. package/dist/fly/deploy.d.mts +4 -0
  30. package/dist/fly/deploy.d.mts.map +1 -1
  31. package/dist/fly/deploy.mjs +4 -0
  32. package/dist/fly/deploy.mjs.map +1 -1
  33. package/dist/fly/ip.cjs +3 -0
  34. package/dist/fly/ip.cjs.map +1 -1
  35. package/dist/fly/ip.d.cts +34 -1
  36. package/dist/fly/ip.d.cts.map +1 -1
  37. package/dist/fly/ip.d.mts +34 -1
  38. package/dist/fly/ip.d.mts.map +1 -1
  39. package/dist/fly/ip.mjs +3 -1
  40. package/dist/fly/ip.mjs.map +1 -1
  41. package/dist/fly/secret.cjs +3 -0
  42. package/dist/fly/secret.cjs.map +1 -1
  43. package/dist/fly/secret.d.cts +36 -2
  44. package/dist/fly/secret.d.cts.map +1 -1
  45. package/dist/fly/secret.d.mts +36 -2
  46. package/dist/fly/secret.d.mts.map +1 -1
  47. package/dist/fly/secret.mjs +3 -1
  48. package/dist/fly/secret.mjs.map +1 -1
  49. package/dist/fly/volume.cjs +18 -0
  50. package/dist/fly/volume.cjs.map +1 -1
  51. package/dist/fly/volume.d.cts +11 -1
  52. package/dist/fly/volume.d.cts.map +1 -1
  53. package/dist/fly/volume.d.mts +11 -1
  54. package/dist/fly/volume.d.mts.map +1 -1
  55. package/dist/fly/volume.mjs +18 -0
  56. package/dist/fly/volume.mjs.map +1 -1
  57. package/dist/neon/branch.cjs +16 -0
  58. package/dist/neon/branch.cjs.map +1 -1
  59. package/dist/neon/branch.d.cts +6 -0
  60. package/dist/neon/branch.d.cts.map +1 -1
  61. package/dist/neon/branch.d.mts +6 -0
  62. package/dist/neon/branch.d.mts.map +1 -1
  63. package/dist/neon/branch.mjs +16 -0
  64. package/dist/neon/branch.mjs.map +1 -1
  65. package/dist/neon/database.cjs.map +1 -1
  66. package/dist/neon/database.d.cts +1 -1
  67. package/dist/neon/database.d.mts +1 -1
  68. package/dist/neon/database.mjs.map +1 -1
  69. package/dist/neon/endpoint.cjs +1 -0
  70. package/dist/neon/endpoint.cjs.map +1 -1
  71. package/dist/neon/endpoint.d.cts +3 -3
  72. package/dist/neon/endpoint.d.cts.map +1 -1
  73. package/dist/neon/endpoint.d.mts +3 -3
  74. package/dist/neon/endpoint.d.mts.map +1 -1
  75. package/dist/neon/endpoint.mjs +1 -0
  76. package/dist/neon/endpoint.mjs.map +1 -1
  77. package/dist/neon/project.cjs +1 -0
  78. package/dist/neon/project.cjs.map +1 -1
  79. package/dist/neon/project.d.cts.map +1 -1
  80. package/dist/neon/project.d.mts.map +1 -1
  81. package/dist/neon/project.mjs +1 -0
  82. package/dist/neon/project.mjs.map +1 -1
  83. package/dist/neon/role.cjs +21 -0
  84. package/dist/neon/role.cjs.map +1 -1
  85. package/dist/neon/role.d.cts +5 -0
  86. package/dist/neon/role.d.cts.map +1 -1
  87. package/dist/neon/role.d.mts +5 -0
  88. package/dist/neon/role.d.mts.map +1 -1
  89. package/dist/neon/role.mjs +21 -0
  90. package/dist/neon/role.mjs.map +1 -1
  91. package/dist/railway/domain.cjs.map +1 -1
  92. package/dist/railway/domain.d.cts +5 -1
  93. package/dist/railway/domain.d.cts.map +1 -1
  94. package/dist/railway/domain.d.mts +5 -1
  95. package/dist/railway/domain.d.mts.map +1 -1
  96. package/dist/railway/domain.mjs.map +1 -1
  97. package/dist/railway/environment.cjs.map +1 -1
  98. package/dist/railway/environment.d.cts +1 -0
  99. package/dist/railway/environment.d.cts.map +1 -1
  100. package/dist/railway/environment.d.mts +1 -0
  101. package/dist/railway/environment.d.mts.map +1 -1
  102. package/dist/railway/environment.mjs.map +1 -1
  103. package/dist/railway/project-token.cjs +17 -0
  104. package/dist/railway/project-token.cjs.map +1 -1
  105. package/dist/railway/project-token.d.cts +6 -0
  106. package/dist/railway/project-token.d.cts.map +1 -1
  107. package/dist/railway/project-token.d.mts +6 -0
  108. package/dist/railway/project-token.d.mts.map +1 -1
  109. package/dist/railway/project-token.mjs +17 -0
  110. package/dist/railway/project-token.mjs.map +1 -1
  111. package/dist/railway/project.cjs +1 -0
  112. package/dist/railway/project.cjs.map +1 -1
  113. package/dist/railway/project.d.cts.map +1 -1
  114. package/dist/railway/project.d.mts.map +1 -1
  115. package/dist/railway/project.mjs +1 -0
  116. package/dist/railway/project.mjs.map +1 -1
  117. package/dist/railway/service.cjs +17 -0
  118. package/dist/railway/service.cjs.map +1 -1
  119. package/dist/railway/service.d.cts +5 -0
  120. package/dist/railway/service.d.cts.map +1 -1
  121. package/dist/railway/service.d.mts +5 -0
  122. package/dist/railway/service.d.mts.map +1 -1
  123. package/dist/railway/service.mjs +17 -0
  124. package/dist/railway/service.mjs.map +1 -1
  125. package/dist/railway/variable.cjs +3 -0
  126. package/dist/railway/variable.cjs.map +1 -1
  127. package/dist/railway/variable.d.cts +47 -1
  128. package/dist/railway/variable.d.cts.map +1 -1
  129. package/dist/railway/variable.d.mts +47 -1
  130. package/dist/railway/variable.d.mts.map +1 -1
  131. package/dist/railway/variable.mjs +3 -1
  132. package/dist/railway/variable.mjs.map +1 -1
  133. package/dist/railway/volume.cjs +26 -5
  134. package/dist/railway/volume.cjs.map +1 -1
  135. package/dist/railway/volume.d.cts +5 -0
  136. package/dist/railway/volume.d.cts.map +1 -1
  137. package/dist/railway/volume.d.mts +5 -0
  138. package/dist/railway/volume.d.mts.map +1 -1
  139. package/dist/railway/volume.mjs +26 -5
  140. package/dist/railway/volume.mjs.map +1 -1
  141. package/dist/{sandbox-BQtqMu-5.mjs → sandbox-Cw11Vveq.mjs} +63 -5
  142. package/dist/sandbox-Cw11Vveq.mjs.map +1 -0
  143. package/dist/{sandbox-BBnhmyM_.cjs → sandbox-DM817Nlx.cjs} +68 -4
  144. package/dist/sandbox-DM817Nlx.cjs.map +1 -0
  145. package/dist/sandbox.cjs +2 -1
  146. package/dist/sandbox.d.cts +20 -4
  147. package/dist/sandbox.d.cts.map +1 -1
  148. package/dist/sandbox.d.mts +20 -4
  149. package/dist/sandbox.d.mts.map +1 -1
  150. package/dist/sandbox.mjs +2 -2
  151. package/dist/vercel/deploy.cjs +4 -0
  152. package/dist/vercel/deploy.cjs.map +1 -1
  153. package/dist/vercel/deploy.d.cts +4 -0
  154. package/dist/vercel/deploy.d.cts.map +1 -1
  155. package/dist/vercel/deploy.d.mts +4 -0
  156. package/dist/vercel/deploy.d.mts.map +1 -1
  157. package/dist/vercel/deploy.mjs +4 -0
  158. package/dist/vercel/deploy.mjs.map +1 -1
  159. package/dist/vercel/marketplace-resource.cjs.map +1 -1
  160. package/dist/vercel/marketplace-resource.d.cts +1 -0
  161. package/dist/vercel/marketplace-resource.d.cts.map +1 -1
  162. package/dist/vercel/marketplace-resource.d.mts +1 -0
  163. package/dist/vercel/marketplace-resource.d.mts.map +1 -1
  164. package/dist/vercel/marketplace-resource.mjs.map +1 -1
  165. package/dist/vercel/project.cjs +20 -0
  166. package/dist/vercel/project.cjs.map +1 -1
  167. package/dist/vercel/project.d.cts +8 -0
  168. package/dist/vercel/project.d.cts.map +1 -1
  169. package/dist/vercel/project.d.mts +8 -0
  170. package/dist/vercel/project.d.mts.map +1 -1
  171. package/dist/vercel/project.mjs +20 -0
  172. package/dist/vercel/project.mjs.map +1 -1
  173. package/dist/vercel/resource-connection.cjs.map +1 -1
  174. package/dist/vercel/resource-connection.d.cts +1 -0
  175. package/dist/vercel/resource-connection.d.cts.map +1 -1
  176. package/dist/vercel/resource-connection.d.mts +1 -0
  177. package/dist/vercel/resource-connection.d.mts.map +1 -1
  178. package/dist/vercel/resource-connection.mjs.map +1 -1
  179. package/dist/vercel/variable.cjs +3 -0
  180. package/dist/vercel/variable.cjs.map +1 -1
  181. package/dist/vercel/variable.d.cts +31 -1
  182. package/dist/vercel/variable.d.cts.map +1 -1
  183. package/dist/vercel/variable.d.mts +31 -1
  184. package/dist/vercel/variable.d.mts.map +1 -1
  185. package/dist/vercel/variable.mjs +3 -1
  186. package/dist/vercel/variable.mjs.map +1 -1
  187. package/package.json +1 -1
  188. package/dist/sandbox-BBnhmyM_.cjs.map +0 -1
  189. package/dist/sandbox-BQtqMu-5.mjs.map +0 -1
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_chunk = require('../chunk-BVYJZCqc.cjs');
3
3
  const require_git_guard = require('../git-guard.cjs');
4
- const require_sandbox = require('../sandbox-BBnhmyM_.cjs');
4
+ const require_sandbox = require('../sandbox-DM817Nlx.cjs');
5
5
  let _pulumi_pulumi = require("@pulumi/pulumi");
6
6
  _pulumi_pulumi = require_chunk.__toESM(_pulumi_pulumi, 1);
7
7
  let _pulumi_command = require("@pulumi/command");
@@ -1,6 +1,6 @@
1
1
  import { t as __name } from "../chunk-OPjESj5l.mjs";
2
2
  import { isGitGuard } from "../git-guard.mjs";
3
- import { a as buildSandboxScript, n as isDeploySandbox, r as SandboxMode } from "../sandbox-BQtqMu-5.mjs";
3
+ import { a as buildSandboxScript, n as isDeploySandbox, r as SandboxMode } from "../sandbox-Cw11Vveq.mjs";
4
4
  import * as pulumi from "@pulumi/pulumi";
5
5
  import * as command from "@pulumi/command";
6
6
 
@@ -0,0 +1,20 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_chunk = require('../chunk-BVYJZCqc.cjs');
3
+ let _pulumi_pulumi = require("@pulumi/pulumi");
4
+ _pulumi_pulumi = require_chunk.__toESM(_pulumi_pulumi, 1);
5
+
6
+ //#region src/dynamic/is-resolved-string.ts
7
+ /**
8
+ * True when a dynamic-provider input holds a concrete string — neither
9
+ * `undefined` nor Pulumi's preview "unknown" sentinel. `check()` runs at plan
10
+ * time, when an input fed by another resource's output may still be
11
+ * unresolved; validation must skip those values instead of failing on the
12
+ * sentinel.
13
+ */
14
+ function isResolvedString(value) {
15
+ return typeof value === "string" && value !== _pulumi_pulumi.runtime.unknownValue;
16
+ }
17
+
18
+ //#endregion
19
+ exports.isResolvedString = isResolvedString;
20
+ //# sourceMappingURL=is-resolved-string.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-resolved-string.cjs","names":["pulumi"],"sources":["../../src/dynamic/is-resolved-string.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\n\n/**\n * True when a dynamic-provider input holds a concrete string — neither\n * `undefined` nor Pulumi's preview \"unknown\" sentinel. `check()` runs at plan\n * time, when an input fed by another resource's output may still be\n * unresolved; validation must skip those values instead of failing on the\n * sentinel.\n */\nexport function isResolvedString(value: unknown): value is string {\n\treturn typeof value === \"string\" && value !== pulumi.runtime.unknownValue;\n}\n"],"mappings":";;;;;;;;;;;;;AASA,SAAgB,iBAAiB,OAAiC;CACjE,OAAO,OAAO,UAAU,YAAY,UAAUA,eAAO,QAAQ;AAC9D"}
@@ -0,0 +1,14 @@
1
+ import { t as __name } from "../chunk-OPjESj5l.cjs";
2
+
3
+ //#region src/dynamic/is-resolved-string.d.ts
4
+ /**
5
+ * True when a dynamic-provider input holds a concrete string — neither
6
+ * `undefined` nor Pulumi's preview "unknown" sentinel. `check()` runs at plan
7
+ * time, when an input fed by another resource's output may still be
8
+ * unresolved; validation must skip those values instead of failing on the
9
+ * sentinel.
10
+ */
11
+ declare function isResolvedString(value: unknown): value is string;
12
+ //#endregion
13
+ export { isResolvedString };
14
+ //# sourceMappingURL=is-resolved-string.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-resolved-string.d.cts","names":[],"sources":["../../src/dynamic/is-resolved-string.ts"],"mappings":";;;;;;AASA;;;;iBAAgB,gBAAA,CAAiB,KAAA,YAAiB,KAAK"}
@@ -0,0 +1,14 @@
1
+ import { t as __name } from "../chunk-OPjESj5l.mjs";
2
+
3
+ //#region src/dynamic/is-resolved-string.d.ts
4
+ /**
5
+ * True when a dynamic-provider input holds a concrete string — neither
6
+ * `undefined` nor Pulumi's preview "unknown" sentinel. `check()` runs at plan
7
+ * time, when an input fed by another resource's output may still be
8
+ * unresolved; validation must skip those values instead of failing on the
9
+ * sentinel.
10
+ */
11
+ declare function isResolvedString(value: unknown): value is string;
12
+ //#endregion
13
+ export { isResolvedString };
14
+ //# sourceMappingURL=is-resolved-string.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-resolved-string.d.mts","names":[],"sources":["../../src/dynamic/is-resolved-string.ts"],"mappings":";;;;;;AASA;;;;iBAAgB,gBAAA,CAAiB,KAAA,YAAiB,KAAK"}
@@ -0,0 +1,18 @@
1
+ import { t as __name } from "../chunk-OPjESj5l.mjs";
2
+ import * as pulumi from "@pulumi/pulumi";
3
+
4
+ //#region src/dynamic/is-resolved-string.ts
5
+ /**
6
+ * True when a dynamic-provider input holds a concrete string — neither
7
+ * `undefined` nor Pulumi's preview "unknown" sentinel. `check()` runs at plan
8
+ * time, when an input fed by another resource's output may still be
9
+ * unresolved; validation must skip those values instead of failing on the
10
+ * sentinel.
11
+ */
12
+ function isResolvedString(value) {
13
+ return typeof value === "string" && value !== pulumi.runtime.unknownValue;
14
+ }
15
+
16
+ //#endregion
17
+ export { isResolvedString };
18
+ //# sourceMappingURL=is-resolved-string.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-resolved-string.mjs","names":[],"sources":["../../src/dynamic/is-resolved-string.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\n\n/**\n * True when a dynamic-provider input holds a concrete string — neither\n * `undefined` nor Pulumi's preview \"unknown\" sentinel. `check()` runs at plan\n * time, when an input fed by another resource's output may still be\n * unresolved; validation must skip those values instead of failing on the\n * sentinel.\n */\nexport function isResolvedString(value: unknown): value is string {\n\treturn typeof value === \"string\" && value !== pulumi.runtime.unknownValue;\n}\n"],"mappings":";;;;;;;;;;;AASA,SAAgB,iBAAiB,OAAiC;CACjE,OAAO,OAAO,UAAU,YAAY,UAAU,OAAO,QAAQ;AAC9D"}
@@ -1 +1 @@
1
- {"version":3,"file":"app.cjs","names":["FlyClient","pulumi"],"sources":["../../src/fly/app.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\n\nimport { FlyClient } from \"./client\";\nimport type { FlyProvider } from \"./provider\";\n\n/** Resolved inputs for the Fly app dynamic provider. */\ninterface FlyAppInputs {\n\t/** Fly API token. */\n\ttoken: string;\n\n\t/** App name (globally unique). Used as the resource identifier. */\n\tname: string;\n\n\t/** Org slug used only when creating a new app. */\n\torganization?: string;\n}\n\n/** Persisted state for the Fly app. */\ninterface FlyAppOutputs extends FlyAppInputs {\n\t/** App identifier — equals the app name (all child paths key off the name). */\n\tappId: string;\n}\n\n/** Get-app response (only the fields we read). */\ninterface FlyAppResponse {\n\tid: string;\n\tname: string;\n}\n\n/**\n * Dynamic provider implementing adopt-or-create for Fly apps.\n *\n * `create()` does `GET /v1/apps/{name}`; if found it adopts, otherwise it\n * `POST /v1/apps`. `delete()` is a no-op — deleting a Fly app destroys\n * everything in it, so (like Railway/Neon/Vercel top-level resources) Pulumi\n * does not delete apps.\n *\n * @internal Exported only for unit testing; not part of the public API surface.\n */\nexport class FlyAppResourceProvider implements pulumi.dynamic.ResourceProvider {\n\tasync create(inputs: FlyAppInputs): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new FlyClient(inputs.token);\n\n\t\tconst existing = await client.tryGet<FlyAppResponse>(\n\t\t\t`/v1/apps/${inputs.name}`,\n\t\t);\n\n\t\tif (existing) {\n\t\t\tpulumi.log.info(`Adopting existing Fly app \"${inputs.name}\"`);\n\t\t} else {\n\t\t\tif (!inputs.organization) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`FlyApp \"${inputs.name}\": an organization is required to create a new app — set it on FlyProvider or FlyApp args`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tpulumi.log.info(`Fly app \"${inputs.name}\" not found — creating...`);\n\n\t\t\tawait client.post(\"/v1/apps\", {\n\t\t\t\tapp_name: inputs.name,\n\t\t\t\torg_slug: inputs.organization,\n\t\t\t});\n\t\t}\n\n\t\tconst outs: FlyAppOutputs = { ...inputs, appId: inputs.name };\n\n\t\treturn { id: inputs.name, outs };\n\t}\n\n\tasync read(\n\t\tid: string,\n\t\tprops: FlyAppOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new FlyClient(props.token);\n\t\tconst app = await client.tryGet<FlyAppResponse>(`/v1/apps/${id}`);\n\n\t\tif (!app) {\n\t\t\t// Resource gone → blank id lets refresh reconcile the deletion.\n\t\t\treturn {};\n\t\t}\n\n\t\treturn { id, props: { ...props, name: app.name, appId: app.name } };\n\t}\n\n\tasync update(\n\t\tid: string,\n\t\t_olds: FlyAppOutputs,\n\t\tnews: FlyAppInputs,\n\t): Promise<pulumi.dynamic.UpdateResult> {\n\t\treturn { outs: { ...news, appId: id } };\n\t}\n\n\tasync delete(): Promise<void> {\n\t\tpulumi.log.warn(\n\t\t\t\"Fly app deletion skipped — apps are not deleted by Pulumi (would destroy all contained resources)\",\n\t\t);\n\t}\n\n\tasync diff(\n\t\t_id: string,\n\t\tolds: FlyAppOutputs,\n\t\tnews: FlyAppInputs,\n\t): Promise<pulumi.dynamic.DiffResult> {\n\t\tconst replaces: string[] = [];\n\n\t\tif (olds.name !== news.name) {\n\t\t\treplaces.push(\"name\");\n\t\t}\n\n\t\tif (olds.organization !== news.organization) {\n\t\t\treplaces.push(\"organization\");\n\t\t}\n\n\t\treturn {\n\t\t\tchanges: replaces.length > 0,\n\t\t\treplaces,\n\t\t\tdeleteBeforeReplace: true,\n\t\t};\n\t}\n}\n\n/** Internal dynamic resource — not part of the public API. */\nclass FlyAppResource extends pulumi.dynamic.Resource {\n\tpublic declare readonly appId: pulumi.Output<string>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: {\n\t\t\ttoken: pulumi.Input<string>;\n\t\t\tname: pulumi.Input<string>;\n\t\t\torganization?: pulumi.Input<string | undefined>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(\n\t\t\tnew FlyAppResourceProvider(),\n\t\t\tname,\n\t\t\t{ ...args, appId: undefined },\n\t\t\t// The API token flows into dynamic-provider state with the outputs — mark it secret there.\n\t\t\t{ ...opts, additionalSecretOutputs: [\"token\"] },\n\t\t);\n\t}\n}\n\n/** Options type for FlyApp — replaces Pulumi's native `provider` field. */\ntype FlyAppOptions = Omit<pulumi.ComponentResourceOptions, \"provider\"> & {\n\t/** Fly authentication context. */\n\tprovider: FlyProvider;\n};\n\n/** Args for FlyApp. */\nexport interface FlyAppArgs {\n\t/** App name (globally unique). Used for adoption lookup and as `.id`. */\n\tname: pulumi.Input<string>;\n\n\t/**\n\t * Org slug for app creation. Overrides `FlyProvider.organization`.\n\t * Ignored when the app already exists (adoption).\n\t */\n\torganization?: pulumi.Input<string>;\n}\n\n/**\n * Manages a Fly app with adopt-or-create semantics.\n *\n * @example\n * ```typescript\n * const app = new FlyApp(\"api\", { name: \"rby-api\" }, { provider });\n * ```\n */\nexport class FlyApp extends pulumi.ComponentResource {\n\t/** App identifier (equals the app name). */\n\tpublic readonly id: pulumi.Output<string>;\n\n\tconstructor(name: string, args: FlyAppArgs, opts: FlyAppOptions) {\n\t\tconst { provider, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:fly:App\", name, {}, pulumiOpts);\n\n\t\tconst resource = new FlyAppResource(\n\t\t\t`${name}-resource`,\n\t\t\t{\n\t\t\t\ttoken: provider.token,\n\t\t\t\tname: args.name,\n\t\t\t\torganization: args.organization ?? provider.organization,\n\t\t\t},\n\t\t\t{ parent: this },\n\t\t);\n\n\t\tthis.id = resource.appId;\n\n\t\tthis.registerOutputs({ id: this.id });\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAuCA,IAAa,yBAAb,MAA+E;CAC9E,MAAM,OAAO,QAA4D;EACxE,MAAM,SAAS,IAAIA,6BAAU,OAAO,KAAK;EAMzC,IAAI,MAJmB,OAAO,OAC7B,YAAY,OAAO,MACpB,GAGC,eAAO,IAAI,KAAK,8BAA8B,OAAO,KAAK,EAAE;OACtD;GACN,IAAI,CAAC,OAAO,cACX,MAAM,IAAI,MACT,WAAW,OAAO,KAAK,0FACxB;GAGD,eAAO,IAAI,KAAK,YAAY,OAAO,KAAK,0BAA0B;GAElE,MAAM,OAAO,KAAK,YAAY;IAC7B,UAAU,OAAO;IACjB,UAAU,OAAO;GAClB,CAAC;EACF;EAEA,MAAM,OAAsB;GAAE,GAAG;GAAQ,OAAO,OAAO;EAAK;EAE5D,OAAO;GAAE,IAAI,OAAO;GAAM;EAAK;CAChC;CAEA,MAAM,KACL,IACA,OACqC;EAErC,MAAM,MAAM,MAAM,IADCA,6BAAU,MAAM,KACZ,EAAE,OAAuB,YAAY,IAAI;EAEhE,IAAI,CAAC,KAEJ,OAAO,CAAC;EAGT,OAAO;GAAE;GAAI,OAAO;IAAE,GAAG;IAAO,MAAM,IAAI;IAAM,OAAO,IAAI;GAAK;EAAE;CACnE;CAEA,MAAM,OACL,IACA,OACA,MACuC;EACvC,OAAO,EAAE,MAAM;GAAE,GAAG;GAAM,OAAO;EAAG,EAAE;CACvC;CAEA,MAAM,SAAwB;EAC7B,eAAO,IAAI,KACV,mGACD;CACD;CAEA,MAAM,KACL,KACA,MACA,MACqC;EACrC,MAAM,WAAqB,CAAC;EAE5B,IAAI,KAAK,SAAS,KAAK,MACtB,SAAS,KAAK,MAAM;EAGrB,IAAI,KAAK,iBAAiB,KAAK,cAC9B,SAAS,KAAK,cAAc;EAG7B,OAAO;GACN,SAAS,SAAS,SAAS;GAC3B;GACA,qBAAqB;EACtB;CACD;AACD;;AAGA,IAAM,iBAAN,cAA6BC,eAAO,QAAQ,SAAS;CAGpD,YACC,MACA,MAKA,MACC;EACD,MACC,IAAI,uBAAuB,GAC3B,MACA;GAAE,GAAG;GAAM,OAAO;EAAU,GAE5B;GAAE,GAAG;GAAM,yBAAyB,CAAC,OAAO;EAAE,CAC/C;CACD;AACD;;;;;;;;;AA4BA,IAAa,SAAb,cAA4BA,eAAO,kBAAkB;CAIpD,YAAY,MAAc,MAAkB,MAAqB;EAChE,MAAM,EAAE,UAAU,GAAG,eAAe;EAEpC,MAAM,sBAAsB,MAAM,CAAC,GAAG,UAAU;EAEhD,MAAM,WAAW,IAAI,eACpB,GAAG,KAAK,YACR;GACC,OAAO,SAAS;GAChB,MAAM,KAAK;GACX,cAAc,KAAK,gBAAgB,SAAS;EAC7C,GACA,EAAE,QAAQ,KAAK,CAChB;EAEA,KAAK,KAAK,SAAS;EAEnB,KAAK,gBAAgB,EAAE,IAAI,KAAK,GAAG,CAAC;CACrC;AACD"}
1
+ {"version":3,"file":"app.cjs","names":["FlyClient","pulumi"],"sources":["../../src/fly/app.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\n\nimport { FlyClient } from \"./client\";\nimport type { FlyProvider } from \"./provider\";\n\n/** Resolved inputs for the Fly app dynamic provider. */\ninterface FlyAppInputs {\n\t/** Fly API token. */\n\ttoken: string;\n\n\t/** App name (globally unique). Used as the resource identifier. */\n\tname: string;\n\n\t/** Org slug used only when creating a new app. */\n\torganization?: string;\n}\n\n/** Persisted state for the Fly app. */\ninterface FlyAppOutputs extends FlyAppInputs {\n\t/** App identifier — equals the app name (all child paths key off the name). */\n\tappId: string;\n}\n\n/** Get-app response (only the fields we read). */\ninterface FlyAppResponse {\n\tid: string;\n\tname: string;\n}\n\n/**\n * Dynamic provider implementing adopt-or-create for Fly apps.\n *\n * `create()` does `GET /v1/apps/{name}`; if found it adopts, otherwise it\n * `POST /v1/apps`. `delete()` is a no-op — deleting a Fly app destroys\n * everything in it, so (like Railway/Neon/Vercel top-level resources) Pulumi\n * does not delete apps.\n *\n * @internal Exported only for unit testing; not part of the public API surface.\n */\nexport class FlyAppResourceProvider implements pulumi.dynamic.ResourceProvider {\n\tasync create(inputs: FlyAppInputs): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new FlyClient(inputs.token);\n\n\t\tconst existing = await client.tryGet<FlyAppResponse>(\n\t\t\t`/v1/apps/${inputs.name}`,\n\t\t);\n\n\t\tif (existing) {\n\t\t\tpulumi.log.info(`Adopting existing Fly app \"${inputs.name}\"`);\n\t\t} else {\n\t\t\tif (!inputs.organization) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`FlyApp \"${inputs.name}\": an organization is required to create a new app — set it on FlyProvider or FlyApp args`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tpulumi.log.info(`Fly app \"${inputs.name}\" not found — creating...`);\n\n\t\t\tawait client.post(\"/v1/apps\", {\n\t\t\t\tapp_name: inputs.name,\n\t\t\t\torg_slug: inputs.organization,\n\t\t\t});\n\t\t}\n\n\t\tconst outs: FlyAppOutputs = { ...inputs, appId: inputs.name };\n\n\t\treturn { id: inputs.name, outs };\n\t}\n\n\tasync read(\n\t\tid: string,\n\t\tprops: FlyAppOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new FlyClient(props.token);\n\t\tconst app = await client.tryGet<FlyAppResponse>(`/v1/apps/${id}`);\n\n\t\tif (!app) {\n\t\t\t// Resource gone → blank id lets refresh reconcile the deletion.\n\t\t\treturn {};\n\t\t}\n\n\t\treturn { id, props: { ...props, name: app.name, appId: app.name } };\n\t}\n\n\tasync update(\n\t\tid: string,\n\t\t_olds: FlyAppOutputs,\n\t\tnews: FlyAppInputs,\n\t): Promise<pulumi.dynamic.UpdateResult> {\n\t\treturn { outs: { ...news, appId: id } };\n\t}\n\n\tasync delete(): Promise<void> {\n\t\tpulumi.log.warn(\n\t\t\t\"Fly app deletion skipped — apps are not deleted by Pulumi (would destroy all contained resources)\",\n\t\t);\n\t}\n\n\tasync diff(\n\t\t_id: string,\n\t\tolds: FlyAppOutputs,\n\t\tnews: FlyAppInputs,\n\t): Promise<pulumi.dynamic.DiffResult> {\n\t\tconst replaces: string[] = [];\n\n\t\tif (olds.name !== news.name) {\n\t\t\treplaces.push(\"name\");\n\t\t}\n\n\t\tif (olds.organization !== news.organization) {\n\t\t\treplaces.push(\"organization\");\n\t\t}\n\n\t\treturn {\n\t\t\tchanges: replaces.length > 0,\n\t\t\treplaces,\n\t\t\tdeleteBeforeReplace: true,\n\t\t};\n\t}\n}\n\n/** Internal dynamic resource — not part of the public API. */\nclass FlyAppResource extends pulumi.dynamic.Resource {\n\tpublic declare readonly appId: pulumi.Output<string>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: {\n\t\t\ttoken: pulumi.Input<string>;\n\t\t\tname: pulumi.Input<string>;\n\t\t\torganization?: pulumi.Input<string | undefined>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(\n\t\t\tnew FlyAppResourceProvider(),\n\t\t\tname,\n\t\t\t{ ...args, appId: undefined },\n\t\t\t// The API token flows into dynamic-provider state with the outputs — mark it secret there.\n\t\t\t{ ...opts, additionalSecretOutputs: [\"token\"] },\n\t\t);\n\t}\n}\n\n/** Options type for FlyApp — replaces Pulumi's native `provider` field. */\ntype FlyAppOptions = Omit<pulumi.ComponentResourceOptions, \"provider\"> & {\n\t/** Fly authentication context. */\n\tprovider: FlyProvider;\n};\n\n/** Args for FlyApp. */\nexport interface FlyAppArgs {\n\t/**\n\t * App name (globally unique). Used for adoption lookup and as `.id`.\n\t * Maps to the Fly Machines API field `app_name`.\n\t */\n\tname: pulumi.Input<string>;\n\n\t/**\n\t * Org slug for app creation. Overrides `FlyProvider.organization`.\n\t * Ignored when the app already exists (adoption).\n\t * Maps to the Fly Machines API field `org_slug`.\n\t */\n\torganization?: pulumi.Input<string>;\n}\n\n/**\n * Manages a Fly app with adopt-or-create semantics.\n *\n * @example\n * ```typescript\n * const app = new FlyApp(\"api\", { name: \"rby-api\" }, { provider });\n * ```\n */\nexport class FlyApp extends pulumi.ComponentResource {\n\t/** App identifier (equals the app name). */\n\tpublic readonly id: pulumi.Output<string>;\n\n\tconstructor(name: string, args: FlyAppArgs, opts: FlyAppOptions) {\n\t\tconst { provider, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:fly:App\", name, {}, pulumiOpts);\n\n\t\tconst resource = new FlyAppResource(\n\t\t\t`${name}-resource`,\n\t\t\t{\n\t\t\t\ttoken: provider.token,\n\t\t\t\tname: args.name,\n\t\t\t\torganization: args.organization ?? provider.organization,\n\t\t\t},\n\t\t\t{ parent: this },\n\t\t);\n\n\t\tthis.id = resource.appId;\n\n\t\tthis.registerOutputs({ id: this.id });\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAuCA,IAAa,yBAAb,MAA+E;CAC9E,MAAM,OAAO,QAA4D;EACxE,MAAM,SAAS,IAAIA,6BAAU,OAAO,KAAK;EAMzC,IAAI,MAJmB,OAAO,OAC7B,YAAY,OAAO,MACpB,GAGC,eAAO,IAAI,KAAK,8BAA8B,OAAO,KAAK,EAAE;OACtD;GACN,IAAI,CAAC,OAAO,cACX,MAAM,IAAI,MACT,WAAW,OAAO,KAAK,0FACxB;GAGD,eAAO,IAAI,KAAK,YAAY,OAAO,KAAK,0BAA0B;GAElE,MAAM,OAAO,KAAK,YAAY;IAC7B,UAAU,OAAO;IACjB,UAAU,OAAO;GAClB,CAAC;EACF;EAEA,MAAM,OAAsB;GAAE,GAAG;GAAQ,OAAO,OAAO;EAAK;EAE5D,OAAO;GAAE,IAAI,OAAO;GAAM;EAAK;CAChC;CAEA,MAAM,KACL,IACA,OACqC;EAErC,MAAM,MAAM,MAAM,IADCA,6BAAU,MAAM,KACZ,EAAE,OAAuB,YAAY,IAAI;EAEhE,IAAI,CAAC,KAEJ,OAAO,CAAC;EAGT,OAAO;GAAE;GAAI,OAAO;IAAE,GAAG;IAAO,MAAM,IAAI;IAAM,OAAO,IAAI;GAAK;EAAE;CACnE;CAEA,MAAM,OACL,IACA,OACA,MACuC;EACvC,OAAO,EAAE,MAAM;GAAE,GAAG;GAAM,OAAO;EAAG,EAAE;CACvC;CAEA,MAAM,SAAwB;EAC7B,eAAO,IAAI,KACV,mGACD;CACD;CAEA,MAAM,KACL,KACA,MACA,MACqC;EACrC,MAAM,WAAqB,CAAC;EAE5B,IAAI,KAAK,SAAS,KAAK,MACtB,SAAS,KAAK,MAAM;EAGrB,IAAI,KAAK,iBAAiB,KAAK,cAC9B,SAAS,KAAK,cAAc;EAG7B,OAAO;GACN,SAAS,SAAS,SAAS;GAC3B;GACA,qBAAqB;EACtB;CACD;AACD;;AAGA,IAAM,iBAAN,cAA6BC,eAAO,QAAQ,SAAS;CAGpD,YACC,MACA,MAKA,MACC;EACD,MACC,IAAI,uBAAuB,GAC3B,MACA;GAAE,GAAG;GAAM,OAAO;EAAU,GAE5B;GAAE,GAAG;GAAM,yBAAyB,CAAC,OAAO;EAAE,CAC/C;CACD;AACD;;;;;;;;;AAgCA,IAAa,SAAb,cAA4BA,eAAO,kBAAkB;CAIpD,YAAY,MAAc,MAAkB,MAAqB;EAChE,MAAM,EAAE,UAAU,GAAG,eAAe;EAEpC,MAAM,sBAAsB,MAAM,CAAC,GAAG,UAAU;EAEhD,MAAM,WAAW,IAAI,eACpB,GAAG,KAAK,YACR;GACC,OAAO,SAAS;GAChB,MAAM,KAAK;GACX,cAAc,KAAK,gBAAgB,SAAS;EAC7C,GACA,EAAE,QAAQ,KAAK,CAChB;EAEA,KAAK,KAAK,SAAS;EAEnB,KAAK,gBAAgB,EAAE,IAAI,KAAK,GAAG,CAAC;CACrC;AACD"}
@@ -40,11 +40,15 @@ type FlyAppOptions = Omit<pulumi.ComponentResourceOptions, "provider"> & {
40
40
  };
41
41
  /** Args for FlyApp. */
42
42
  interface FlyAppArgs {
43
- /** App name (globally unique). Used for adoption lookup and as `.id`. */
43
+ /**
44
+ * App name (globally unique). Used for adoption lookup and as `.id`.
45
+ * Maps to the Fly Machines API field `app_name`.
46
+ */
44
47
  name: pulumi.Input<string>;
45
48
  /**
46
49
  * Org slug for app creation. Overrides `FlyProvider.organization`.
47
50
  * Ignored when the app already exists (adoption).
51
+ * Maps to the Fly Machines API field `org_slug`.
48
52
  */
49
53
  organization?: pulumi.Input<string>;
50
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.cts","names":[],"sources":["../../src/fly/app.ts"],"mappings":";;;;;;UAMU,YAAA;;EAET,KAAA;EAFqB;EAKrB,IAAA;EALqB;EAQrB,YAAA;AAAA;;UAIS,aAAA,SAAsB,YAAY;EAJ/B;EAMZ,KAAK;AAAA;;;AAAA;AAmBN;;;;;;;cAAa,sBAAA,YAAkC,MAAA,CAAO,OAAA,CAAQ,gBAAA;EACvD,MAAA,CAAO,MAAA,EAAQ,YAAA,GAAe,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,YAAA;EA6BrD,IAAA,CACL,EAAA,UACA,KAAA,EAAO,aAAA,GACL,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,UAAA;EAYpB,MAAA,CACL,EAAA,UACA,KAAA,EAAO,aAAA,EACP,IAAA,EAAM,YAAA,GACJ,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,YAAA;EAIpB,MAAA,CAAA,GAAU,OAAA;EAMV,IAAA,CACL,GAAA,UACA,IAAA,EAAM,aAAA,EACN,IAAA,EAAM,YAAA,GACJ,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,UAAA;AAAA;;KA2CtB,aAAA,GAAgB,IAAA,CAAK,MAAA,CAAO,wBAAA;EA3CrB,kCA6CX,QAAA,EAAU,WAAA;AAAA;;UAIM,UAAA;EAhH8B;EAkH9C,IAAA,EAAM,MAAA,CAAO,KAAA;EAlHgD;;;;EAwH7D,YAAA,GAAe,MAAA,CAAO,KAAK;AAAA;;;;;;;;;cAWf,MAAA,SAAe,MAAA,CAAO,iBAAA;EAlGR;EAAA,SAoGV,EAAA,EAAI,MAAA,CAAO,MAAA;cAEf,IAAA,UAAc,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM,aAAA;AAAA"}
1
+ {"version":3,"file":"app.d.cts","names":[],"sources":["../../src/fly/app.ts"],"mappings":";;;;;;UAMU,YAAA;;EAET,KAAA;EAFqB;EAKrB,IAAA;EALqB;EAQrB,YAAA;AAAA;;UAIS,aAAA,SAAsB,YAAY;EAJ/B;EAMZ,KAAK;AAAA;;;AAAA;AAmBN;;;;;;;cAAa,sBAAA,YAAkC,MAAA,CAAO,OAAA,CAAQ,gBAAA;EACvD,MAAA,CAAO,MAAA,EAAQ,YAAA,GAAe,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,YAAA;EA6BrD,IAAA,CACL,EAAA,UACA,KAAA,EAAO,aAAA,GACL,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,UAAA;EAYpB,MAAA,CACL,EAAA,UACA,KAAA,EAAO,aAAA,EACP,IAAA,EAAM,YAAA,GACJ,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,YAAA;EAIpB,MAAA,CAAA,GAAU,OAAA;EAMV,IAAA,CACL,GAAA,UACA,IAAA,EAAM,aAAA,EACN,IAAA,EAAM,YAAA,GACJ,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,UAAA;AAAA;;KA2CtB,aAAA,GAAgB,IAAA,CAAK,MAAA,CAAO,wBAAA;EA3CrB,kCA6CX,QAAA,EAAU,WAAA;AAAA;;UAIM,UAAA;EAhH8B;;;;EAqH9C,IAAA,EAAM,MAAA,CAAO,KAAA;EApHA;;;;;EA2Hb,YAAA,GAAe,MAAA,CAAO,KAAK;AAAA;;;;;;;;;cAWf,MAAA,SAAe,MAAA,CAAO,iBAAA;EAxFjC;EAAA,SA0Fe,EAAA,EAAI,MAAA,CAAO,MAAA;cAEf,IAAA,UAAc,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM,aAAA;AAAA"}
@@ -40,11 +40,15 @@ type FlyAppOptions = Omit<pulumi.ComponentResourceOptions, "provider"> & {
40
40
  };
41
41
  /** Args for FlyApp. */
42
42
  interface FlyAppArgs {
43
- /** App name (globally unique). Used for adoption lookup and as `.id`. */
43
+ /**
44
+ * App name (globally unique). Used for adoption lookup and as `.id`.
45
+ * Maps to the Fly Machines API field `app_name`.
46
+ */
44
47
  name: pulumi.Input<string>;
45
48
  /**
46
49
  * Org slug for app creation. Overrides `FlyProvider.organization`.
47
50
  * Ignored when the app already exists (adoption).
51
+ * Maps to the Fly Machines API field `org_slug`.
48
52
  */
49
53
  organization?: pulumi.Input<string>;
50
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.mts","names":[],"sources":["../../src/fly/app.ts"],"mappings":";;;;;;UAMU,YAAA;;EAET,KAAA;EAFqB;EAKrB,IAAA;EALqB;EAQrB,YAAA;AAAA;;UAIS,aAAA,SAAsB,YAAY;EAJ/B;EAMZ,KAAK;AAAA;;;AAAA;AAmBN;;;;;;;cAAa,sBAAA,YAAkC,MAAA,CAAO,OAAA,CAAQ,gBAAA;EACvD,MAAA,CAAO,MAAA,EAAQ,YAAA,GAAe,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,YAAA;EA6BrD,IAAA,CACL,EAAA,UACA,KAAA,EAAO,aAAA,GACL,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,UAAA;EAYpB,MAAA,CACL,EAAA,UACA,KAAA,EAAO,aAAA,EACP,IAAA,EAAM,YAAA,GACJ,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,YAAA;EAIpB,MAAA,CAAA,GAAU,OAAA;EAMV,IAAA,CACL,GAAA,UACA,IAAA,EAAM,aAAA,EACN,IAAA,EAAM,YAAA,GACJ,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,UAAA;AAAA;;KA2CtB,aAAA,GAAgB,IAAA,CAAK,MAAA,CAAO,wBAAA;EA3CrB,kCA6CX,QAAA,EAAU,WAAA;AAAA;;UAIM,UAAA;EAhH8B;EAkH9C,IAAA,EAAM,MAAA,CAAO,KAAA;EAlHgD;;;;EAwH7D,YAAA,GAAe,MAAA,CAAO,KAAK;AAAA;;;;;;;;;cAWf,MAAA,SAAe,MAAA,CAAO,iBAAA;EAlGR;EAAA,SAoGV,EAAA,EAAI,MAAA,CAAO,MAAA;cAEf,IAAA,UAAc,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM,aAAA;AAAA"}
1
+ {"version":3,"file":"app.d.mts","names":[],"sources":["../../src/fly/app.ts"],"mappings":";;;;;;UAMU,YAAA;;EAET,KAAA;EAFqB;EAKrB,IAAA;EALqB;EAQrB,YAAA;AAAA;;UAIS,aAAA,SAAsB,YAAY;EAJ/B;EAMZ,KAAK;AAAA;;;AAAA;AAmBN;;;;;;;cAAa,sBAAA,YAAkC,MAAA,CAAO,OAAA,CAAQ,gBAAA;EACvD,MAAA,CAAO,MAAA,EAAQ,YAAA,GAAe,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,YAAA;EA6BrD,IAAA,CACL,EAAA,UACA,KAAA,EAAO,aAAA,GACL,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,UAAA;EAYpB,MAAA,CACL,EAAA,UACA,KAAA,EAAO,aAAA,EACP,IAAA,EAAM,YAAA,GACJ,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,YAAA;EAIpB,MAAA,CAAA,GAAU,OAAA;EAMV,IAAA,CACL,GAAA,UACA,IAAA,EAAM,aAAA,EACN,IAAA,EAAM,YAAA,GACJ,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,UAAA;AAAA;;KA2CtB,aAAA,GAAgB,IAAA,CAAK,MAAA,CAAO,wBAAA;EA3CrB,kCA6CX,QAAA,EAAU,WAAA;AAAA;;UAIM,UAAA;EAhH8B;;;;EAqH9C,IAAA,EAAM,MAAA,CAAO,KAAA;EApHA;;;;;EA2Hb,YAAA,GAAe,MAAA,CAAO,KAAK;AAAA;;;;;;;;;cAWf,MAAA,SAAe,MAAA,CAAO,iBAAA;EAxFjC;EAAA,SA0Fe,EAAA,EAAI,MAAA,CAAO,MAAA;cAEf,IAAA,UAAc,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM,aAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"app.mjs","names":[],"sources":["../../src/fly/app.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\n\nimport { FlyClient } from \"./client\";\nimport type { FlyProvider } from \"./provider\";\n\n/** Resolved inputs for the Fly app dynamic provider. */\ninterface FlyAppInputs {\n\t/** Fly API token. */\n\ttoken: string;\n\n\t/** App name (globally unique). Used as the resource identifier. */\n\tname: string;\n\n\t/** Org slug used only when creating a new app. */\n\torganization?: string;\n}\n\n/** Persisted state for the Fly app. */\ninterface FlyAppOutputs extends FlyAppInputs {\n\t/** App identifier — equals the app name (all child paths key off the name). */\n\tappId: string;\n}\n\n/** Get-app response (only the fields we read). */\ninterface FlyAppResponse {\n\tid: string;\n\tname: string;\n}\n\n/**\n * Dynamic provider implementing adopt-or-create for Fly apps.\n *\n * `create()` does `GET /v1/apps/{name}`; if found it adopts, otherwise it\n * `POST /v1/apps`. `delete()` is a no-op — deleting a Fly app destroys\n * everything in it, so (like Railway/Neon/Vercel top-level resources) Pulumi\n * does not delete apps.\n *\n * @internal Exported only for unit testing; not part of the public API surface.\n */\nexport class FlyAppResourceProvider implements pulumi.dynamic.ResourceProvider {\n\tasync create(inputs: FlyAppInputs): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new FlyClient(inputs.token);\n\n\t\tconst existing = await client.tryGet<FlyAppResponse>(\n\t\t\t`/v1/apps/${inputs.name}`,\n\t\t);\n\n\t\tif (existing) {\n\t\t\tpulumi.log.info(`Adopting existing Fly app \"${inputs.name}\"`);\n\t\t} else {\n\t\t\tif (!inputs.organization) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`FlyApp \"${inputs.name}\": an organization is required to create a new app — set it on FlyProvider or FlyApp args`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tpulumi.log.info(`Fly app \"${inputs.name}\" not found — creating...`);\n\n\t\t\tawait client.post(\"/v1/apps\", {\n\t\t\t\tapp_name: inputs.name,\n\t\t\t\torg_slug: inputs.organization,\n\t\t\t});\n\t\t}\n\n\t\tconst outs: FlyAppOutputs = { ...inputs, appId: inputs.name };\n\n\t\treturn { id: inputs.name, outs };\n\t}\n\n\tasync read(\n\t\tid: string,\n\t\tprops: FlyAppOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new FlyClient(props.token);\n\t\tconst app = await client.tryGet<FlyAppResponse>(`/v1/apps/${id}`);\n\n\t\tif (!app) {\n\t\t\t// Resource gone → blank id lets refresh reconcile the deletion.\n\t\t\treturn {};\n\t\t}\n\n\t\treturn { id, props: { ...props, name: app.name, appId: app.name } };\n\t}\n\n\tasync update(\n\t\tid: string,\n\t\t_olds: FlyAppOutputs,\n\t\tnews: FlyAppInputs,\n\t): Promise<pulumi.dynamic.UpdateResult> {\n\t\treturn { outs: { ...news, appId: id } };\n\t}\n\n\tasync delete(): Promise<void> {\n\t\tpulumi.log.warn(\n\t\t\t\"Fly app deletion skipped — apps are not deleted by Pulumi (would destroy all contained resources)\",\n\t\t);\n\t}\n\n\tasync diff(\n\t\t_id: string,\n\t\tolds: FlyAppOutputs,\n\t\tnews: FlyAppInputs,\n\t): Promise<pulumi.dynamic.DiffResult> {\n\t\tconst replaces: string[] = [];\n\n\t\tif (olds.name !== news.name) {\n\t\t\treplaces.push(\"name\");\n\t\t}\n\n\t\tif (olds.organization !== news.organization) {\n\t\t\treplaces.push(\"organization\");\n\t\t}\n\n\t\treturn {\n\t\t\tchanges: replaces.length > 0,\n\t\t\treplaces,\n\t\t\tdeleteBeforeReplace: true,\n\t\t};\n\t}\n}\n\n/** Internal dynamic resource — not part of the public API. */\nclass FlyAppResource extends pulumi.dynamic.Resource {\n\tpublic declare readonly appId: pulumi.Output<string>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: {\n\t\t\ttoken: pulumi.Input<string>;\n\t\t\tname: pulumi.Input<string>;\n\t\t\torganization?: pulumi.Input<string | undefined>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(\n\t\t\tnew FlyAppResourceProvider(),\n\t\t\tname,\n\t\t\t{ ...args, appId: undefined },\n\t\t\t// The API token flows into dynamic-provider state with the outputs — mark it secret there.\n\t\t\t{ ...opts, additionalSecretOutputs: [\"token\"] },\n\t\t);\n\t}\n}\n\n/** Options type for FlyApp — replaces Pulumi's native `provider` field. */\ntype FlyAppOptions = Omit<pulumi.ComponentResourceOptions, \"provider\"> & {\n\t/** Fly authentication context. */\n\tprovider: FlyProvider;\n};\n\n/** Args for FlyApp. */\nexport interface FlyAppArgs {\n\t/** App name (globally unique). Used for adoption lookup and as `.id`. */\n\tname: pulumi.Input<string>;\n\n\t/**\n\t * Org slug for app creation. Overrides `FlyProvider.organization`.\n\t * Ignored when the app already exists (adoption).\n\t */\n\torganization?: pulumi.Input<string>;\n}\n\n/**\n * Manages a Fly app with adopt-or-create semantics.\n *\n * @example\n * ```typescript\n * const app = new FlyApp(\"api\", { name: \"rby-api\" }, { provider });\n * ```\n */\nexport class FlyApp extends pulumi.ComponentResource {\n\t/** App identifier (equals the app name). */\n\tpublic readonly id: pulumi.Output<string>;\n\n\tconstructor(name: string, args: FlyAppArgs, opts: FlyAppOptions) {\n\t\tconst { provider, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:fly:App\", name, {}, pulumiOpts);\n\n\t\tconst resource = new FlyAppResource(\n\t\t\t`${name}-resource`,\n\t\t\t{\n\t\t\t\ttoken: provider.token,\n\t\t\t\tname: args.name,\n\t\t\t\torganization: args.organization ?? provider.organization,\n\t\t\t},\n\t\t\t{ parent: this },\n\t\t);\n\n\t\tthis.id = resource.appId;\n\n\t\tthis.registerOutputs({ id: this.id });\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;AAuCA,IAAa,yBAAb,MAA+E;CAC9E,MAAM,OAAO,QAA4D;EACxE,MAAM,SAAS,IAAI,UAAU,OAAO,KAAK;EAMzC,IAAI,MAJmB,OAAO,OAC7B,YAAY,OAAO,MACpB,GAGC,OAAO,IAAI,KAAK,8BAA8B,OAAO,KAAK,EAAE;OACtD;GACN,IAAI,CAAC,OAAO,cACX,MAAM,IAAI,MACT,WAAW,OAAO,KAAK,0FACxB;GAGD,OAAO,IAAI,KAAK,YAAY,OAAO,KAAK,0BAA0B;GAElE,MAAM,OAAO,KAAK,YAAY;IAC7B,UAAU,OAAO;IACjB,UAAU,OAAO;GAClB,CAAC;EACF;EAEA,MAAM,OAAsB;GAAE,GAAG;GAAQ,OAAO,OAAO;EAAK;EAE5D,OAAO;GAAE,IAAI,OAAO;GAAM;EAAK;CAChC;CAEA,MAAM,KACL,IACA,OACqC;EAErC,MAAM,MAAM,MAAM,IADC,UAAU,MAAM,KACZ,EAAE,OAAuB,YAAY,IAAI;EAEhE,IAAI,CAAC,KAEJ,OAAO,CAAC;EAGT,OAAO;GAAE;GAAI,OAAO;IAAE,GAAG;IAAO,MAAM,IAAI;IAAM,OAAO,IAAI;GAAK;EAAE;CACnE;CAEA,MAAM,OACL,IACA,OACA,MACuC;EACvC,OAAO,EAAE,MAAM;GAAE,GAAG;GAAM,OAAO;EAAG,EAAE;CACvC;CAEA,MAAM,SAAwB;EAC7B,OAAO,IAAI,KACV,mGACD;CACD;CAEA,MAAM,KACL,KACA,MACA,MACqC;EACrC,MAAM,WAAqB,CAAC;EAE5B,IAAI,KAAK,SAAS,KAAK,MACtB,SAAS,KAAK,MAAM;EAGrB,IAAI,KAAK,iBAAiB,KAAK,cAC9B,SAAS,KAAK,cAAc;EAG7B,OAAO;GACN,SAAS,SAAS,SAAS;GAC3B;GACA,qBAAqB;EACtB;CACD;AACD;;AAGA,IAAM,iBAAN,cAA6B,OAAO,QAAQ,SAAS;CAGpD,YACC,MACA,MAKA,MACC;EACD,MACC,IAAI,uBAAuB,GAC3B,MACA;GAAE,GAAG;GAAM,OAAO;EAAU,GAE5B;GAAE,GAAG;GAAM,yBAAyB,CAAC,OAAO;EAAE,CAC/C;CACD;AACD;;;;;;;;;AA4BA,IAAa,SAAb,cAA4B,OAAO,kBAAkB;CAIpD,YAAY,MAAc,MAAkB,MAAqB;EAChE,MAAM,EAAE,UAAU,GAAG,eAAe;EAEpC,MAAM,sBAAsB,MAAM,CAAC,GAAG,UAAU;EAEhD,MAAM,WAAW,IAAI,eACpB,GAAG,KAAK,YACR;GACC,OAAO,SAAS;GAChB,MAAM,KAAK;GACX,cAAc,KAAK,gBAAgB,SAAS;EAC7C,GACA,EAAE,QAAQ,KAAK,CAChB;EAEA,KAAK,KAAK,SAAS;EAEnB,KAAK,gBAAgB,EAAE,IAAI,KAAK,GAAG,CAAC;CACrC;AACD"}
1
+ {"version":3,"file":"app.mjs","names":[],"sources":["../../src/fly/app.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\n\nimport { FlyClient } from \"./client\";\nimport type { FlyProvider } from \"./provider\";\n\n/** Resolved inputs for the Fly app dynamic provider. */\ninterface FlyAppInputs {\n\t/** Fly API token. */\n\ttoken: string;\n\n\t/** App name (globally unique). Used as the resource identifier. */\n\tname: string;\n\n\t/** Org slug used only when creating a new app. */\n\torganization?: string;\n}\n\n/** Persisted state for the Fly app. */\ninterface FlyAppOutputs extends FlyAppInputs {\n\t/** App identifier — equals the app name (all child paths key off the name). */\n\tappId: string;\n}\n\n/** Get-app response (only the fields we read). */\ninterface FlyAppResponse {\n\tid: string;\n\tname: string;\n}\n\n/**\n * Dynamic provider implementing adopt-or-create for Fly apps.\n *\n * `create()` does `GET /v1/apps/{name}`; if found it adopts, otherwise it\n * `POST /v1/apps`. `delete()` is a no-op — deleting a Fly app destroys\n * everything in it, so (like Railway/Neon/Vercel top-level resources) Pulumi\n * does not delete apps.\n *\n * @internal Exported only for unit testing; not part of the public API surface.\n */\nexport class FlyAppResourceProvider implements pulumi.dynamic.ResourceProvider {\n\tasync create(inputs: FlyAppInputs): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new FlyClient(inputs.token);\n\n\t\tconst existing = await client.tryGet<FlyAppResponse>(\n\t\t\t`/v1/apps/${inputs.name}`,\n\t\t);\n\n\t\tif (existing) {\n\t\t\tpulumi.log.info(`Adopting existing Fly app \"${inputs.name}\"`);\n\t\t} else {\n\t\t\tif (!inputs.organization) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`FlyApp \"${inputs.name}\": an organization is required to create a new app — set it on FlyProvider or FlyApp args`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tpulumi.log.info(`Fly app \"${inputs.name}\" not found — creating...`);\n\n\t\t\tawait client.post(\"/v1/apps\", {\n\t\t\t\tapp_name: inputs.name,\n\t\t\t\torg_slug: inputs.organization,\n\t\t\t});\n\t\t}\n\n\t\tconst outs: FlyAppOutputs = { ...inputs, appId: inputs.name };\n\n\t\treturn { id: inputs.name, outs };\n\t}\n\n\tasync read(\n\t\tid: string,\n\t\tprops: FlyAppOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new FlyClient(props.token);\n\t\tconst app = await client.tryGet<FlyAppResponse>(`/v1/apps/${id}`);\n\n\t\tif (!app) {\n\t\t\t// Resource gone → blank id lets refresh reconcile the deletion.\n\t\t\treturn {};\n\t\t}\n\n\t\treturn { id, props: { ...props, name: app.name, appId: app.name } };\n\t}\n\n\tasync update(\n\t\tid: string,\n\t\t_olds: FlyAppOutputs,\n\t\tnews: FlyAppInputs,\n\t): Promise<pulumi.dynamic.UpdateResult> {\n\t\treturn { outs: { ...news, appId: id } };\n\t}\n\n\tasync delete(): Promise<void> {\n\t\tpulumi.log.warn(\n\t\t\t\"Fly app deletion skipped — apps are not deleted by Pulumi (would destroy all contained resources)\",\n\t\t);\n\t}\n\n\tasync diff(\n\t\t_id: string,\n\t\tolds: FlyAppOutputs,\n\t\tnews: FlyAppInputs,\n\t): Promise<pulumi.dynamic.DiffResult> {\n\t\tconst replaces: string[] = [];\n\n\t\tif (olds.name !== news.name) {\n\t\t\treplaces.push(\"name\");\n\t\t}\n\n\t\tif (olds.organization !== news.organization) {\n\t\t\treplaces.push(\"organization\");\n\t\t}\n\n\t\treturn {\n\t\t\tchanges: replaces.length > 0,\n\t\t\treplaces,\n\t\t\tdeleteBeforeReplace: true,\n\t\t};\n\t}\n}\n\n/** Internal dynamic resource — not part of the public API. */\nclass FlyAppResource extends pulumi.dynamic.Resource {\n\tpublic declare readonly appId: pulumi.Output<string>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: {\n\t\t\ttoken: pulumi.Input<string>;\n\t\t\tname: pulumi.Input<string>;\n\t\t\torganization?: pulumi.Input<string | undefined>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(\n\t\t\tnew FlyAppResourceProvider(),\n\t\t\tname,\n\t\t\t{ ...args, appId: undefined },\n\t\t\t// The API token flows into dynamic-provider state with the outputs — mark it secret there.\n\t\t\t{ ...opts, additionalSecretOutputs: [\"token\"] },\n\t\t);\n\t}\n}\n\n/** Options type for FlyApp — replaces Pulumi's native `provider` field. */\ntype FlyAppOptions = Omit<pulumi.ComponentResourceOptions, \"provider\"> & {\n\t/** Fly authentication context. */\n\tprovider: FlyProvider;\n};\n\n/** Args for FlyApp. */\nexport interface FlyAppArgs {\n\t/**\n\t * App name (globally unique). Used for adoption lookup and as `.id`.\n\t * Maps to the Fly Machines API field `app_name`.\n\t */\n\tname: pulumi.Input<string>;\n\n\t/**\n\t * Org slug for app creation. Overrides `FlyProvider.organization`.\n\t * Ignored when the app already exists (adoption).\n\t * Maps to the Fly Machines API field `org_slug`.\n\t */\n\torganization?: pulumi.Input<string>;\n}\n\n/**\n * Manages a Fly app with adopt-or-create semantics.\n *\n * @example\n * ```typescript\n * const app = new FlyApp(\"api\", { name: \"rby-api\" }, { provider });\n * ```\n */\nexport class FlyApp extends pulumi.ComponentResource {\n\t/** App identifier (equals the app name). */\n\tpublic readonly id: pulumi.Output<string>;\n\n\tconstructor(name: string, args: FlyAppArgs, opts: FlyAppOptions) {\n\t\tconst { provider, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:fly:App\", name, {}, pulumiOpts);\n\n\t\tconst resource = new FlyAppResource(\n\t\t\t`${name}-resource`,\n\t\t\t{\n\t\t\t\ttoken: provider.token,\n\t\t\t\tname: args.name,\n\t\t\t\torganization: args.organization ?? provider.organization,\n\t\t\t},\n\t\t\t{ parent: this },\n\t\t);\n\n\t\tthis.id = resource.appId;\n\n\t\tthis.registerOutputs({ id: this.id });\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;AAuCA,IAAa,yBAAb,MAA+E;CAC9E,MAAM,OAAO,QAA4D;EACxE,MAAM,SAAS,IAAI,UAAU,OAAO,KAAK;EAMzC,IAAI,MAJmB,OAAO,OAC7B,YAAY,OAAO,MACpB,GAGC,OAAO,IAAI,KAAK,8BAA8B,OAAO,KAAK,EAAE;OACtD;GACN,IAAI,CAAC,OAAO,cACX,MAAM,IAAI,MACT,WAAW,OAAO,KAAK,0FACxB;GAGD,OAAO,IAAI,KAAK,YAAY,OAAO,KAAK,0BAA0B;GAElE,MAAM,OAAO,KAAK,YAAY;IAC7B,UAAU,OAAO;IACjB,UAAU,OAAO;GAClB,CAAC;EACF;EAEA,MAAM,OAAsB;GAAE,GAAG;GAAQ,OAAO,OAAO;EAAK;EAE5D,OAAO;GAAE,IAAI,OAAO;GAAM;EAAK;CAChC;CAEA,MAAM,KACL,IACA,OACqC;EAErC,MAAM,MAAM,MAAM,IADC,UAAU,MAAM,KACZ,EAAE,OAAuB,YAAY,IAAI;EAEhE,IAAI,CAAC,KAEJ,OAAO,CAAC;EAGT,OAAO;GAAE;GAAI,OAAO;IAAE,GAAG;IAAO,MAAM,IAAI;IAAM,OAAO,IAAI;GAAK;EAAE;CACnE;CAEA,MAAM,OACL,IACA,OACA,MACuC;EACvC,OAAO,EAAE,MAAM;GAAE,GAAG;GAAM,OAAO;EAAG,EAAE;CACvC;CAEA,MAAM,SAAwB;EAC7B,OAAO,IAAI,KACV,mGACD;CACD;CAEA,MAAM,KACL,KACA,MACA,MACqC;EACrC,MAAM,WAAqB,CAAC;EAE5B,IAAI,KAAK,SAAS,KAAK,MACtB,SAAS,KAAK,MAAM;EAGrB,IAAI,KAAK,iBAAiB,KAAK,cAC9B,SAAS,KAAK,cAAc;EAG7B,OAAO;GACN,SAAS,SAAS,SAAS;GAC3B;GACA,qBAAqB;EACtB;CACD;AACD;;AAGA,IAAM,iBAAN,cAA6B,OAAO,QAAQ,SAAS;CAGpD,YACC,MACA,MAKA,MACC;EACD,MACC,IAAI,uBAAuB,GAC3B,MACA;GAAE,GAAG;GAAM,OAAO;EAAU,GAE5B;GAAE,GAAG;GAAM,yBAAyB,CAAC,OAAO;EAAE,CAC/C;CACD;AACD;;;;;;;;;AAgCA,IAAa,SAAb,cAA4B,OAAO,kBAAkB;CAIpD,YAAY,MAAc,MAAkB,MAAqB;EAChE,MAAM,EAAE,UAAU,GAAG,eAAe;EAEpC,MAAM,sBAAsB,MAAM,CAAC,GAAG,UAAU;EAEhD,MAAM,WAAW,IAAI,eACpB,GAAG,KAAK,YACR;GACC,OAAO,SAAS;GAChB,MAAM,KAAK;GACX,cAAc,KAAK,gBAAgB,SAAS;EAC7C,GACA,EAAE,QAAQ,KAAK,CAChB;EAEA,KAAK,KAAK,SAAS;EAEnB,KAAK,gBAAgB,EAAE,IAAI,KAAK,GAAG,CAAC;CACrC;AACD"}
@@ -11,6 +11,8 @@ _pulumi_pulumi = require_chunk.__toESM(_pulumi_pulumi, 1);
11
11
  * for an existing cert by hostname and adopts it, otherwise it requests one via
12
12
  * `POST /v1/apps/{app}/certificates/acme`. The Machines API returns no `id` —
13
13
  * the hostname is the resource key.
14
+ *
15
+ * @internal Exported only for unit testing; not part of the public API surface.
14
16
  */
15
17
  var FlyCertificateResourceProvider = class {
16
18
  async create(inputs) {
@@ -119,4 +121,5 @@ var FlyCertificate = class extends _pulumi_pulumi.ComponentResource {
119
121
 
120
122
  //#endregion
121
123
  exports.FlyCertificate = FlyCertificate;
124
+ exports.FlyCertificateResourceProvider = FlyCertificateResourceProvider;
122
125
  //# sourceMappingURL=certificate.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"certificate.cjs","names":["FlyClient","ApiNotFoundError","pulumi"],"sources":["../../src/fly/certificate.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\n\nimport { ApiNotFoundError } from \"../errors/api-not-found-error\";\nimport type { FlyApp } from \"./app\";\nimport { FlyClient } from \"./client\";\nimport type { FlyProvider } from \"./provider\";\n\n/** DNS records the consumer must create for certificate validation. */\nexport interface FlyDnsRequirements {\n\t/** ACME challenge CNAME record. */\n\tacme_challenge?: { name: string; target: string };\n\n\t/** `_fly-ownership` TXT record. */\n\townership?: { name: string; app_value: string };\n\n\t/** CNAME target for the hostname itself. */\n\tcname?: string;\n}\n\n/** Resolved inputs for the Fly certificate dynamic provider. */\ninterface FlyCertificateInputs {\n\t/** Fly API token. */\n\ttoken: string;\n\n\t/** App name the certificate belongs to. */\n\tappName: string;\n\n\t/** Hostname to issue an ACME certificate for. Used as the resource key. */\n\thostname: string;\n}\n\n/** Persisted state for the Fly certificate. */\ninterface FlyCertificateOutputs extends FlyCertificateInputs {\n\t/** Whether the certificate is fully provisioned (DNS correct). */\n\tconfigured: boolean;\n\n\t/** DNS records required for validation. */\n\tdnsRequirements: FlyDnsRequirements;\n}\n\n/** Certificate response (only the fields we read). */\ninterface FlyCertificateResponse {\n\thostname: string;\n\tconfigured: boolean;\n\tdns_requirements?: FlyDnsRequirements;\n}\n\n/**\n * Dynamic provider for Fly ACME (Let's Encrypt) certificates. `create()` checks\n * for an existing cert by hostname and adopts it, otherwise it requests one via\n * `POST /v1/apps/{app}/certificates/acme`. The Machines API returns no `id` —\n * the hostname is the resource key.\n */\nclass FlyCertificateResourceProvider\n\timplements pulumi.dynamic.ResourceProvider\n{\n\tasync create(\n\t\tinputs: FlyCertificateInputs,\n\t): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new FlyClient(inputs.token);\n\t\tconst path = `/v1/apps/${inputs.appName}/certificates/${encodeURIComponent(inputs.hostname)}`;\n\n\t\tlet cert = await client.tryGet<FlyCertificateResponse>(path);\n\n\t\tif (cert) {\n\t\t\tpulumi.log.info(`Adopting existing Fly certificate \"${inputs.hostname}\"`);\n\t\t} else {\n\t\t\tcert = await client.post<FlyCertificateResponse>(\n\t\t\t\t`/v1/apps/${inputs.appName}/certificates/acme`,\n\t\t\t\t{ hostname: inputs.hostname },\n\t\t\t);\n\t\t}\n\n\t\tconst outs: FlyCertificateOutputs = {\n\t\t\t...inputs,\n\t\t\tconfigured: cert.configured ?? false,\n\t\t\tdnsRequirements: cert.dns_requirements ?? {},\n\t\t};\n\n\t\treturn { id: inputs.hostname, outs };\n\t}\n\n\tasync read(\n\t\tid: string,\n\t\tprops: FlyCertificateOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new FlyClient(props.token);\n\n\t\tconst cert = await client.tryGet<FlyCertificateResponse>(\n\t\t\t`/v1/apps/${props.appName}/certificates/${encodeURIComponent(id)}`,\n\t\t);\n\n\t\tif (!cert) {\n\t\t\t// Resource gone → blank id lets refresh reconcile the deletion.\n\t\t\treturn {};\n\t\t}\n\n\t\treturn {\n\t\t\tid,\n\t\t\tprops: {\n\t\t\t\t...props,\n\t\t\t\tconfigured: cert.configured ?? false,\n\t\t\t\tdnsRequirements: cert.dns_requirements ?? {},\n\t\t\t},\n\t\t};\n\t}\n\n\tasync update(\n\t\t_id: string,\n\t\t_olds: FlyCertificateOutputs,\n\t\tnews: FlyCertificateInputs,\n\t): Promise<pulumi.dynamic.UpdateResult> {\n\t\t// Hostname/app changes force replacement (see diff); nothing else is updatable.\n\t\treturn {\n\t\t\touts: { ...news, configured: false, dnsRequirements: {} },\n\t\t};\n\t}\n\n\tasync delete(id: string, props: FlyCertificateOutputs): Promise<void> {\n\t\tconst client = new FlyClient(props.token);\n\n\t\ttry {\n\t\t\tawait client.delete(\n\t\t\t\t`/v1/apps/${props.appName}/certificates/${encodeURIComponent(id)}`,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\t// Already gone — deletion is idempotent.\n\t\t\tif (error instanceof ApiNotFoundError) {\n\t\t\t\tpulumi.log.warn(`Fly certificate \"${id}\" already deleted`);\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync diff(\n\t\t_id: string,\n\t\tolds: FlyCertificateOutputs,\n\t\tnews: FlyCertificateInputs,\n\t): Promise<pulumi.dynamic.DiffResult> {\n\t\tconst replaces: string[] = [];\n\n\t\tif (olds.appName !== news.appName) {\n\t\t\treplaces.push(\"appName\");\n\t\t}\n\n\t\tif (olds.hostname !== news.hostname) {\n\t\t\treplaces.push(\"hostname\");\n\t\t}\n\n\t\treturn {\n\t\t\tchanges: replaces.length > 0,\n\t\t\treplaces,\n\t\t\tdeleteBeforeReplace: true,\n\t\t};\n\t}\n}\n\n/** Internal dynamic resource — not part of the public API. */\nclass FlyCertificateResource extends pulumi.dynamic.Resource {\n\tpublic declare readonly configured: pulumi.Output<boolean>;\n\tpublic declare readonly dnsRequirements: pulumi.Output<FlyDnsRequirements>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: {\n\t\t\ttoken: pulumi.Input<string>;\n\t\t\tappName: pulumi.Input<string>;\n\t\t\thostname: pulumi.Input<string>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(\n\t\t\tnew FlyCertificateResourceProvider(),\n\t\t\tname,\n\t\t\t{ ...args, configured: undefined, dnsRequirements: undefined },\n\t\t\t// The API token flows into dynamic-provider state with the outputs — mark it secret there.\n\t\t\t{ ...opts, additionalSecretOutputs: [\"token\"] },\n\t\t);\n\t}\n}\n\n/** Options type for FlyCertificate. */\ntype FlyCertificateOptions = Omit<\n\tpulumi.ComponentResourceOptions,\n\t\"provider\"\n> & {\n\t/** Fly authentication context. */\n\tprovider: FlyProvider;\n\n\t/** App the certificate belongs to. */\n\tapp: FlyApp;\n};\n\n/** Args for FlyCertificate. */\nexport interface FlyCertificateArgs {\n\t/** Hostname to issue an ACME certificate for (e.g. `\"api.example.com\"`). */\n\thostname: pulumi.Input<string>;\n}\n\n/**\n * Manages a Fly ACME certificate for a custom hostname.\n *\n * Exposes `.configured` and `.dnsRequirements` so the consumer can wire up the\n * required DNS records.\n *\n * @example\n * ```typescript\n * const cert = new FlyCertificate(\"api-cert\", {\n * hostname: \"api.example.com\",\n * }, { provider, app });\n * ```\n */\nexport class FlyCertificate extends pulumi.ComponentResource {\n\t/** Certificate identifier (equals the hostname). */\n\tpublic readonly id: pulumi.Output<string>;\n\n\t/** Whether the certificate is fully provisioned. */\n\tpublic readonly configured: pulumi.Output<boolean>;\n\n\t/** DNS records required for validation. */\n\tpublic readonly dnsRequirements: pulumi.Output<FlyDnsRequirements>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: FlyCertificateArgs,\n\t\topts: FlyCertificateOptions,\n\t) {\n\t\tconst { provider, app, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:fly:Certificate\", name, {}, pulumiOpts);\n\n\t\tconst resource = new FlyCertificateResource(\n\t\t\t`${name}-resource`,\n\t\t\t{\n\t\t\t\ttoken: provider.token,\n\t\t\t\tappName: app.id,\n\t\t\t\thostname: args.hostname,\n\t\t\t},\n\t\t\t{ parent: this },\n\t\t);\n\n\t\tthis.id = pulumi.output(args.hostname);\n\t\tthis.configured = resource.configured;\n\t\tthis.dnsRequirements = resource.dnsRequirements;\n\n\t\tthis.registerOutputs({\n\t\t\tid: this.id,\n\t\t\tconfigured: this.configured,\n\t\t\tdnsRequirements: this.dnsRequirements,\n\t\t});\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;AAqDA,IAAM,iCAAN,MAEA;CACC,MAAM,OACL,QACuC;EACvC,MAAM,SAAS,IAAIA,6BAAU,OAAO,KAAK;EACzC,MAAM,OAAO,YAAY,OAAO,QAAQ,gBAAgB,mBAAmB,OAAO,QAAQ;EAE1F,IAAI,OAAO,MAAM,OAAO,OAA+B,IAAI;EAE3D,IAAI,MACH,eAAO,IAAI,KAAK,sCAAsC,OAAO,SAAS,EAAE;OAExE,OAAO,MAAM,OAAO,KACnB,YAAY,OAAO,QAAQ,qBAC3B,EAAE,UAAU,OAAO,SAAS,CAC7B;EAGD,MAAM,OAA8B;GACnC,GAAG;GACH,YAAY,KAAK,cAAc;GAC/B,iBAAiB,KAAK,oBAAoB,CAAC;EAC5C;EAEA,OAAO;GAAE,IAAI,OAAO;GAAU;EAAK;CACpC;CAEA,MAAM,KACL,IACA,OACqC;EAGrC,MAAM,OAAO,MAAM,IAFAA,6BAAU,MAAM,KAEX,EAAE,OACzB,YAAY,MAAM,QAAQ,gBAAgB,mBAAmB,EAAE,GAChE;EAEA,IAAI,CAAC,MAEJ,OAAO,CAAC;EAGT,OAAO;GACN;GACA,OAAO;IACN,GAAG;IACH,YAAY,KAAK,cAAc;IAC/B,iBAAiB,KAAK,oBAAoB,CAAC;GAC5C;EACD;CACD;CAEA,MAAM,OACL,KACA,OACA,MACuC;EAEvC,OAAO,EACN,MAAM;GAAE,GAAG;GAAM,YAAY;GAAO,iBAAiB,CAAC;EAAE,EACzD;CACD;CAEA,MAAM,OAAO,IAAY,OAA6C;EACrE,MAAM,SAAS,IAAIA,6BAAU,MAAM,KAAK;EAExC,IAAI;GACH,MAAM,OAAO,OACZ,YAAY,MAAM,QAAQ,gBAAgB,mBAAmB,EAAE,GAChE;EACD,SAAS,OAAO;GAEf,IAAI,iBAAiBC,qDAAkB;IACtC,eAAO,IAAI,KAAK,oBAAoB,GAAG,kBAAkB;IAEzD;GACD;GAEA,MAAM;EACP;CACD;CAEA,MAAM,KACL,KACA,MACA,MACqC;EACrC,MAAM,WAAqB,CAAC;EAE5B,IAAI,KAAK,YAAY,KAAK,SACzB,SAAS,KAAK,SAAS;EAGxB,IAAI,KAAK,aAAa,KAAK,UAC1B,SAAS,KAAK,UAAU;EAGzB,OAAO;GACN,SAAS,SAAS,SAAS;GAC3B;GACA,qBAAqB;EACtB;CACD;AACD;;AAGA,IAAM,yBAAN,cAAqCC,eAAO,QAAQ,SAAS;CAI5D,YACC,MACA,MAKA,MACC;EACD,MACC,IAAI,+BAA+B,GACnC,MACA;GAAE,GAAG;GAAM,YAAY;GAAW,iBAAiB;EAAU,GAE7D;GAAE,GAAG;GAAM,yBAAyB,CAAC,OAAO;EAAE,CAC/C;CACD;AACD;;;;;;;;;;;;;;AAiCA,IAAa,iBAAb,cAAoCA,eAAO,kBAAkB;CAU5D,YACC,MACA,MACA,MACC;EACD,MAAM,EAAE,UAAU,KAAK,GAAG,eAAe;EAEzC,MAAM,8BAA8B,MAAM,CAAC,GAAG,UAAU;EAExD,MAAM,WAAW,IAAI,uBACpB,GAAG,KAAK,YACR;GACC,OAAO,SAAS;GAChB,SAAS,IAAI;GACb,UAAU,KAAK;EAChB,GACA,EAAE,QAAQ,KAAK,CAChB;EAEA,KAAK,KAAKA,eAAO,OAAO,KAAK,QAAQ;EACrC,KAAK,aAAa,SAAS;EAC3B,KAAK,kBAAkB,SAAS;EAEhC,KAAK,gBAAgB;GACpB,IAAI,KAAK;GACT,YAAY,KAAK;GACjB,iBAAiB,KAAK;EACvB,CAAC;CACF;AACD"}
1
+ {"version":3,"file":"certificate.cjs","names":["FlyClient","ApiNotFoundError","pulumi"],"sources":["../../src/fly/certificate.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\n\nimport { ApiNotFoundError } from \"../errors/api-not-found-error\";\nimport type { FlyApp } from \"./app\";\nimport { FlyClient } from \"./client\";\nimport type { FlyProvider } from \"./provider\";\n\n/** DNS records the consumer must create for certificate validation. */\nexport interface FlyDnsRequirements {\n\t/** ACME challenge CNAME record. */\n\tacme_challenge?: { name: string; target: string };\n\n\t/** `_fly-ownership` TXT record. */\n\townership?: { name: string; app_value: string };\n\n\t/** CNAME target for the hostname itself. */\n\tcname?: string;\n}\n\n/** Resolved inputs for the Fly certificate dynamic provider. */\ninterface FlyCertificateInputs {\n\t/** Fly API token. */\n\ttoken: string;\n\n\t/** App name the certificate belongs to. */\n\tappName: string;\n\n\t/** Hostname to issue an ACME certificate for. Used as the resource key. */\n\thostname: string;\n}\n\n/** Persisted state for the Fly certificate. */\ninterface FlyCertificateOutputs extends FlyCertificateInputs {\n\t/** Whether the certificate is fully provisioned (DNS correct). */\n\tconfigured: boolean;\n\n\t/** DNS records required for validation. */\n\tdnsRequirements: FlyDnsRequirements;\n}\n\n/** Certificate response (only the fields we read). */\ninterface FlyCertificateResponse {\n\thostname: string;\n\tconfigured: boolean;\n\tdns_requirements?: FlyDnsRequirements;\n}\n\n/**\n * Dynamic provider for Fly ACME (Let's Encrypt) certificates. `create()` checks\n * for an existing cert by hostname and adopts it, otherwise it requests one via\n * `POST /v1/apps/{app}/certificates/acme`. The Machines API returns no `id` —\n * the hostname is the resource key.\n *\n * @internal Exported only for unit testing; not part of the public API surface.\n */\nexport class FlyCertificateResourceProvider\n\timplements pulumi.dynamic.ResourceProvider\n{\n\tasync create(\n\t\tinputs: FlyCertificateInputs,\n\t): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new FlyClient(inputs.token);\n\t\tconst path = `/v1/apps/${inputs.appName}/certificates/${encodeURIComponent(inputs.hostname)}`;\n\n\t\tlet cert = await client.tryGet<FlyCertificateResponse>(path);\n\n\t\tif (cert) {\n\t\t\tpulumi.log.info(`Adopting existing Fly certificate \"${inputs.hostname}\"`);\n\t\t} else {\n\t\t\tcert = await client.post<FlyCertificateResponse>(\n\t\t\t\t`/v1/apps/${inputs.appName}/certificates/acme`,\n\t\t\t\t{ hostname: inputs.hostname },\n\t\t\t);\n\t\t}\n\n\t\tconst outs: FlyCertificateOutputs = {\n\t\t\t...inputs,\n\t\t\tconfigured: cert.configured ?? false,\n\t\t\tdnsRequirements: cert.dns_requirements ?? {},\n\t\t};\n\n\t\treturn { id: inputs.hostname, outs };\n\t}\n\n\tasync read(\n\t\tid: string,\n\t\tprops: FlyCertificateOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new FlyClient(props.token);\n\n\t\tconst cert = await client.tryGet<FlyCertificateResponse>(\n\t\t\t`/v1/apps/${props.appName}/certificates/${encodeURIComponent(id)}`,\n\t\t);\n\n\t\tif (!cert) {\n\t\t\t// Resource gone → blank id lets refresh reconcile the deletion.\n\t\t\treturn {};\n\t\t}\n\n\t\treturn {\n\t\t\tid,\n\t\t\tprops: {\n\t\t\t\t...props,\n\t\t\t\tconfigured: cert.configured ?? false,\n\t\t\t\tdnsRequirements: cert.dns_requirements ?? {},\n\t\t\t},\n\t\t};\n\t}\n\n\tasync update(\n\t\t_id: string,\n\t\t_olds: FlyCertificateOutputs,\n\t\tnews: FlyCertificateInputs,\n\t): Promise<pulumi.dynamic.UpdateResult> {\n\t\t// Hostname/app changes force replacement (see diff); nothing else is updatable.\n\t\treturn {\n\t\t\touts: { ...news, configured: false, dnsRequirements: {} },\n\t\t};\n\t}\n\n\tasync delete(id: string, props: FlyCertificateOutputs): Promise<void> {\n\t\tconst client = new FlyClient(props.token);\n\n\t\ttry {\n\t\t\tawait client.delete(\n\t\t\t\t`/v1/apps/${props.appName}/certificates/${encodeURIComponent(id)}`,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\t// Already gone — deletion is idempotent.\n\t\t\tif (error instanceof ApiNotFoundError) {\n\t\t\t\tpulumi.log.warn(`Fly certificate \"${id}\" already deleted`);\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync diff(\n\t\t_id: string,\n\t\tolds: FlyCertificateOutputs,\n\t\tnews: FlyCertificateInputs,\n\t): Promise<pulumi.dynamic.DiffResult> {\n\t\tconst replaces: string[] = [];\n\n\t\tif (olds.appName !== news.appName) {\n\t\t\treplaces.push(\"appName\");\n\t\t}\n\n\t\tif (olds.hostname !== news.hostname) {\n\t\t\treplaces.push(\"hostname\");\n\t\t}\n\n\t\treturn {\n\t\t\tchanges: replaces.length > 0,\n\t\t\treplaces,\n\t\t\tdeleteBeforeReplace: true,\n\t\t};\n\t}\n}\n\n/** Internal dynamic resource — not part of the public API. */\nclass FlyCertificateResource extends pulumi.dynamic.Resource {\n\tpublic declare readonly configured: pulumi.Output<boolean>;\n\tpublic declare readonly dnsRequirements: pulumi.Output<FlyDnsRequirements>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: {\n\t\t\ttoken: pulumi.Input<string>;\n\t\t\tappName: pulumi.Input<string>;\n\t\t\thostname: pulumi.Input<string>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(\n\t\t\tnew FlyCertificateResourceProvider(),\n\t\t\tname,\n\t\t\t{ ...args, configured: undefined, dnsRequirements: undefined },\n\t\t\t// The API token flows into dynamic-provider state with the outputs — mark it secret there.\n\t\t\t{ ...opts, additionalSecretOutputs: [\"token\"] },\n\t\t);\n\t}\n}\n\n/** Options type for FlyCertificate. */\ntype FlyCertificateOptions = Omit<\n\tpulumi.ComponentResourceOptions,\n\t\"provider\"\n> & {\n\t/** Fly authentication context. */\n\tprovider: FlyProvider;\n\n\t/** App the certificate belongs to. */\n\tapp: FlyApp;\n};\n\n/** Args for FlyCertificate. */\nexport interface FlyCertificateArgs {\n\t/** Hostname to issue an ACME certificate for (e.g. `\"api.example.com\"`). */\n\thostname: pulumi.Input<string>;\n}\n\n/**\n * Manages a Fly ACME certificate for a custom hostname.\n *\n * Exposes `.configured` and `.dnsRequirements` so the consumer can wire up the\n * required DNS records.\n *\n * @example\n * ```typescript\n * const cert = new FlyCertificate(\"api-cert\", {\n * hostname: \"api.example.com\",\n * }, { provider, app });\n * ```\n */\nexport class FlyCertificate extends pulumi.ComponentResource {\n\t/** Certificate identifier (equals the hostname). */\n\tpublic readonly id: pulumi.Output<string>;\n\n\t/** Whether the certificate is fully provisioned. */\n\tpublic readonly configured: pulumi.Output<boolean>;\n\n\t/** DNS records required for validation. */\n\tpublic readonly dnsRequirements: pulumi.Output<FlyDnsRequirements>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: FlyCertificateArgs,\n\t\topts: FlyCertificateOptions,\n\t) {\n\t\tconst { provider, app, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:fly:Certificate\", name, {}, pulumiOpts);\n\n\t\tconst resource = new FlyCertificateResource(\n\t\t\t`${name}-resource`,\n\t\t\t{\n\t\t\t\ttoken: provider.token,\n\t\t\t\tappName: app.id,\n\t\t\t\thostname: args.hostname,\n\t\t\t},\n\t\t\t{ parent: this },\n\t\t);\n\n\t\tthis.id = pulumi.output(args.hostname);\n\t\tthis.configured = resource.configured;\n\t\tthis.dnsRequirements = resource.dnsRequirements;\n\n\t\tthis.registerOutputs({\n\t\t\tid: this.id,\n\t\t\tconfigured: this.configured,\n\t\t\tdnsRequirements: this.dnsRequirements,\n\t\t});\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAuDA,IAAa,iCAAb,MAEA;CACC,MAAM,OACL,QACuC;EACvC,MAAM,SAAS,IAAIA,6BAAU,OAAO,KAAK;EACzC,MAAM,OAAO,YAAY,OAAO,QAAQ,gBAAgB,mBAAmB,OAAO,QAAQ;EAE1F,IAAI,OAAO,MAAM,OAAO,OAA+B,IAAI;EAE3D,IAAI,MACH,eAAO,IAAI,KAAK,sCAAsC,OAAO,SAAS,EAAE;OAExE,OAAO,MAAM,OAAO,KACnB,YAAY,OAAO,QAAQ,qBAC3B,EAAE,UAAU,OAAO,SAAS,CAC7B;EAGD,MAAM,OAA8B;GACnC,GAAG;GACH,YAAY,KAAK,cAAc;GAC/B,iBAAiB,KAAK,oBAAoB,CAAC;EAC5C;EAEA,OAAO;GAAE,IAAI,OAAO;GAAU;EAAK;CACpC;CAEA,MAAM,KACL,IACA,OACqC;EAGrC,MAAM,OAAO,MAAM,IAFAA,6BAAU,MAAM,KAEX,EAAE,OACzB,YAAY,MAAM,QAAQ,gBAAgB,mBAAmB,EAAE,GAChE;EAEA,IAAI,CAAC,MAEJ,OAAO,CAAC;EAGT,OAAO;GACN;GACA,OAAO;IACN,GAAG;IACH,YAAY,KAAK,cAAc;IAC/B,iBAAiB,KAAK,oBAAoB,CAAC;GAC5C;EACD;CACD;CAEA,MAAM,OACL,KACA,OACA,MACuC;EAEvC,OAAO,EACN,MAAM;GAAE,GAAG;GAAM,YAAY;GAAO,iBAAiB,CAAC;EAAE,EACzD;CACD;CAEA,MAAM,OAAO,IAAY,OAA6C;EACrE,MAAM,SAAS,IAAIA,6BAAU,MAAM,KAAK;EAExC,IAAI;GACH,MAAM,OAAO,OACZ,YAAY,MAAM,QAAQ,gBAAgB,mBAAmB,EAAE,GAChE;EACD,SAAS,OAAO;GAEf,IAAI,iBAAiBC,qDAAkB;IACtC,eAAO,IAAI,KAAK,oBAAoB,GAAG,kBAAkB;IAEzD;GACD;GAEA,MAAM;EACP;CACD;CAEA,MAAM,KACL,KACA,MACA,MACqC;EACrC,MAAM,WAAqB,CAAC;EAE5B,IAAI,KAAK,YAAY,KAAK,SACzB,SAAS,KAAK,SAAS;EAGxB,IAAI,KAAK,aAAa,KAAK,UAC1B,SAAS,KAAK,UAAU;EAGzB,OAAO;GACN,SAAS,SAAS,SAAS;GAC3B;GACA,qBAAqB;EACtB;CACD;AACD;;AAGA,IAAM,yBAAN,cAAqCC,eAAO,QAAQ,SAAS;CAI5D,YACC,MACA,MAKA,MACC;EACD,MACC,IAAI,+BAA+B,GACnC,MACA;GAAE,GAAG;GAAM,YAAY;GAAW,iBAAiB;EAAU,GAE7D;GAAE,GAAG;GAAM,yBAAyB,CAAC,OAAO;EAAE,CAC/C;CACD;AACD;;;;;;;;;;;;;;AAiCA,IAAa,iBAAb,cAAoCA,eAAO,kBAAkB;CAU5D,YACC,MACA,MACA,MACC;EACD,MAAM,EAAE,UAAU,KAAK,GAAG,eAAe;EAEzC,MAAM,8BAA8B,MAAM,CAAC,GAAG,UAAU;EAExD,MAAM,WAAW,IAAI,uBACpB,GAAG,KAAK,YACR;GACC,OAAO,SAAS;GAChB,SAAS,IAAI;GACb,UAAU,KAAK;EAChB,GACA,EAAE,QAAQ,KAAK,CAChB;EAEA,KAAK,KAAKA,eAAO,OAAO,KAAK,QAAQ;EACrC,KAAK,aAAa,SAAS;EAC3B,KAAK,kBAAkB,SAAS;EAEhC,KAAK,gBAAgB;GACpB,IAAI,KAAK;GACT,YAAY,KAAK;GACjB,iBAAiB,KAAK;EACvB,CAAC;CACF;AACD"}
@@ -19,6 +19,37 @@ interface FlyDnsRequirements {
19
19
  /** CNAME target for the hostname itself. */
20
20
  cname?: string;
21
21
  }
22
+ /** Resolved inputs for the Fly certificate dynamic provider. */
23
+ interface FlyCertificateInputs {
24
+ /** Fly API token. */
25
+ token: string;
26
+ /** App name the certificate belongs to. */
27
+ appName: string;
28
+ /** Hostname to issue an ACME certificate for. Used as the resource key. */
29
+ hostname: string;
30
+ }
31
+ /** Persisted state for the Fly certificate. */
32
+ interface FlyCertificateOutputs extends FlyCertificateInputs {
33
+ /** Whether the certificate is fully provisioned (DNS correct). */
34
+ configured: boolean;
35
+ /** DNS records required for validation. */
36
+ dnsRequirements: FlyDnsRequirements;
37
+ }
38
+ /**
39
+ * Dynamic provider for Fly ACME (Let's Encrypt) certificates. `create()` checks
40
+ * for an existing cert by hostname and adopts it, otherwise it requests one via
41
+ * `POST /v1/apps/{app}/certificates/acme`. The Machines API returns no `id` —
42
+ * the hostname is the resource key.
43
+ *
44
+ * @internal Exported only for unit testing; not part of the public API surface.
45
+ */
46
+ declare class FlyCertificateResourceProvider implements pulumi.dynamic.ResourceProvider {
47
+ create(inputs: FlyCertificateInputs): Promise<pulumi.dynamic.CreateResult>;
48
+ read(id: string, props: FlyCertificateOutputs): Promise<pulumi.dynamic.ReadResult>;
49
+ update(_id: string, _olds: FlyCertificateOutputs, news: FlyCertificateInputs): Promise<pulumi.dynamic.UpdateResult>;
50
+ delete(id: string, props: FlyCertificateOutputs): Promise<void>;
51
+ diff(_id: string, olds: FlyCertificateOutputs, news: FlyCertificateInputs): Promise<pulumi.dynamic.DiffResult>;
52
+ }
22
53
  /** Options type for FlyCertificate. */
23
54
  type FlyCertificateOptions = Omit<pulumi.ComponentResourceOptions, "provider"> & {
24
55
  /** Fly authentication context. */provider: FlyProvider; /** App the certificate belongs to. */
@@ -52,5 +83,5 @@ declare class FlyCertificate extends pulumi.ComponentResource {
52
83
  constructor(name: string, args: FlyCertificateArgs, opts: FlyCertificateOptions);
53
84
  }
54
85
  //#endregion
55
- export { FlyCertificate, FlyCertificateArgs, FlyDnsRequirements };
86
+ export { FlyCertificate, FlyCertificateArgs, FlyCertificateResourceProvider, FlyDnsRequirements };
56
87
  //# sourceMappingURL=certificate.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"certificate.d.cts","names":[],"sources":["../../src/fly/certificate.ts"],"mappings":";;;;;;;UAQiB,kBAAA;;EAEhB,cAAA;IAAmB,IAAA;IAAc,MAAA;EAAA;EAAjC;EAGA,SAAA;IAAc,IAAA;IAAc,SAAA;EAAA;EAAA;EAG5B,KAAA;AAAA;AAAK;AAAA,KAyKD,qBAAA,GAAwB,IAAA,CAC5B,MAAA,CAAO,wBAAA;EADkB,kCAKzB,QAAA,EAAU,WAAA,EAJV;EAOA,GAAA,EAAK,MAAA;AAAA;;UAIW,kBAAA;EAJL;EAMX,QAAA,EAAU,MAAA,CAAO,KAAK;AAAA;;;;;;;AANX;AAIZ;;;;;;cAkBa,cAAA,SAAuB,MAAA,CAAO,iBAAA;EAhBpB;EAAA,SAkBN,EAAA,EAAI,MAAA,CAAO,MAAA;EAFf;EAAA,SAKI,UAAA,EAAY,MAAA,CAAO,MAAA;;WAGnB,eAAA,EAAiB,MAAA,CAAO,MAAA,CAAO,kBAAA;cAG9C,IAAA,UACA,IAAA,EAAM,kBAAA,EACN,IAAA,EAAM,qBAAA;AAAA"}
1
+ {"version":3,"file":"certificate.d.cts","names":[],"sources":["../../src/fly/certificate.ts"],"mappings":";;;;;;;UAQiB,kBAAA;;EAEhB,cAAA;IAAmB,IAAA;IAAc,MAAA;EAAA;EAAjC;EAGA,SAAA;IAAc,IAAA;IAAc,SAAA;EAAA;EAAA;EAG5B,KAAA;AAAA;AAAK;AAAA,UAII,oBAAA;EAAoB;EAE7B,KAAA;EAF6B;EAK7B,OAAA;EAAA;EAGA,QAAA;AAAA;AAAQ;AAAA,UAIC,qBAAA,SAA8B,oBAAoB;EAA5B;EAE/B,UAAA;EAF2D;EAK3D,eAAA,EAAiB,kBAAA;AAAA;;;;AAAkB;AAkBpC;;;;cAAa,8BAAA,YACD,MAAA,CAAO,OAAA,CAAQ,gBAAA;EAEpB,MAAA,CACL,MAAA,EAAQ,oBAAA,GACN,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,YAAA;EAwBpB,IAAA,CACL,EAAA,UACA,KAAA,EAAO,qBAAA,GACL,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,UAAA;EAsBpB,MAAA,CACL,GAAA,UACA,KAAA,EAAO,qBAAA,EACP,IAAA,EAAM,oBAAA,GACJ,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,YAAA;EAOpB,MAAA,CAAO,EAAA,UAAY,KAAA,EAAO,qBAAA,GAAwB,OAAA;EAmBlD,IAAA,CACL,GAAA,UACA,IAAA,EAAM,qBAAA,EACN,IAAA,EAAM,oBAAA,GACJ,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,UAAA;AAAA;;KA4CtB,qBAAA,GAAwB,IAAA,CAC5B,MAAA,CAAO,wBAAA;EApEyB,kCAwEhC,QAAA,EAAU,WAAA,EAnDH;EAsDP,GAAA,EAAK,MAAA;AAAA;;UAIW,kBAAA;EA/I0B;EAiJ1C,QAAA,EAAU,MAAA,CAAO,KAAK;AAAA;;;;;;;;;;;;;;cAgBV,cAAA,SAAuB,MAAA,CAAO,iBAAA;EAlI/B;EAAA,SAoIK,EAAA,EAAI,MAAA,CAAO,MAAA;EApID;EAAA,SAuIV,UAAA,EAAY,MAAA,CAAO,MAAA;EAhHlC;EAAA,SAmHe,eAAA,EAAiB,MAAA,CAAO,MAAA,CAAO,kBAAA;cAG9C,IAAA,UACA,IAAA,EAAM,kBAAA,EACN,IAAA,EAAM,qBAAA;AAAA"}
@@ -19,6 +19,37 @@ interface FlyDnsRequirements {
19
19
  /** CNAME target for the hostname itself. */
20
20
  cname?: string;
21
21
  }
22
+ /** Resolved inputs for the Fly certificate dynamic provider. */
23
+ interface FlyCertificateInputs {
24
+ /** Fly API token. */
25
+ token: string;
26
+ /** App name the certificate belongs to. */
27
+ appName: string;
28
+ /** Hostname to issue an ACME certificate for. Used as the resource key. */
29
+ hostname: string;
30
+ }
31
+ /** Persisted state for the Fly certificate. */
32
+ interface FlyCertificateOutputs extends FlyCertificateInputs {
33
+ /** Whether the certificate is fully provisioned (DNS correct). */
34
+ configured: boolean;
35
+ /** DNS records required for validation. */
36
+ dnsRequirements: FlyDnsRequirements;
37
+ }
38
+ /**
39
+ * Dynamic provider for Fly ACME (Let's Encrypt) certificates. `create()` checks
40
+ * for an existing cert by hostname and adopts it, otherwise it requests one via
41
+ * `POST /v1/apps/{app}/certificates/acme`. The Machines API returns no `id` —
42
+ * the hostname is the resource key.
43
+ *
44
+ * @internal Exported only for unit testing; not part of the public API surface.
45
+ */
46
+ declare class FlyCertificateResourceProvider implements pulumi.dynamic.ResourceProvider {
47
+ create(inputs: FlyCertificateInputs): Promise<pulumi.dynamic.CreateResult>;
48
+ read(id: string, props: FlyCertificateOutputs): Promise<pulumi.dynamic.ReadResult>;
49
+ update(_id: string, _olds: FlyCertificateOutputs, news: FlyCertificateInputs): Promise<pulumi.dynamic.UpdateResult>;
50
+ delete(id: string, props: FlyCertificateOutputs): Promise<void>;
51
+ diff(_id: string, olds: FlyCertificateOutputs, news: FlyCertificateInputs): Promise<pulumi.dynamic.DiffResult>;
52
+ }
22
53
  /** Options type for FlyCertificate. */
23
54
  type FlyCertificateOptions = Omit<pulumi.ComponentResourceOptions, "provider"> & {
24
55
  /** Fly authentication context. */provider: FlyProvider; /** App the certificate belongs to. */
@@ -52,5 +83,5 @@ declare class FlyCertificate extends pulumi.ComponentResource {
52
83
  constructor(name: string, args: FlyCertificateArgs, opts: FlyCertificateOptions);
53
84
  }
54
85
  //#endregion
55
- export { FlyCertificate, FlyCertificateArgs, FlyDnsRequirements };
86
+ export { FlyCertificate, FlyCertificateArgs, FlyCertificateResourceProvider, FlyDnsRequirements };
56
87
  //# sourceMappingURL=certificate.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"certificate.d.mts","names":[],"sources":["../../src/fly/certificate.ts"],"mappings":";;;;;;;UAQiB,kBAAA;;EAEhB,cAAA;IAAmB,IAAA;IAAc,MAAA;EAAA;EAAjC;EAGA,SAAA;IAAc,IAAA;IAAc,SAAA;EAAA;EAAA;EAG5B,KAAA;AAAA;AAAK;AAAA,KAyKD,qBAAA,GAAwB,IAAA,CAC5B,MAAA,CAAO,wBAAA;EADkB,kCAKzB,QAAA,EAAU,WAAA,EAJV;EAOA,GAAA,EAAK,MAAA;AAAA;;UAIW,kBAAA;EAJL;EAMX,QAAA,EAAU,MAAA,CAAO,KAAK;AAAA;;;;;;;AANX;AAIZ;;;;;;cAkBa,cAAA,SAAuB,MAAA,CAAO,iBAAA;EAhBpB;EAAA,SAkBN,EAAA,EAAI,MAAA,CAAO,MAAA;EAFf;EAAA,SAKI,UAAA,EAAY,MAAA,CAAO,MAAA;;WAGnB,eAAA,EAAiB,MAAA,CAAO,MAAA,CAAO,kBAAA;cAG9C,IAAA,UACA,IAAA,EAAM,kBAAA,EACN,IAAA,EAAM,qBAAA;AAAA"}
1
+ {"version":3,"file":"certificate.d.mts","names":[],"sources":["../../src/fly/certificate.ts"],"mappings":";;;;;;;UAQiB,kBAAA;;EAEhB,cAAA;IAAmB,IAAA;IAAc,MAAA;EAAA;EAAjC;EAGA,SAAA;IAAc,IAAA;IAAc,SAAA;EAAA;EAAA;EAG5B,KAAA;AAAA;AAAK;AAAA,UAII,oBAAA;EAAoB;EAE7B,KAAA;EAF6B;EAK7B,OAAA;EAAA;EAGA,QAAA;AAAA;AAAQ;AAAA,UAIC,qBAAA,SAA8B,oBAAoB;EAA5B;EAE/B,UAAA;EAF2D;EAK3D,eAAA,EAAiB,kBAAA;AAAA;;;;AAAkB;AAkBpC;;;;cAAa,8BAAA,YACD,MAAA,CAAO,OAAA,CAAQ,gBAAA;EAEpB,MAAA,CACL,MAAA,EAAQ,oBAAA,GACN,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,YAAA;EAwBpB,IAAA,CACL,EAAA,UACA,KAAA,EAAO,qBAAA,GACL,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,UAAA;EAsBpB,MAAA,CACL,GAAA,UACA,KAAA,EAAO,qBAAA,EACP,IAAA,EAAM,oBAAA,GACJ,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,YAAA;EAOpB,MAAA,CAAO,EAAA,UAAY,KAAA,EAAO,qBAAA,GAAwB,OAAA;EAmBlD,IAAA,CACL,GAAA,UACA,IAAA,EAAM,qBAAA,EACN,IAAA,EAAM,oBAAA,GACJ,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,UAAA;AAAA;;KA4CtB,qBAAA,GAAwB,IAAA,CAC5B,MAAA,CAAO,wBAAA;EApEyB,kCAwEhC,QAAA,EAAU,WAAA,EAnDH;EAsDP,GAAA,EAAK,MAAA;AAAA;;UAIW,kBAAA;EA/I0B;EAiJ1C,QAAA,EAAU,MAAA,CAAO,KAAK;AAAA;;;;;;;;;;;;;;cAgBV,cAAA,SAAuB,MAAA,CAAO,iBAAA;EAlI/B;EAAA,SAoIK,EAAA,EAAI,MAAA,CAAO,MAAA;EApID;EAAA,SAuIV,UAAA,EAAY,MAAA,CAAO,MAAA;EAhHlC;EAAA,SAmHe,eAAA,EAAiB,MAAA,CAAO,MAAA,CAAO,kBAAA;cAG9C,IAAA,UACA,IAAA,EAAM,kBAAA,EACN,IAAA,EAAM,qBAAA;AAAA"}
@@ -9,6 +9,8 @@ import * as pulumi from "@pulumi/pulumi";
9
9
  * for an existing cert by hostname and adopts it, otherwise it requests one via
10
10
  * `POST /v1/apps/{app}/certificates/acme`. The Machines API returns no `id` —
11
11
  * the hostname is the resource key.
12
+ *
13
+ * @internal Exported only for unit testing; not part of the public API surface.
12
14
  */
13
15
  var FlyCertificateResourceProvider = class {
14
16
  async create(inputs) {
@@ -116,5 +118,5 @@ var FlyCertificate = class extends pulumi.ComponentResource {
116
118
  };
117
119
 
118
120
  //#endregion
119
- export { FlyCertificate };
121
+ export { FlyCertificate, FlyCertificateResourceProvider };
120
122
  //# sourceMappingURL=certificate.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"certificate.mjs","names":[],"sources":["../../src/fly/certificate.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\n\nimport { ApiNotFoundError } from \"../errors/api-not-found-error\";\nimport type { FlyApp } from \"./app\";\nimport { FlyClient } from \"./client\";\nimport type { FlyProvider } from \"./provider\";\n\n/** DNS records the consumer must create for certificate validation. */\nexport interface FlyDnsRequirements {\n\t/** ACME challenge CNAME record. */\n\tacme_challenge?: { name: string; target: string };\n\n\t/** `_fly-ownership` TXT record. */\n\townership?: { name: string; app_value: string };\n\n\t/** CNAME target for the hostname itself. */\n\tcname?: string;\n}\n\n/** Resolved inputs for the Fly certificate dynamic provider. */\ninterface FlyCertificateInputs {\n\t/** Fly API token. */\n\ttoken: string;\n\n\t/** App name the certificate belongs to. */\n\tappName: string;\n\n\t/** Hostname to issue an ACME certificate for. Used as the resource key. */\n\thostname: string;\n}\n\n/** Persisted state for the Fly certificate. */\ninterface FlyCertificateOutputs extends FlyCertificateInputs {\n\t/** Whether the certificate is fully provisioned (DNS correct). */\n\tconfigured: boolean;\n\n\t/** DNS records required for validation. */\n\tdnsRequirements: FlyDnsRequirements;\n}\n\n/** Certificate response (only the fields we read). */\ninterface FlyCertificateResponse {\n\thostname: string;\n\tconfigured: boolean;\n\tdns_requirements?: FlyDnsRequirements;\n}\n\n/**\n * Dynamic provider for Fly ACME (Let's Encrypt) certificates. `create()` checks\n * for an existing cert by hostname and adopts it, otherwise it requests one via\n * `POST /v1/apps/{app}/certificates/acme`. The Machines API returns no `id` —\n * the hostname is the resource key.\n */\nclass FlyCertificateResourceProvider\n\timplements pulumi.dynamic.ResourceProvider\n{\n\tasync create(\n\t\tinputs: FlyCertificateInputs,\n\t): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new FlyClient(inputs.token);\n\t\tconst path = `/v1/apps/${inputs.appName}/certificates/${encodeURIComponent(inputs.hostname)}`;\n\n\t\tlet cert = await client.tryGet<FlyCertificateResponse>(path);\n\n\t\tif (cert) {\n\t\t\tpulumi.log.info(`Adopting existing Fly certificate \"${inputs.hostname}\"`);\n\t\t} else {\n\t\t\tcert = await client.post<FlyCertificateResponse>(\n\t\t\t\t`/v1/apps/${inputs.appName}/certificates/acme`,\n\t\t\t\t{ hostname: inputs.hostname },\n\t\t\t);\n\t\t}\n\n\t\tconst outs: FlyCertificateOutputs = {\n\t\t\t...inputs,\n\t\t\tconfigured: cert.configured ?? false,\n\t\t\tdnsRequirements: cert.dns_requirements ?? {},\n\t\t};\n\n\t\treturn { id: inputs.hostname, outs };\n\t}\n\n\tasync read(\n\t\tid: string,\n\t\tprops: FlyCertificateOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new FlyClient(props.token);\n\n\t\tconst cert = await client.tryGet<FlyCertificateResponse>(\n\t\t\t`/v1/apps/${props.appName}/certificates/${encodeURIComponent(id)}`,\n\t\t);\n\n\t\tif (!cert) {\n\t\t\t// Resource gone → blank id lets refresh reconcile the deletion.\n\t\t\treturn {};\n\t\t}\n\n\t\treturn {\n\t\t\tid,\n\t\t\tprops: {\n\t\t\t\t...props,\n\t\t\t\tconfigured: cert.configured ?? false,\n\t\t\t\tdnsRequirements: cert.dns_requirements ?? {},\n\t\t\t},\n\t\t};\n\t}\n\n\tasync update(\n\t\t_id: string,\n\t\t_olds: FlyCertificateOutputs,\n\t\tnews: FlyCertificateInputs,\n\t): Promise<pulumi.dynamic.UpdateResult> {\n\t\t// Hostname/app changes force replacement (see diff); nothing else is updatable.\n\t\treturn {\n\t\t\touts: { ...news, configured: false, dnsRequirements: {} },\n\t\t};\n\t}\n\n\tasync delete(id: string, props: FlyCertificateOutputs): Promise<void> {\n\t\tconst client = new FlyClient(props.token);\n\n\t\ttry {\n\t\t\tawait client.delete(\n\t\t\t\t`/v1/apps/${props.appName}/certificates/${encodeURIComponent(id)}`,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\t// Already gone — deletion is idempotent.\n\t\t\tif (error instanceof ApiNotFoundError) {\n\t\t\t\tpulumi.log.warn(`Fly certificate \"${id}\" already deleted`);\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync diff(\n\t\t_id: string,\n\t\tolds: FlyCertificateOutputs,\n\t\tnews: FlyCertificateInputs,\n\t): Promise<pulumi.dynamic.DiffResult> {\n\t\tconst replaces: string[] = [];\n\n\t\tif (olds.appName !== news.appName) {\n\t\t\treplaces.push(\"appName\");\n\t\t}\n\n\t\tif (olds.hostname !== news.hostname) {\n\t\t\treplaces.push(\"hostname\");\n\t\t}\n\n\t\treturn {\n\t\t\tchanges: replaces.length > 0,\n\t\t\treplaces,\n\t\t\tdeleteBeforeReplace: true,\n\t\t};\n\t}\n}\n\n/** Internal dynamic resource — not part of the public API. */\nclass FlyCertificateResource extends pulumi.dynamic.Resource {\n\tpublic declare readonly configured: pulumi.Output<boolean>;\n\tpublic declare readonly dnsRequirements: pulumi.Output<FlyDnsRequirements>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: {\n\t\t\ttoken: pulumi.Input<string>;\n\t\t\tappName: pulumi.Input<string>;\n\t\t\thostname: pulumi.Input<string>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(\n\t\t\tnew FlyCertificateResourceProvider(),\n\t\t\tname,\n\t\t\t{ ...args, configured: undefined, dnsRequirements: undefined },\n\t\t\t// The API token flows into dynamic-provider state with the outputs — mark it secret there.\n\t\t\t{ ...opts, additionalSecretOutputs: [\"token\"] },\n\t\t);\n\t}\n}\n\n/** Options type for FlyCertificate. */\ntype FlyCertificateOptions = Omit<\n\tpulumi.ComponentResourceOptions,\n\t\"provider\"\n> & {\n\t/** Fly authentication context. */\n\tprovider: FlyProvider;\n\n\t/** App the certificate belongs to. */\n\tapp: FlyApp;\n};\n\n/** Args for FlyCertificate. */\nexport interface FlyCertificateArgs {\n\t/** Hostname to issue an ACME certificate for (e.g. `\"api.example.com\"`). */\n\thostname: pulumi.Input<string>;\n}\n\n/**\n * Manages a Fly ACME certificate for a custom hostname.\n *\n * Exposes `.configured` and `.dnsRequirements` so the consumer can wire up the\n * required DNS records.\n *\n * @example\n * ```typescript\n * const cert = new FlyCertificate(\"api-cert\", {\n * hostname: \"api.example.com\",\n * }, { provider, app });\n * ```\n */\nexport class FlyCertificate extends pulumi.ComponentResource {\n\t/** Certificate identifier (equals the hostname). */\n\tpublic readonly id: pulumi.Output<string>;\n\n\t/** Whether the certificate is fully provisioned. */\n\tpublic readonly configured: pulumi.Output<boolean>;\n\n\t/** DNS records required for validation. */\n\tpublic readonly dnsRequirements: pulumi.Output<FlyDnsRequirements>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: FlyCertificateArgs,\n\t\topts: FlyCertificateOptions,\n\t) {\n\t\tconst { provider, app, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:fly:Certificate\", name, {}, pulumiOpts);\n\n\t\tconst resource = new FlyCertificateResource(\n\t\t\t`${name}-resource`,\n\t\t\t{\n\t\t\t\ttoken: provider.token,\n\t\t\t\tappName: app.id,\n\t\t\t\thostname: args.hostname,\n\t\t\t},\n\t\t\t{ parent: this },\n\t\t);\n\n\t\tthis.id = pulumi.output(args.hostname);\n\t\tthis.configured = resource.configured;\n\t\tthis.dnsRequirements = resource.dnsRequirements;\n\n\t\tthis.registerOutputs({\n\t\t\tid: this.id,\n\t\t\tconfigured: this.configured,\n\t\t\tdnsRequirements: this.dnsRequirements,\n\t\t});\n\t}\n}\n"],"mappings":";;;;;;;;;;;;AAqDA,IAAM,iCAAN,MAEA;CACC,MAAM,OACL,QACuC;EACvC,MAAM,SAAS,IAAI,UAAU,OAAO,KAAK;EACzC,MAAM,OAAO,YAAY,OAAO,QAAQ,gBAAgB,mBAAmB,OAAO,QAAQ;EAE1F,IAAI,OAAO,MAAM,OAAO,OAA+B,IAAI;EAE3D,IAAI,MACH,OAAO,IAAI,KAAK,sCAAsC,OAAO,SAAS,EAAE;OAExE,OAAO,MAAM,OAAO,KACnB,YAAY,OAAO,QAAQ,qBAC3B,EAAE,UAAU,OAAO,SAAS,CAC7B;EAGD,MAAM,OAA8B;GACnC,GAAG;GACH,YAAY,KAAK,cAAc;GAC/B,iBAAiB,KAAK,oBAAoB,CAAC;EAC5C;EAEA,OAAO;GAAE,IAAI,OAAO;GAAU;EAAK;CACpC;CAEA,MAAM,KACL,IACA,OACqC;EAGrC,MAAM,OAAO,MAAM,IAFA,UAAU,MAAM,KAEX,EAAE,OACzB,YAAY,MAAM,QAAQ,gBAAgB,mBAAmB,EAAE,GAChE;EAEA,IAAI,CAAC,MAEJ,OAAO,CAAC;EAGT,OAAO;GACN;GACA,OAAO;IACN,GAAG;IACH,YAAY,KAAK,cAAc;IAC/B,iBAAiB,KAAK,oBAAoB,CAAC;GAC5C;EACD;CACD;CAEA,MAAM,OACL,KACA,OACA,MACuC;EAEvC,OAAO,EACN,MAAM;GAAE,GAAG;GAAM,YAAY;GAAO,iBAAiB,CAAC;EAAE,EACzD;CACD;CAEA,MAAM,OAAO,IAAY,OAA6C;EACrE,MAAM,SAAS,IAAI,UAAU,MAAM,KAAK;EAExC,IAAI;GACH,MAAM,OAAO,OACZ,YAAY,MAAM,QAAQ,gBAAgB,mBAAmB,EAAE,GAChE;EACD,SAAS,OAAO;GAEf,IAAI,iBAAiB,kBAAkB;IACtC,OAAO,IAAI,KAAK,oBAAoB,GAAG,kBAAkB;IAEzD;GACD;GAEA,MAAM;EACP;CACD;CAEA,MAAM,KACL,KACA,MACA,MACqC;EACrC,MAAM,WAAqB,CAAC;EAE5B,IAAI,KAAK,YAAY,KAAK,SACzB,SAAS,KAAK,SAAS;EAGxB,IAAI,KAAK,aAAa,KAAK,UAC1B,SAAS,KAAK,UAAU;EAGzB,OAAO;GACN,SAAS,SAAS,SAAS;GAC3B;GACA,qBAAqB;EACtB;CACD;AACD;;AAGA,IAAM,yBAAN,cAAqC,OAAO,QAAQ,SAAS;CAI5D,YACC,MACA,MAKA,MACC;EACD,MACC,IAAI,+BAA+B,GACnC,MACA;GAAE,GAAG;GAAM,YAAY;GAAW,iBAAiB;EAAU,GAE7D;GAAE,GAAG;GAAM,yBAAyB,CAAC,OAAO;EAAE,CAC/C;CACD;AACD;;;;;;;;;;;;;;AAiCA,IAAa,iBAAb,cAAoC,OAAO,kBAAkB;CAU5D,YACC,MACA,MACA,MACC;EACD,MAAM,EAAE,UAAU,KAAK,GAAG,eAAe;EAEzC,MAAM,8BAA8B,MAAM,CAAC,GAAG,UAAU;EAExD,MAAM,WAAW,IAAI,uBACpB,GAAG,KAAK,YACR;GACC,OAAO,SAAS;GAChB,SAAS,IAAI;GACb,UAAU,KAAK;EAChB,GACA,EAAE,QAAQ,KAAK,CAChB;EAEA,KAAK,KAAK,OAAO,OAAO,KAAK,QAAQ;EACrC,KAAK,aAAa,SAAS;EAC3B,KAAK,kBAAkB,SAAS;EAEhC,KAAK,gBAAgB;GACpB,IAAI,KAAK;GACT,YAAY,KAAK;GACjB,iBAAiB,KAAK;EACvB,CAAC;CACF;AACD"}
1
+ {"version":3,"file":"certificate.mjs","names":[],"sources":["../../src/fly/certificate.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\n\nimport { ApiNotFoundError } from \"../errors/api-not-found-error\";\nimport type { FlyApp } from \"./app\";\nimport { FlyClient } from \"./client\";\nimport type { FlyProvider } from \"./provider\";\n\n/** DNS records the consumer must create for certificate validation. */\nexport interface FlyDnsRequirements {\n\t/** ACME challenge CNAME record. */\n\tacme_challenge?: { name: string; target: string };\n\n\t/** `_fly-ownership` TXT record. */\n\townership?: { name: string; app_value: string };\n\n\t/** CNAME target for the hostname itself. */\n\tcname?: string;\n}\n\n/** Resolved inputs for the Fly certificate dynamic provider. */\ninterface FlyCertificateInputs {\n\t/** Fly API token. */\n\ttoken: string;\n\n\t/** App name the certificate belongs to. */\n\tappName: string;\n\n\t/** Hostname to issue an ACME certificate for. Used as the resource key. */\n\thostname: string;\n}\n\n/** Persisted state for the Fly certificate. */\ninterface FlyCertificateOutputs extends FlyCertificateInputs {\n\t/** Whether the certificate is fully provisioned (DNS correct). */\n\tconfigured: boolean;\n\n\t/** DNS records required for validation. */\n\tdnsRequirements: FlyDnsRequirements;\n}\n\n/** Certificate response (only the fields we read). */\ninterface FlyCertificateResponse {\n\thostname: string;\n\tconfigured: boolean;\n\tdns_requirements?: FlyDnsRequirements;\n}\n\n/**\n * Dynamic provider for Fly ACME (Let's Encrypt) certificates. `create()` checks\n * for an existing cert by hostname and adopts it, otherwise it requests one via\n * `POST /v1/apps/{app}/certificates/acme`. The Machines API returns no `id` —\n * the hostname is the resource key.\n *\n * @internal Exported only for unit testing; not part of the public API surface.\n */\nexport class FlyCertificateResourceProvider\n\timplements pulumi.dynamic.ResourceProvider\n{\n\tasync create(\n\t\tinputs: FlyCertificateInputs,\n\t): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new FlyClient(inputs.token);\n\t\tconst path = `/v1/apps/${inputs.appName}/certificates/${encodeURIComponent(inputs.hostname)}`;\n\n\t\tlet cert = await client.tryGet<FlyCertificateResponse>(path);\n\n\t\tif (cert) {\n\t\t\tpulumi.log.info(`Adopting existing Fly certificate \"${inputs.hostname}\"`);\n\t\t} else {\n\t\t\tcert = await client.post<FlyCertificateResponse>(\n\t\t\t\t`/v1/apps/${inputs.appName}/certificates/acme`,\n\t\t\t\t{ hostname: inputs.hostname },\n\t\t\t);\n\t\t}\n\n\t\tconst outs: FlyCertificateOutputs = {\n\t\t\t...inputs,\n\t\t\tconfigured: cert.configured ?? false,\n\t\t\tdnsRequirements: cert.dns_requirements ?? {},\n\t\t};\n\n\t\treturn { id: inputs.hostname, outs };\n\t}\n\n\tasync read(\n\t\tid: string,\n\t\tprops: FlyCertificateOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new FlyClient(props.token);\n\n\t\tconst cert = await client.tryGet<FlyCertificateResponse>(\n\t\t\t`/v1/apps/${props.appName}/certificates/${encodeURIComponent(id)}`,\n\t\t);\n\n\t\tif (!cert) {\n\t\t\t// Resource gone → blank id lets refresh reconcile the deletion.\n\t\t\treturn {};\n\t\t}\n\n\t\treturn {\n\t\t\tid,\n\t\t\tprops: {\n\t\t\t\t...props,\n\t\t\t\tconfigured: cert.configured ?? false,\n\t\t\t\tdnsRequirements: cert.dns_requirements ?? {},\n\t\t\t},\n\t\t};\n\t}\n\n\tasync update(\n\t\t_id: string,\n\t\t_olds: FlyCertificateOutputs,\n\t\tnews: FlyCertificateInputs,\n\t): Promise<pulumi.dynamic.UpdateResult> {\n\t\t// Hostname/app changes force replacement (see diff); nothing else is updatable.\n\t\treturn {\n\t\t\touts: { ...news, configured: false, dnsRequirements: {} },\n\t\t};\n\t}\n\n\tasync delete(id: string, props: FlyCertificateOutputs): Promise<void> {\n\t\tconst client = new FlyClient(props.token);\n\n\t\ttry {\n\t\t\tawait client.delete(\n\t\t\t\t`/v1/apps/${props.appName}/certificates/${encodeURIComponent(id)}`,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\t// Already gone — deletion is idempotent.\n\t\t\tif (error instanceof ApiNotFoundError) {\n\t\t\t\tpulumi.log.warn(`Fly certificate \"${id}\" already deleted`);\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync diff(\n\t\t_id: string,\n\t\tolds: FlyCertificateOutputs,\n\t\tnews: FlyCertificateInputs,\n\t): Promise<pulumi.dynamic.DiffResult> {\n\t\tconst replaces: string[] = [];\n\n\t\tif (olds.appName !== news.appName) {\n\t\t\treplaces.push(\"appName\");\n\t\t}\n\n\t\tif (olds.hostname !== news.hostname) {\n\t\t\treplaces.push(\"hostname\");\n\t\t}\n\n\t\treturn {\n\t\t\tchanges: replaces.length > 0,\n\t\t\treplaces,\n\t\t\tdeleteBeforeReplace: true,\n\t\t};\n\t}\n}\n\n/** Internal dynamic resource — not part of the public API. */\nclass FlyCertificateResource extends pulumi.dynamic.Resource {\n\tpublic declare readonly configured: pulumi.Output<boolean>;\n\tpublic declare readonly dnsRequirements: pulumi.Output<FlyDnsRequirements>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: {\n\t\t\ttoken: pulumi.Input<string>;\n\t\t\tappName: pulumi.Input<string>;\n\t\t\thostname: pulumi.Input<string>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(\n\t\t\tnew FlyCertificateResourceProvider(),\n\t\t\tname,\n\t\t\t{ ...args, configured: undefined, dnsRequirements: undefined },\n\t\t\t// The API token flows into dynamic-provider state with the outputs — mark it secret there.\n\t\t\t{ ...opts, additionalSecretOutputs: [\"token\"] },\n\t\t);\n\t}\n}\n\n/** Options type for FlyCertificate. */\ntype FlyCertificateOptions = Omit<\n\tpulumi.ComponentResourceOptions,\n\t\"provider\"\n> & {\n\t/** Fly authentication context. */\n\tprovider: FlyProvider;\n\n\t/** App the certificate belongs to. */\n\tapp: FlyApp;\n};\n\n/** Args for FlyCertificate. */\nexport interface FlyCertificateArgs {\n\t/** Hostname to issue an ACME certificate for (e.g. `\"api.example.com\"`). */\n\thostname: pulumi.Input<string>;\n}\n\n/**\n * Manages a Fly ACME certificate for a custom hostname.\n *\n * Exposes `.configured` and `.dnsRequirements` so the consumer can wire up the\n * required DNS records.\n *\n * @example\n * ```typescript\n * const cert = new FlyCertificate(\"api-cert\", {\n * hostname: \"api.example.com\",\n * }, { provider, app });\n * ```\n */\nexport class FlyCertificate extends pulumi.ComponentResource {\n\t/** Certificate identifier (equals the hostname). */\n\tpublic readonly id: pulumi.Output<string>;\n\n\t/** Whether the certificate is fully provisioned. */\n\tpublic readonly configured: pulumi.Output<boolean>;\n\n\t/** DNS records required for validation. */\n\tpublic readonly dnsRequirements: pulumi.Output<FlyDnsRequirements>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: FlyCertificateArgs,\n\t\topts: FlyCertificateOptions,\n\t) {\n\t\tconst { provider, app, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:fly:Certificate\", name, {}, pulumiOpts);\n\n\t\tconst resource = new FlyCertificateResource(\n\t\t\t`${name}-resource`,\n\t\t\t{\n\t\t\t\ttoken: provider.token,\n\t\t\t\tappName: app.id,\n\t\t\t\thostname: args.hostname,\n\t\t\t},\n\t\t\t{ parent: this },\n\t\t);\n\n\t\tthis.id = pulumi.output(args.hostname);\n\t\tthis.configured = resource.configured;\n\t\tthis.dnsRequirements = resource.dnsRequirements;\n\n\t\tthis.registerOutputs({\n\t\t\tid: this.id,\n\t\t\tconfigured: this.configured,\n\t\t\tdnsRequirements: this.dnsRequirements,\n\t\t});\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;AAuDA,IAAa,iCAAb,MAEA;CACC,MAAM,OACL,QACuC;EACvC,MAAM,SAAS,IAAI,UAAU,OAAO,KAAK;EACzC,MAAM,OAAO,YAAY,OAAO,QAAQ,gBAAgB,mBAAmB,OAAO,QAAQ;EAE1F,IAAI,OAAO,MAAM,OAAO,OAA+B,IAAI;EAE3D,IAAI,MACH,OAAO,IAAI,KAAK,sCAAsC,OAAO,SAAS,EAAE;OAExE,OAAO,MAAM,OAAO,KACnB,YAAY,OAAO,QAAQ,qBAC3B,EAAE,UAAU,OAAO,SAAS,CAC7B;EAGD,MAAM,OAA8B;GACnC,GAAG;GACH,YAAY,KAAK,cAAc;GAC/B,iBAAiB,KAAK,oBAAoB,CAAC;EAC5C;EAEA,OAAO;GAAE,IAAI,OAAO;GAAU;EAAK;CACpC;CAEA,MAAM,KACL,IACA,OACqC;EAGrC,MAAM,OAAO,MAAM,IAFA,UAAU,MAAM,KAEX,EAAE,OACzB,YAAY,MAAM,QAAQ,gBAAgB,mBAAmB,EAAE,GAChE;EAEA,IAAI,CAAC,MAEJ,OAAO,CAAC;EAGT,OAAO;GACN;GACA,OAAO;IACN,GAAG;IACH,YAAY,KAAK,cAAc;IAC/B,iBAAiB,KAAK,oBAAoB,CAAC;GAC5C;EACD;CACD;CAEA,MAAM,OACL,KACA,OACA,MACuC;EAEvC,OAAO,EACN,MAAM;GAAE,GAAG;GAAM,YAAY;GAAO,iBAAiB,CAAC;EAAE,EACzD;CACD;CAEA,MAAM,OAAO,IAAY,OAA6C;EACrE,MAAM,SAAS,IAAI,UAAU,MAAM,KAAK;EAExC,IAAI;GACH,MAAM,OAAO,OACZ,YAAY,MAAM,QAAQ,gBAAgB,mBAAmB,EAAE,GAChE;EACD,SAAS,OAAO;GAEf,IAAI,iBAAiB,kBAAkB;IACtC,OAAO,IAAI,KAAK,oBAAoB,GAAG,kBAAkB;IAEzD;GACD;GAEA,MAAM;EACP;CACD;CAEA,MAAM,KACL,KACA,MACA,MACqC;EACrC,MAAM,WAAqB,CAAC;EAE5B,IAAI,KAAK,YAAY,KAAK,SACzB,SAAS,KAAK,SAAS;EAGxB,IAAI,KAAK,aAAa,KAAK,UAC1B,SAAS,KAAK,UAAU;EAGzB,OAAO;GACN,SAAS,SAAS,SAAS;GAC3B;GACA,qBAAqB;EACtB;CACD;AACD;;AAGA,IAAM,yBAAN,cAAqC,OAAO,QAAQ,SAAS;CAI5D,YACC,MACA,MAKA,MACC;EACD,MACC,IAAI,+BAA+B,GACnC,MACA;GAAE,GAAG;GAAM,YAAY;GAAW,iBAAiB;EAAU,GAE7D;GAAE,GAAG;GAAM,yBAAyB,CAAC,OAAO;EAAE,CAC/C;CACD;AACD;;;;;;;;;;;;;;AAiCA,IAAa,iBAAb,cAAoC,OAAO,kBAAkB;CAU5D,YACC,MACA,MACA,MACC;EACD,MAAM,EAAE,UAAU,KAAK,GAAG,eAAe;EAEzC,MAAM,8BAA8B,MAAM,CAAC,GAAG,UAAU;EAExD,MAAM,WAAW,IAAI,uBACpB,GAAG,KAAK,YACR;GACC,OAAO,SAAS;GAChB,SAAS,IAAI;GACb,UAAU,KAAK;EAChB,GACA,EAAE,QAAQ,KAAK,CAChB;EAEA,KAAK,KAAK,OAAO,OAAO,KAAK,QAAQ;EACrC,KAAK,aAAa,SAAS;EAC3B,KAAK,kBAAkB,SAAS;EAEhC,KAAK,gBAAgB;GACpB,IAAI,KAAK;GACT,YAAY,KAAK;GACjB,iBAAiB,KAAK;EACvB,CAAC;CACF;AACD"}
@@ -9,6 +9,10 @@ _pulumi_pulumi = require_chunk.__toESM(_pulumi_pulumi, 1);
9
9
  /**
10
10
  * Deploys a Fly app via `fly deploy --remote-only` from a generated fly.toml.
11
11
  * Isolation/git are the seam's job (list a `DeploySandbox`, optionally a `GitGuard`).
12
+ *
13
+ * Recommended preflight: `assertHostBinaries(["fly"])` (from
14
+ * `@infracraft/pulumi/sandbox`) at program start, so a missing CLI fails fast
15
+ * with an install hint instead of mid-deploy.
12
16
  */
13
17
  var FlyDeploy = class extends _pulumi_pulumi.ComponentResource {
14
18
  constructor(name, args, opts) {
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.cjs","names":["pulumi","generateFlyToml","dependsOnList","createDeployCommand"],"sources":["../../src/fly/deploy.ts"],"sourcesContent":["// src/fly/deploy.ts (replace entire file)\nimport * as pulumi from \"@pulumi/pulumi\";\n\nimport { createDeployCommand, dependsOnList } from \"../commands/deploy\";\nimport type { FlyApp } from \"./app\";\nimport type { FlyProvider } from \"./provider\";\nimport { type FlyTomlConfig, generateFlyToml } from \"./toml\";\n\ntype FlyDeployOptions = Omit<pulumi.ComponentResourceOptions, \"provider\"> & {\n\tprovider: FlyProvider;\n\tapp: FlyApp;\n};\n\nexport interface FlyDeployArgs {\n\t/** fly.toml configuration. `config.app` must equal the FlyApp name. */\n\tconfig: FlyTomlConfig;\n\t/** Redeploy triggers; the generated toml content is appended automatically. */\n\ttriggers: pulumi.Input<pulumi.Input<string>[]>;\n\t/** `fly deploy --wait-timeout` seconds (default 300). */\n\twaitTimeout?: number;\n\t/** `fly deploy --release-command-timeout` seconds (default 600). */\n\treleaseCommandTimeout?: number;\n\t/** `fly deploy --ha` (default false). */\n\thighAvailability?: boolean;\n}\n\n/**\n * Deploys a Fly app via `fly deploy --remote-only` from a generated fly.toml.\n * Isolation/git are the seam's job (list a `DeploySandbox`, optionally a `GitGuard`).\n */\nexport class FlyDeploy extends pulumi.ComponentResource {\n\t/** The deploy CLI's final stdout line (the Fly app URL when emitted). */\n\tpublic readonly deploymentUrl: pulumi.Output<string>;\n\n\tconstructor(name: string, args: FlyDeployArgs, opts: FlyDeployOptions) {\n\t\tconst { provider, app, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:fly:Deploy\", name, {}, pulumiOpts);\n\n\t\tconst tomlContent = generateFlyToml(args.config);\n\t\tconst configPath = `.fly/${args.config.app}.toml`;\n\n\t\tconst waitTimeout = args.waitTimeout ?? 300;\n\t\tconst releaseCommandTimeout = args.releaseCommandTimeout ?? 600;\n\t\tconst highAvailability = args.highAvailability ?? false;\n\n\t\t// The toml content arrives via FLY_TOML_CONTENT (avoids shell escaping).\n\t\tconst setup = `mkdir -p .fly && printf '%s' \"$FLY_TOML_CONTENT\" > ${configPath}`;\n\t\tconst cli = `fly deploy --config ${configPath} --remote-only --ha=${highAvailability} --wait-timeout ${waitTimeout} --release-command-timeout ${releaseCommandTimeout}`;\n\n\t\tconst triggers = pulumi\n\t\t\t.output(args.triggers)\n\t\t\t.apply((values) => [...values, tomlContent]);\n\n\t\t// Keep the `app` ordering anchor first; append the consumer's deps\n\t\t// (DeploySandbox / GitGuard) using the seam's shared normaliser.\n\t\tconst consumerDeps = dependsOnList(pulumiOpts) as pulumi.Resource[];\n\n\t\tconst { deploymentUrl } = createDeployCommand(\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tcli,\n\t\t\t\ttriggers,\n\t\t\t\tsetup,\n\t\t\t\tenvironment: {\n\t\t\t\t\tFLY_API_TOKEN: provider.token,\n\t\t\t\t\tFLY_TOML_CONTENT: tomlContent,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{ ...pulumiOpts, parent: this, dependsOn: [app, ...consumerDeps] },\n\t\t);\n\n\t\tthis.deploymentUrl = deploymentUrl;\n\n\t\tthis.registerOutputs({ deploymentUrl: this.deploymentUrl });\n\t}\n}\n"],"mappings":";;;;;;;;;;;;AA8BA,IAAa,YAAb,cAA+BA,eAAO,kBAAkB;CAIvD,YAAY,MAAc,MAAqB,MAAwB;EACtE,MAAM,EAAE,UAAU,KAAK,GAAG,eAAe;EAEzC,MAAM,yBAAyB,MAAM,CAAC,GAAG,UAAU;EAEnD,MAAM,cAAcC,iCAAgB,KAAK,MAAM;EAC/C,MAAM,aAAa,QAAQ,KAAK,OAAO,IAAI;EAE3C,MAAM,cAAc,KAAK,eAAe;EACxC,MAAM,wBAAwB,KAAK,yBAAyB;EAC5D,MAAM,mBAAmB,KAAK,oBAAoB;EAGlD,MAAM,QAAQ,sDAAsD;EACpE,MAAM,MAAM,uBAAuB,WAAW,sBAAsB,iBAAiB,kBAAkB,YAAY,6BAA6B;EAEhJ,MAAM,WAAWD,eACf,OAAO,KAAK,QAAQ,EACpB,OAAO,WAAW,CAAC,GAAG,QAAQ,WAAW,CAAC;EAI5C,MAAM,eAAeE,sCAAc,UAAU;EAE7C,MAAM,EAAE,kBAAkBC,4CACzB;GACC;GACA;GACA;GACA;GACA,aAAa;IACZ,eAAe,SAAS;IACxB,kBAAkB;GACnB;EACD,GACA;GAAE,GAAG;GAAY,QAAQ;GAAM,WAAW,CAAC,KAAK,GAAG,YAAY;EAAE,CAClE;EAEA,KAAK,gBAAgB;EAErB,KAAK,gBAAgB,EAAE,eAAe,KAAK,cAAc,CAAC;CAC3D;AACD"}
1
+ {"version":3,"file":"deploy.cjs","names":["pulumi","generateFlyToml","dependsOnList","createDeployCommand"],"sources":["../../src/fly/deploy.ts"],"sourcesContent":["// src/fly/deploy.ts (replace entire file)\nimport * as pulumi from \"@pulumi/pulumi\";\n\nimport { createDeployCommand, dependsOnList } from \"../commands/deploy\";\nimport type { FlyApp } from \"./app\";\nimport type { FlyProvider } from \"./provider\";\nimport { type FlyTomlConfig, generateFlyToml } from \"./toml\";\n\ntype FlyDeployOptions = Omit<pulumi.ComponentResourceOptions, \"provider\"> & {\n\tprovider: FlyProvider;\n\tapp: FlyApp;\n};\n\nexport interface FlyDeployArgs {\n\t/** fly.toml configuration. `config.app` must equal the FlyApp name. */\n\tconfig: FlyTomlConfig;\n\t/** Redeploy triggers; the generated toml content is appended automatically. */\n\ttriggers: pulumi.Input<pulumi.Input<string>[]>;\n\t/** `fly deploy --wait-timeout` seconds (default 300). */\n\twaitTimeout?: number;\n\t/** `fly deploy --release-command-timeout` seconds (default 600). */\n\treleaseCommandTimeout?: number;\n\t/** `fly deploy --ha` (default false). */\n\thighAvailability?: boolean;\n}\n\n/**\n * Deploys a Fly app via `fly deploy --remote-only` from a generated fly.toml.\n * Isolation/git are the seam's job (list a `DeploySandbox`, optionally a `GitGuard`).\n *\n * Recommended preflight: `assertHostBinaries([\"fly\"])` (from\n * `@infracraft/pulumi/sandbox`) at program start, so a missing CLI fails fast\n * with an install hint instead of mid-deploy.\n */\nexport class FlyDeploy extends pulumi.ComponentResource {\n\t/** The deploy CLI's final stdout line (the Fly app URL when emitted). */\n\tpublic readonly deploymentUrl: pulumi.Output<string>;\n\n\tconstructor(name: string, args: FlyDeployArgs, opts: FlyDeployOptions) {\n\t\tconst { provider, app, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:fly:Deploy\", name, {}, pulumiOpts);\n\n\t\tconst tomlContent = generateFlyToml(args.config);\n\t\tconst configPath = `.fly/${args.config.app}.toml`;\n\n\t\tconst waitTimeout = args.waitTimeout ?? 300;\n\t\tconst releaseCommandTimeout = args.releaseCommandTimeout ?? 600;\n\t\tconst highAvailability = args.highAvailability ?? false;\n\n\t\t// The toml content arrives via FLY_TOML_CONTENT (avoids shell escaping).\n\t\tconst setup = `mkdir -p .fly && printf '%s' \"$FLY_TOML_CONTENT\" > ${configPath}`;\n\t\tconst cli = `fly deploy --config ${configPath} --remote-only --ha=${highAvailability} --wait-timeout ${waitTimeout} --release-command-timeout ${releaseCommandTimeout}`;\n\n\t\tconst triggers = pulumi\n\t\t\t.output(args.triggers)\n\t\t\t.apply((values) => [...values, tomlContent]);\n\n\t\t// Keep the `app` ordering anchor first; append the consumer's deps\n\t\t// (DeploySandbox / GitGuard) using the seam's shared normaliser.\n\t\tconst consumerDeps = dependsOnList(pulumiOpts) as pulumi.Resource[];\n\n\t\tconst { deploymentUrl } = createDeployCommand(\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tcli,\n\t\t\t\ttriggers,\n\t\t\t\tsetup,\n\t\t\t\tenvironment: {\n\t\t\t\t\tFLY_API_TOKEN: provider.token,\n\t\t\t\t\tFLY_TOML_CONTENT: tomlContent,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{ ...pulumiOpts, parent: this, dependsOn: [app, ...consumerDeps] },\n\t\t);\n\n\t\tthis.deploymentUrl = deploymentUrl;\n\n\t\tthis.registerOutputs({ deploymentUrl: this.deploymentUrl });\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAkCA,IAAa,YAAb,cAA+BA,eAAO,kBAAkB;CAIvD,YAAY,MAAc,MAAqB,MAAwB;EACtE,MAAM,EAAE,UAAU,KAAK,GAAG,eAAe;EAEzC,MAAM,yBAAyB,MAAM,CAAC,GAAG,UAAU;EAEnD,MAAM,cAAcC,iCAAgB,KAAK,MAAM;EAC/C,MAAM,aAAa,QAAQ,KAAK,OAAO,IAAI;EAE3C,MAAM,cAAc,KAAK,eAAe;EACxC,MAAM,wBAAwB,KAAK,yBAAyB;EAC5D,MAAM,mBAAmB,KAAK,oBAAoB;EAGlD,MAAM,QAAQ,sDAAsD;EACpE,MAAM,MAAM,uBAAuB,WAAW,sBAAsB,iBAAiB,kBAAkB,YAAY,6BAA6B;EAEhJ,MAAM,WAAWD,eACf,OAAO,KAAK,QAAQ,EACpB,OAAO,WAAW,CAAC,GAAG,QAAQ,WAAW,CAAC;EAI5C,MAAM,eAAeE,sCAAc,UAAU;EAE7C,MAAM,EAAE,kBAAkBC,4CACzB;GACC;GACA;GACA;GACA;GACA,aAAa;IACZ,eAAe,SAAS;IACxB,kBAAkB;GACnB;EACD,GACA;GAAE,GAAG;GAAY,QAAQ;GAAM,WAAW,CAAC,KAAK,GAAG,YAAY;EAAE,CAClE;EAEA,KAAK,gBAAgB;EAErB,KAAK,gBAAgB,EAAE,eAAe,KAAK,cAAc,CAAC;CAC3D;AACD"}
@@ -24,6 +24,10 @@ interface FlyDeployArgs {
24
24
  /**
25
25
  * Deploys a Fly app via `fly deploy --remote-only` from a generated fly.toml.
26
26
  * Isolation/git are the seam's job (list a `DeploySandbox`, optionally a `GitGuard`).
27
+ *
28
+ * Recommended preflight: `assertHostBinaries(["fly"])` (from
29
+ * `@infracraft/pulumi/sandbox`) at program start, so a missing CLI fails fast
30
+ * with an install hint instead of mid-deploy.
27
31
  */
28
32
  declare class FlyDeploy extends pulumi.ComponentResource {
29
33
  /** The deploy CLI's final stdout line (the Fly app URL when emitted). */
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.d.cts","names":[],"sources":["../../src/fly/deploy.ts"],"mappings":";;;;;;;KAQK,gBAAA,GAAmB,IAAA,CAAK,MAAA,CAAO,wBAAA;EACnC,QAAA,EAAU,WAAA;EACV,GAAA,EAAK,MAAA;AAAA;AAAA,UAGW,aAAA;;EAEhB,MAAA,EAAQ,aAAA;EAPe;EASvB,QAAA,EAAU,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,KAAA;EAPzB;EASL,WAAA;EATW;EAWX,qBAAA;EAb4B;EAe5B,gBAAA;AAAA;;;;;cAOY,SAAA,SAAkB,MAAA,CAAO,iBAAA;EAjBrB;EAAA,SAmBA,aAAA,EAAe,MAAA,CAAO,MAAA;cAE1B,IAAA,UAAc,IAAA,EAAM,aAAA,EAAe,IAAA,EAAM,gBAAA;AAAA"}
1
+ {"version":3,"file":"deploy.d.cts","names":[],"sources":["../../src/fly/deploy.ts"],"mappings":";;;;;;;KAQK,gBAAA,GAAmB,IAAA,CAAK,MAAA,CAAO,wBAAA;EACnC,QAAA,EAAU,WAAA;EACV,GAAA,EAAK,MAAA;AAAA;AAAA,UAGW,aAAA;;EAEhB,MAAA,EAAQ,aAAA;EAPe;EASvB,QAAA,EAAU,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,KAAA;EAPzB;EASL,WAAA;EATW;EAWX,qBAAA;EAb4B;EAe5B,gBAAA;AAAA;;;;;AAbW;AAGZ;;;cAqBa,SAAA,SAAkB,MAAA,CAAO,iBAAA;EAjBd;EAAA,SAmBP,aAAA,EAAe,MAAA,CAAO,MAAA;cAE1B,IAAA,UAAc,IAAA,EAAM,aAAA,EAAe,IAAA,EAAM,gBAAA;AAAA"}
@@ -24,6 +24,10 @@ interface FlyDeployArgs {
24
24
  /**
25
25
  * Deploys a Fly app via `fly deploy --remote-only` from a generated fly.toml.
26
26
  * Isolation/git are the seam's job (list a `DeploySandbox`, optionally a `GitGuard`).
27
+ *
28
+ * Recommended preflight: `assertHostBinaries(["fly"])` (from
29
+ * `@infracraft/pulumi/sandbox`) at program start, so a missing CLI fails fast
30
+ * with an install hint instead of mid-deploy.
27
31
  */
28
32
  declare class FlyDeploy extends pulumi.ComponentResource {
29
33
  /** The deploy CLI's final stdout line (the Fly app URL when emitted). */
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.d.mts","names":[],"sources":["../../src/fly/deploy.ts"],"mappings":";;;;;;;KAQK,gBAAA,GAAmB,IAAA,CAAK,MAAA,CAAO,wBAAA;EACnC,QAAA,EAAU,WAAA;EACV,GAAA,EAAK,MAAA;AAAA;AAAA,UAGW,aAAA;;EAEhB,MAAA,EAAQ,aAAA;EAPe;EASvB,QAAA,EAAU,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,KAAA;EAPzB;EASL,WAAA;EATW;EAWX,qBAAA;EAb4B;EAe5B,gBAAA;AAAA;;;;;cAOY,SAAA,SAAkB,MAAA,CAAO,iBAAA;EAjBrB;EAAA,SAmBA,aAAA,EAAe,MAAA,CAAO,MAAA;cAE1B,IAAA,UAAc,IAAA,EAAM,aAAA,EAAe,IAAA,EAAM,gBAAA;AAAA"}
1
+ {"version":3,"file":"deploy.d.mts","names":[],"sources":["../../src/fly/deploy.ts"],"mappings":";;;;;;;KAQK,gBAAA,GAAmB,IAAA,CAAK,MAAA,CAAO,wBAAA;EACnC,QAAA,EAAU,WAAA;EACV,GAAA,EAAK,MAAA;AAAA;AAAA,UAGW,aAAA;;EAEhB,MAAA,EAAQ,aAAA;EAPe;EASvB,QAAA,EAAU,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,KAAA;EAPzB;EASL,WAAA;EATW;EAWX,qBAAA;EAb4B;EAe5B,gBAAA;AAAA;;;;;AAbW;AAGZ;;;cAqBa,SAAA,SAAkB,MAAA,CAAO,iBAAA;EAjBd;EAAA,SAmBP,aAAA,EAAe,MAAA,CAAO,MAAA;cAE1B,IAAA,UAAc,IAAA,EAAM,aAAA,EAAe,IAAA,EAAM,gBAAA;AAAA"}
@@ -7,6 +7,10 @@ import * as pulumi from "@pulumi/pulumi";
7
7
  /**
8
8
  * Deploys a Fly app via `fly deploy --remote-only` from a generated fly.toml.
9
9
  * Isolation/git are the seam's job (list a `DeploySandbox`, optionally a `GitGuard`).
10
+ *
11
+ * Recommended preflight: `assertHostBinaries(["fly"])` (from
12
+ * `@infracraft/pulumi/sandbox`) at program start, so a missing CLI fails fast
13
+ * with an install hint instead of mid-deploy.
10
14
  */
11
15
  var FlyDeploy = class extends pulumi.ComponentResource {
12
16
  constructor(name, args, opts) {
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.mjs","names":[],"sources":["../../src/fly/deploy.ts"],"sourcesContent":["// src/fly/deploy.ts (replace entire file)\nimport * as pulumi from \"@pulumi/pulumi\";\n\nimport { createDeployCommand, dependsOnList } from \"../commands/deploy\";\nimport type { FlyApp } from \"./app\";\nimport type { FlyProvider } from \"./provider\";\nimport { type FlyTomlConfig, generateFlyToml } from \"./toml\";\n\ntype FlyDeployOptions = Omit<pulumi.ComponentResourceOptions, \"provider\"> & {\n\tprovider: FlyProvider;\n\tapp: FlyApp;\n};\n\nexport interface FlyDeployArgs {\n\t/** fly.toml configuration. `config.app` must equal the FlyApp name. */\n\tconfig: FlyTomlConfig;\n\t/** Redeploy triggers; the generated toml content is appended automatically. */\n\ttriggers: pulumi.Input<pulumi.Input<string>[]>;\n\t/** `fly deploy --wait-timeout` seconds (default 300). */\n\twaitTimeout?: number;\n\t/** `fly deploy --release-command-timeout` seconds (default 600). */\n\treleaseCommandTimeout?: number;\n\t/** `fly deploy --ha` (default false). */\n\thighAvailability?: boolean;\n}\n\n/**\n * Deploys a Fly app via `fly deploy --remote-only` from a generated fly.toml.\n * Isolation/git are the seam's job (list a `DeploySandbox`, optionally a `GitGuard`).\n */\nexport class FlyDeploy extends pulumi.ComponentResource {\n\t/** The deploy CLI's final stdout line (the Fly app URL when emitted). */\n\tpublic readonly deploymentUrl: pulumi.Output<string>;\n\n\tconstructor(name: string, args: FlyDeployArgs, opts: FlyDeployOptions) {\n\t\tconst { provider, app, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:fly:Deploy\", name, {}, pulumiOpts);\n\n\t\tconst tomlContent = generateFlyToml(args.config);\n\t\tconst configPath = `.fly/${args.config.app}.toml`;\n\n\t\tconst waitTimeout = args.waitTimeout ?? 300;\n\t\tconst releaseCommandTimeout = args.releaseCommandTimeout ?? 600;\n\t\tconst highAvailability = args.highAvailability ?? false;\n\n\t\t// The toml content arrives via FLY_TOML_CONTENT (avoids shell escaping).\n\t\tconst setup = `mkdir -p .fly && printf '%s' \"$FLY_TOML_CONTENT\" > ${configPath}`;\n\t\tconst cli = `fly deploy --config ${configPath} --remote-only --ha=${highAvailability} --wait-timeout ${waitTimeout} --release-command-timeout ${releaseCommandTimeout}`;\n\n\t\tconst triggers = pulumi\n\t\t\t.output(args.triggers)\n\t\t\t.apply((values) => [...values, tomlContent]);\n\n\t\t// Keep the `app` ordering anchor first; append the consumer's deps\n\t\t// (DeploySandbox / GitGuard) using the seam's shared normaliser.\n\t\tconst consumerDeps = dependsOnList(pulumiOpts) as pulumi.Resource[];\n\n\t\tconst { deploymentUrl } = createDeployCommand(\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tcli,\n\t\t\t\ttriggers,\n\t\t\t\tsetup,\n\t\t\t\tenvironment: {\n\t\t\t\t\tFLY_API_TOKEN: provider.token,\n\t\t\t\t\tFLY_TOML_CONTENT: tomlContent,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{ ...pulumiOpts, parent: this, dependsOn: [app, ...consumerDeps] },\n\t\t);\n\n\t\tthis.deploymentUrl = deploymentUrl;\n\n\t\tthis.registerOutputs({ deploymentUrl: this.deploymentUrl });\n\t}\n}\n"],"mappings":";;;;;;;;;;AA8BA,IAAa,YAAb,cAA+B,OAAO,kBAAkB;CAIvD,YAAY,MAAc,MAAqB,MAAwB;EACtE,MAAM,EAAE,UAAU,KAAK,GAAG,eAAe;EAEzC,MAAM,yBAAyB,MAAM,CAAC,GAAG,UAAU;EAEnD,MAAM,cAAc,gBAAgB,KAAK,MAAM;EAC/C,MAAM,aAAa,QAAQ,KAAK,OAAO,IAAI;EAE3C,MAAM,cAAc,KAAK,eAAe;EACxC,MAAM,wBAAwB,KAAK,yBAAyB;EAC5D,MAAM,mBAAmB,KAAK,oBAAoB;EAGlD,MAAM,QAAQ,sDAAsD;EACpE,MAAM,MAAM,uBAAuB,WAAW,sBAAsB,iBAAiB,kBAAkB,YAAY,6BAA6B;EAEhJ,MAAM,WAAW,OACf,OAAO,KAAK,QAAQ,EACpB,OAAO,WAAW,CAAC,GAAG,QAAQ,WAAW,CAAC;EAI5C,MAAM,eAAe,cAAc,UAAU;EAE7C,MAAM,EAAE,kBAAkB,oBACzB;GACC;GACA;GACA;GACA;GACA,aAAa;IACZ,eAAe,SAAS;IACxB,kBAAkB;GACnB;EACD,GACA;GAAE,GAAG;GAAY,QAAQ;GAAM,WAAW,CAAC,KAAK,GAAG,YAAY;EAAE,CAClE;EAEA,KAAK,gBAAgB;EAErB,KAAK,gBAAgB,EAAE,eAAe,KAAK,cAAc,CAAC;CAC3D;AACD"}
1
+ {"version":3,"file":"deploy.mjs","names":[],"sources":["../../src/fly/deploy.ts"],"sourcesContent":["// src/fly/deploy.ts (replace entire file)\nimport * as pulumi from \"@pulumi/pulumi\";\n\nimport { createDeployCommand, dependsOnList } from \"../commands/deploy\";\nimport type { FlyApp } from \"./app\";\nimport type { FlyProvider } from \"./provider\";\nimport { type FlyTomlConfig, generateFlyToml } from \"./toml\";\n\ntype FlyDeployOptions = Omit<pulumi.ComponentResourceOptions, \"provider\"> & {\n\tprovider: FlyProvider;\n\tapp: FlyApp;\n};\n\nexport interface FlyDeployArgs {\n\t/** fly.toml configuration. `config.app` must equal the FlyApp name. */\n\tconfig: FlyTomlConfig;\n\t/** Redeploy triggers; the generated toml content is appended automatically. */\n\ttriggers: pulumi.Input<pulumi.Input<string>[]>;\n\t/** `fly deploy --wait-timeout` seconds (default 300). */\n\twaitTimeout?: number;\n\t/** `fly deploy --release-command-timeout` seconds (default 600). */\n\treleaseCommandTimeout?: number;\n\t/** `fly deploy --ha` (default false). */\n\thighAvailability?: boolean;\n}\n\n/**\n * Deploys a Fly app via `fly deploy --remote-only` from a generated fly.toml.\n * Isolation/git are the seam's job (list a `DeploySandbox`, optionally a `GitGuard`).\n *\n * Recommended preflight: `assertHostBinaries([\"fly\"])` (from\n * `@infracraft/pulumi/sandbox`) at program start, so a missing CLI fails fast\n * with an install hint instead of mid-deploy.\n */\nexport class FlyDeploy extends pulumi.ComponentResource {\n\t/** The deploy CLI's final stdout line (the Fly app URL when emitted). */\n\tpublic readonly deploymentUrl: pulumi.Output<string>;\n\n\tconstructor(name: string, args: FlyDeployArgs, opts: FlyDeployOptions) {\n\t\tconst { provider, app, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:fly:Deploy\", name, {}, pulumiOpts);\n\n\t\tconst tomlContent = generateFlyToml(args.config);\n\t\tconst configPath = `.fly/${args.config.app}.toml`;\n\n\t\tconst waitTimeout = args.waitTimeout ?? 300;\n\t\tconst releaseCommandTimeout = args.releaseCommandTimeout ?? 600;\n\t\tconst highAvailability = args.highAvailability ?? false;\n\n\t\t// The toml content arrives via FLY_TOML_CONTENT (avoids shell escaping).\n\t\tconst setup = `mkdir -p .fly && printf '%s' \"$FLY_TOML_CONTENT\" > ${configPath}`;\n\t\tconst cli = `fly deploy --config ${configPath} --remote-only --ha=${highAvailability} --wait-timeout ${waitTimeout} --release-command-timeout ${releaseCommandTimeout}`;\n\n\t\tconst triggers = pulumi\n\t\t\t.output(args.triggers)\n\t\t\t.apply((values) => [...values, tomlContent]);\n\n\t\t// Keep the `app` ordering anchor first; append the consumer's deps\n\t\t// (DeploySandbox / GitGuard) using the seam's shared normaliser.\n\t\tconst consumerDeps = dependsOnList(pulumiOpts) as pulumi.Resource[];\n\n\t\tconst { deploymentUrl } = createDeployCommand(\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tcli,\n\t\t\t\ttriggers,\n\t\t\t\tsetup,\n\t\t\t\tenvironment: {\n\t\t\t\t\tFLY_API_TOKEN: provider.token,\n\t\t\t\t\tFLY_TOML_CONTENT: tomlContent,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{ ...pulumiOpts, parent: this, dependsOn: [app, ...consumerDeps] },\n\t\t);\n\n\t\tthis.deploymentUrl = deploymentUrl;\n\n\t\tthis.registerOutputs({ deploymentUrl: this.deploymentUrl });\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;AAkCA,IAAa,YAAb,cAA+B,OAAO,kBAAkB;CAIvD,YAAY,MAAc,MAAqB,MAAwB;EACtE,MAAM,EAAE,UAAU,KAAK,GAAG,eAAe;EAEzC,MAAM,yBAAyB,MAAM,CAAC,GAAG,UAAU;EAEnD,MAAM,cAAc,gBAAgB,KAAK,MAAM;EAC/C,MAAM,aAAa,QAAQ,KAAK,OAAO,IAAI;EAE3C,MAAM,cAAc,KAAK,eAAe;EACxC,MAAM,wBAAwB,KAAK,yBAAyB;EAC5D,MAAM,mBAAmB,KAAK,oBAAoB;EAGlD,MAAM,QAAQ,sDAAsD;EACpE,MAAM,MAAM,uBAAuB,WAAW,sBAAsB,iBAAiB,kBAAkB,YAAY,6BAA6B;EAEhJ,MAAM,WAAW,OACf,OAAO,KAAK,QAAQ,EACpB,OAAO,WAAW,CAAC,GAAG,QAAQ,WAAW,CAAC;EAI5C,MAAM,eAAe,cAAc,UAAU;EAE7C,MAAM,EAAE,kBAAkB,oBACzB;GACC;GACA;GACA;GACA;GACA,aAAa;IACZ,eAAe,SAAS;IACxB,kBAAkB;GACnB;EACD,GACA;GAAE,GAAG;GAAY,QAAQ;GAAM,WAAW,CAAC,KAAK,GAAG,YAAY;EAAE,CAClE;EAEA,KAAK,gBAAgB;EAErB,KAAK,gBAAgB,EAAE,eAAe,KAAK,cAAc,CAAC;CAC3D;AACD"}
package/dist/fly/ip.cjs CHANGED
@@ -44,6 +44,8 @@ const RELEASE_IP = `
44
44
  * API. `create()` queries existing IPs and adopts a matching one, otherwise it
45
45
  * allocates. `shared_v4` allocations return a null `ipAddress` in the payload —
46
46
  * the address is read from `app.sharedIpAddress`.
47
+ *
48
+ * @internal Exported only for unit testing; not part of the public API surface.
47
49
  */
48
50
  var FlyIpResourceProvider = class {
49
51
  async create(inputs) {
@@ -160,5 +162,6 @@ var FlyIp = class extends _pulumi_pulumi.ComponentResource {
160
162
 
161
163
  //#endregion
162
164
  exports.FlyIp = FlyIp;
165
+ exports.FlyIpResourceProvider = FlyIpResourceProvider;
163
166
  exports.FlyIpType = FlyIpType;
164
167
  //# sourceMappingURL=ip.cjs.map