@infracraft/pulumi 1.2.0 → 1.5.1

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 (191) hide show
  1. package/dist/fly/app.cjs +102 -0
  2. package/dist/fly/app.cjs.map +1 -0
  3. package/dist/fly/app.d.cts +44 -0
  4. package/dist/fly/app.d.cts.map +1 -0
  5. package/dist/fly/app.d.mts +44 -0
  6. package/dist/fly/app.d.mts.map +1 -0
  7. package/dist/fly/app.mjs +100 -0
  8. package/dist/fly/app.mjs.map +1 -0
  9. package/dist/fly/certificate.cjs +109 -0
  10. package/dist/fly/certificate.cjs.map +1 -0
  11. package/dist/fly/certificate.d.cts +65 -0
  12. package/dist/fly/certificate.d.cts.map +1 -0
  13. package/dist/fly/certificate.d.mts +65 -0
  14. package/dist/fly/certificate.d.mts.map +1 -0
  15. package/dist/fly/certificate.mjs +107 -0
  16. package/dist/fly/certificate.mjs.map +1 -0
  17. package/dist/fly/client.cjs +103 -0
  18. package/dist/fly/client.cjs.map +1 -0
  19. package/dist/fly/client.d.cts +54 -0
  20. package/dist/fly/client.d.cts.map +1 -0
  21. package/dist/fly/client.d.mts +54 -0
  22. package/dist/fly/client.d.mts.map +1 -0
  23. package/dist/fly/client.mjs +102 -0
  24. package/dist/fly/client.mjs.map +1 -0
  25. package/dist/fly/deploy.cjs +59 -0
  26. package/dist/fly/deploy.cjs.map +1 -0
  27. package/dist/fly/deploy.d.cts +59 -0
  28. package/dist/fly/deploy.d.cts.map +1 -0
  29. package/dist/fly/deploy.d.mts +59 -0
  30. package/dist/fly/deploy.d.mts.map +1 -0
  31. package/dist/fly/deploy.mjs +56 -0
  32. package/dist/fly/deploy.mjs.map +1 -0
  33. package/dist/fly/index.cjs +31 -0
  34. package/dist/fly/index.d.cts +10 -0
  35. package/dist/fly/index.d.mts +10 -0
  36. package/dist/fly/index.mjs +11 -0
  37. package/dist/fly/ip.cjs +153 -0
  38. package/dist/fly/ip.cjs.map +1 -0
  39. package/dist/fly/ip.d.cts +55 -0
  40. package/dist/fly/ip.d.cts.map +1 -0
  41. package/dist/fly/ip.d.mts +55 -0
  42. package/dist/fly/ip.d.mts.map +1 -0
  43. package/dist/fly/ip.mjs +150 -0
  44. package/dist/fly/ip.mjs.map +1 -0
  45. package/dist/fly/provider.cjs +33 -0
  46. package/dist/fly/provider.cjs.map +1 -0
  47. package/dist/fly/provider.d.cts +36 -0
  48. package/dist/fly/provider.d.cts.map +1 -0
  49. package/dist/fly/provider.d.mts +36 -0
  50. package/dist/fly/provider.d.mts.map +1 -0
  51. package/dist/fly/provider.mjs +31 -0
  52. package/dist/fly/provider.mjs.map +1 -0
  53. package/dist/fly/secret.cjs +109 -0
  54. package/dist/fly/secret.cjs.map +1 -0
  55. package/dist/fly/secret.d.cts +46 -0
  56. package/dist/fly/secret.d.cts.map +1 -0
  57. package/dist/fly/secret.d.mts +46 -0
  58. package/dist/fly/secret.d.mts.map +1 -0
  59. package/dist/fly/secret.mjs +107 -0
  60. package/dist/fly/secret.mjs.map +1 -0
  61. package/dist/fly/toml.cjs +248 -0
  62. package/dist/fly/toml.cjs.map +1 -0
  63. package/dist/fly/toml.d.cts +214 -0
  64. package/dist/fly/toml.d.cts.map +1 -0
  65. package/dist/fly/toml.d.mts +214 -0
  66. package/dist/fly/toml.d.mts.map +1 -0
  67. package/dist/fly/toml.mjs +237 -0
  68. package/dist/fly/toml.mjs.map +1 -0
  69. package/dist/fly/volume.cjs +111 -0
  70. package/dist/fly/volume.cjs.map +1 -0
  71. package/dist/fly/volume.d.cts +53 -0
  72. package/dist/fly/volume.d.cts.map +1 -0
  73. package/dist/fly/volume.d.mts +53 -0
  74. package/dist/fly/volume.d.mts.map +1 -0
  75. package/dist/fly/volume.mjs +109 -0
  76. package/dist/fly/volume.mjs.map +1 -0
  77. package/dist/git-guard.cjs +4 -2
  78. package/dist/git-guard.cjs.map +1 -1
  79. package/dist/git-guard.d.cts.map +1 -1
  80. package/dist/git-guard.d.mts.map +1 -1
  81. package/dist/git-guard.mjs +4 -2
  82. package/dist/git-guard.mjs.map +1 -1
  83. package/dist/neon/branch.cjs.map +1 -1
  84. package/dist/neon/branch.d.cts.map +1 -1
  85. package/dist/neon/branch.d.mts.map +1 -1
  86. package/dist/neon/branch.mjs.map +1 -1
  87. package/dist/neon/database.cjs.map +1 -1
  88. package/dist/neon/database.d.cts.map +1 -1
  89. package/dist/neon/database.d.mts.map +1 -1
  90. package/dist/neon/database.mjs.map +1 -1
  91. package/dist/neon/endpoint.cjs.map +1 -1
  92. package/dist/neon/endpoint.d.cts.map +1 -1
  93. package/dist/neon/endpoint.d.mts.map +1 -1
  94. package/dist/neon/endpoint.mjs.map +1 -1
  95. package/dist/neon/index.cjs +1 -1
  96. package/dist/neon/index.d.cts +2 -2
  97. package/dist/neon/index.d.mts +2 -2
  98. package/dist/neon/index.mjs +1 -1
  99. package/dist/neon/project.cjs.map +1 -1
  100. package/dist/neon/project.d.cts.map +1 -1
  101. package/dist/neon/project.d.mts.map +1 -1
  102. package/dist/neon/project.mjs.map +1 -1
  103. package/dist/neon/provider.cjs.map +1 -1
  104. package/dist/neon/provider.d.cts +9 -5
  105. package/dist/neon/provider.d.cts.map +1 -1
  106. package/dist/neon/provider.d.mts +9 -5
  107. package/dist/neon/provider.d.mts.map +1 -1
  108. package/dist/neon/provider.mjs.map +1 -1
  109. package/dist/neon/role.cjs.map +1 -1
  110. package/dist/neon/role.d.cts.map +1 -1
  111. package/dist/neon/role.d.mts.map +1 -1
  112. package/dist/neon/role.mjs.map +1 -1
  113. package/dist/railway/deploy.cjs +2 -1
  114. package/dist/railway/deploy.cjs.map +1 -1
  115. package/dist/railway/deploy.d.cts +8 -4
  116. package/dist/railway/deploy.d.cts.map +1 -1
  117. package/dist/railway/deploy.d.mts +8 -4
  118. package/dist/railway/deploy.d.mts.map +1 -1
  119. package/dist/railway/deploy.mjs +2 -1
  120. package/dist/railway/deploy.mjs.map +1 -1
  121. package/dist/railway/domain.cjs.map +1 -1
  122. package/dist/railway/domain.mjs.map +1 -1
  123. package/dist/railway/environment.cjs +1 -1
  124. package/dist/railway/environment.cjs.map +1 -1
  125. package/dist/railway/environment.d.cts.map +1 -1
  126. package/dist/railway/environment.d.mts.map +1 -1
  127. package/dist/railway/environment.mjs +1 -1
  128. package/dist/railway/environment.mjs.map +1 -1
  129. package/dist/railway/index.cjs +3 -1
  130. package/dist/railway/index.d.cts +3 -3
  131. package/dist/railway/index.d.mts +3 -3
  132. package/dist/railway/index.mjs +3 -3
  133. package/dist/railway/project.cjs.map +1 -1
  134. package/dist/railway/project.d.cts.map +1 -1
  135. package/dist/railway/project.d.mts.map +1 -1
  136. package/dist/railway/project.mjs.map +1 -1
  137. package/dist/railway/provider.cjs.map +1 -1
  138. package/dist/railway/provider.d.cts +7 -4
  139. package/dist/railway/provider.d.cts.map +1 -1
  140. package/dist/railway/provider.d.mts +7 -4
  141. package/dist/railway/provider.d.mts.map +1 -1
  142. package/dist/railway/provider.mjs.map +1 -1
  143. package/dist/railway/service.cjs +27 -1
  144. package/dist/railway/service.cjs.map +1 -1
  145. package/dist/railway/service.d.cts +32 -10
  146. package/dist/railway/service.d.cts.map +1 -1
  147. package/dist/railway/service.d.mts +32 -10
  148. package/dist/railway/service.d.mts.map +1 -1
  149. package/dist/railway/service.mjs +26 -2
  150. package/dist/railway/service.mjs.map +1 -1
  151. package/dist/railway/variable.cjs.map +1 -1
  152. package/dist/railway/variable.mjs.map +1 -1
  153. package/dist/railway/volume.cjs.map +1 -1
  154. package/dist/railway/volume.mjs.map +1 -1
  155. package/dist/stable-dir.cjs +41 -0
  156. package/dist/stable-dir.cjs.map +1 -0
  157. package/dist/stable-dir.d.cts +34 -0
  158. package/dist/stable-dir.d.cts.map +1 -0
  159. package/dist/stable-dir.d.mts +34 -0
  160. package/dist/stable-dir.d.mts.map +1 -0
  161. package/dist/stable-dir.mjs +39 -0
  162. package/dist/stable-dir.mjs.map +1 -0
  163. package/dist/vercel/deploy.cjs +2 -1
  164. package/dist/vercel/deploy.cjs.map +1 -1
  165. package/dist/vercel/deploy.d.cts +5 -1
  166. package/dist/vercel/deploy.d.cts.map +1 -1
  167. package/dist/vercel/deploy.d.mts +5 -1
  168. package/dist/vercel/deploy.d.mts.map +1 -1
  169. package/dist/vercel/deploy.mjs +2 -1
  170. package/dist/vercel/deploy.mjs.map +1 -1
  171. package/dist/vercel/index.cjs +2 -1
  172. package/dist/vercel/index.d.cts +3 -3
  173. package/dist/vercel/index.d.mts +3 -3
  174. package/dist/vercel/index.mjs +2 -2
  175. package/dist/vercel/project.cjs +78 -0
  176. package/dist/vercel/project.cjs.map +1 -1
  177. package/dist/vercel/project.d.cts +17 -5
  178. package/dist/vercel/project.d.cts.map +1 -1
  179. package/dist/vercel/project.d.mts +17 -5
  180. package/dist/vercel/project.d.mts.map +1 -1
  181. package/dist/vercel/project.mjs +78 -1
  182. package/dist/vercel/project.mjs.map +1 -1
  183. package/dist/vercel/provider.cjs.map +1 -1
  184. package/dist/vercel/provider.d.cts +9 -5
  185. package/dist/vercel/provider.d.cts.map +1 -1
  186. package/dist/vercel/provider.d.mts +9 -5
  187. package/dist/vercel/provider.d.mts.map +1 -1
  188. package/dist/vercel/provider.mjs.map +1 -1
  189. package/dist/vercel/variable.cjs.map +1 -1
  190. package/dist/vercel/variable.mjs.map +1 -1
  191. package/package.json +8 -2
@@ -0,0 +1,102 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_chunk = require('../chunk-BVYJZCqc.cjs');
3
+ const require_fly_client = require('./client.cjs');
4
+ let _pulumi_pulumi = require("@pulumi/pulumi");
5
+ _pulumi_pulumi = require_chunk.__toESM(_pulumi_pulumi, 1);
6
+
7
+ //#region src/fly/app.ts
8
+ /**
9
+ * Dynamic provider implementing adopt-or-create for Fly apps.
10
+ *
11
+ * `create()` does `GET /v1/apps/{name}`; if found it adopts, otherwise it
12
+ * `POST /v1/apps`. `delete()` is a no-op — deleting a Fly app destroys
13
+ * everything in it, so (like Railway/Neon/Vercel top-level resources) Pulumi
14
+ * does not delete apps.
15
+ */
16
+ var FlyAppResourceProvider = class {
17
+ async create(inputs) {
18
+ const client = new require_fly_client.FlyClient(inputs.token);
19
+ if (await client.tryGet(`/v1/apps/${inputs.name}`)) _pulumi_pulumi.log.info(`Adopting existing Fly app "${inputs.name}"`);
20
+ else {
21
+ if (!inputs.organization) throw new Error(`FlyApp "${inputs.name}": an organization is required to create a new app — set it on FlyProvider or FlyApp args`);
22
+ _pulumi_pulumi.log.info(`Fly app "${inputs.name}" not found — creating...`);
23
+ await client.post("/v1/apps", {
24
+ app_name: inputs.name,
25
+ org_slug: inputs.organization
26
+ });
27
+ }
28
+ const outs = {
29
+ ...inputs,
30
+ appId: inputs.name
31
+ };
32
+ return {
33
+ id: inputs.name,
34
+ outs
35
+ };
36
+ }
37
+ async read(id, props) {
38
+ const app = await new require_fly_client.FlyClient(props.token).tryGet(`/v1/apps/${id}`);
39
+ if (!app) throw new Error(`Fly app "${id}" not found during refresh`);
40
+ return {
41
+ id,
42
+ props: {
43
+ ...props,
44
+ name: app.name,
45
+ appId: app.name
46
+ }
47
+ };
48
+ }
49
+ async update(id, _olds, news) {
50
+ return { outs: {
51
+ ...news,
52
+ appId: id
53
+ } };
54
+ }
55
+ async delete() {
56
+ _pulumi_pulumi.log.warn("Fly app deletion skipped — apps are not deleted by Pulumi (would destroy all contained resources)");
57
+ }
58
+ async diff(_id, olds, news) {
59
+ const replaces = [];
60
+ if (olds.name !== news.name) replaces.push("name");
61
+ if (olds.organization !== news.organization) replaces.push("organization");
62
+ return {
63
+ changes: replaces.length > 0,
64
+ replaces,
65
+ deleteBeforeReplace: true
66
+ };
67
+ }
68
+ };
69
+ /** Internal dynamic resource — not part of the public API. */
70
+ var FlyAppResource = class extends _pulumi_pulumi.dynamic.Resource {
71
+ constructor(name, args, opts) {
72
+ super(new FlyAppResourceProvider(), name, {
73
+ ...args,
74
+ appId: void 0
75
+ }, opts);
76
+ }
77
+ };
78
+ /**
79
+ * Manages a Fly app with adopt-or-create semantics.
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * const app = new FlyApp("api", { name: "rby-api" }, { provider });
84
+ * ```
85
+ */
86
+ var FlyApp = class extends _pulumi_pulumi.ComponentResource {
87
+ constructor(name, args, opts) {
88
+ const { provider, ...pulumiOpts } = opts;
89
+ super("infracraft:fly:App", name, {}, pulumiOpts);
90
+ const resource = new FlyAppResource(`${name}-resource`, {
91
+ token: provider.token,
92
+ name: args.name,
93
+ organization: args.organization ?? provider.organization
94
+ }, { parent: this });
95
+ this.id = resource.appId;
96
+ this.registerOutputs({ id: this.id });
97
+ }
98
+ };
99
+
100
+ //#endregion
101
+ exports.FlyApp = FlyApp;
102
+ //# sourceMappingURL=app.cjs.map
@@ -0,0 +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. */\nexport interface 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 */\nclass FlyAppResourceProvider implements pulumi.dynamic.ResourceProvider {\n\tasync create(inputs: FlyAppInputs): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new FlyClient(inputs.token);\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\tthrow new Error(`Fly app \"${id}\" not found during refresh`);\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\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\topts,\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":";;;;;;;;;;;;;;;AAqCA,IAAM,yBAAN,MAAwE;CACvE,MAAM,OAAO,QAA4D;EACxE,MAAM,SAAS,IAAIA,6BAAU,OAAO,KAAK;EAKzC,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,KACJ,MAAM,IAAI,MAAM,YAAY,GAAG,2BAA2B;EAG3D,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;EAErB,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,GAC5B,IACD;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"}
@@ -0,0 +1,44 @@
1
+ import { t as __name } from "../chunk-OPjESj5l.cjs";
2
+ import { FlyProvider } from "./provider.cjs";
3
+ import * as pulumi from "@pulumi/pulumi";
4
+
5
+ //#region src/fly/app.d.ts
6
+ /** Resolved inputs for the Fly app dynamic provider. */
7
+ interface FlyAppInputs {
8
+ /** Fly API token. */
9
+ token: string;
10
+ /** App name (globally unique). Used as the resource identifier. */
11
+ name: string;
12
+ /** Org slug used only when creating a new app. */
13
+ organization?: string;
14
+ }
15
+ /** Options type for FlyApp — replaces Pulumi's native `provider` field. */
16
+ type FlyAppOptions = Omit<pulumi.ComponentResourceOptions, "provider"> & {
17
+ /** Fly authentication context. */provider: FlyProvider;
18
+ };
19
+ /** Args for FlyApp. */
20
+ interface FlyAppArgs {
21
+ /** App name (globally unique). Used for adoption lookup and as `.id`. */
22
+ name: pulumi.Input<string>;
23
+ /**
24
+ * Org slug for app creation. Overrides `FlyProvider.organization`.
25
+ * Ignored when the app already exists (adoption).
26
+ */
27
+ organization?: pulumi.Input<string>;
28
+ }
29
+ /**
30
+ * Manages a Fly app with adopt-or-create semantics.
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * const app = new FlyApp("api", { name: "rby-api" }, { provider });
35
+ * ```
36
+ */
37
+ declare class FlyApp extends pulumi.ComponentResource {
38
+ /** App identifier (equals the app name). */
39
+ readonly id: pulumi.Output<string>;
40
+ constructor(name: string, args: FlyAppArgs, opts: FlyAppOptions);
41
+ }
42
+ //#endregion
43
+ export { FlyApp, FlyAppArgs, FlyAppInputs };
44
+ //# sourceMappingURL=app.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.cts","names":[],"sources":["../../src/fly/app.ts"],"mappings":";;;;;;UAMiB,YAAA;;EAEhB,KAAA;EAF4B;EAK5B,IAAA;EAL4B;EAQ5B,YAAA;AAAA;;KA6HI,aAAA,GAAgB,IAAA,CAAK,MAAA,CAAO,wBAAA;EA7HpB,kCA+HZ,QAAA,EAAU,WAAA;AAAA;;UAIM,UAAA;EANI;EAQpB,IAAA,EAAM,MAAA,CAAO,KAAA;EANQ;;;;EAYrB,YAAA,GAAe,MAAA,CAAO,KAAK;AAAA;;;AAZN;AAItB;;;;;cAmBa,MAAA,SAAe,MAAA,CAAO,iBAAA;EAjBrB;EAAA,SAmBG,EAAA,EAAI,MAAA,CAAO,MAAA;cAEf,IAAA,UAAc,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM,aAAA;AAAA"}
@@ -0,0 +1,44 @@
1
+ import { t as __name } from "../chunk-OPjESj5l.mjs";
2
+ import { FlyProvider } from "./provider.mjs";
3
+ import * as pulumi from "@pulumi/pulumi";
4
+
5
+ //#region src/fly/app.d.ts
6
+ /** Resolved inputs for the Fly app dynamic provider. */
7
+ interface FlyAppInputs {
8
+ /** Fly API token. */
9
+ token: string;
10
+ /** App name (globally unique). Used as the resource identifier. */
11
+ name: string;
12
+ /** Org slug used only when creating a new app. */
13
+ organization?: string;
14
+ }
15
+ /** Options type for FlyApp — replaces Pulumi's native `provider` field. */
16
+ type FlyAppOptions = Omit<pulumi.ComponentResourceOptions, "provider"> & {
17
+ /** Fly authentication context. */provider: FlyProvider;
18
+ };
19
+ /** Args for FlyApp. */
20
+ interface FlyAppArgs {
21
+ /** App name (globally unique). Used for adoption lookup and as `.id`. */
22
+ name: pulumi.Input<string>;
23
+ /**
24
+ * Org slug for app creation. Overrides `FlyProvider.organization`.
25
+ * Ignored when the app already exists (adoption).
26
+ */
27
+ organization?: pulumi.Input<string>;
28
+ }
29
+ /**
30
+ * Manages a Fly app with adopt-or-create semantics.
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * const app = new FlyApp("api", { name: "rby-api" }, { provider });
35
+ * ```
36
+ */
37
+ declare class FlyApp extends pulumi.ComponentResource {
38
+ /** App identifier (equals the app name). */
39
+ readonly id: pulumi.Output<string>;
40
+ constructor(name: string, args: FlyAppArgs, opts: FlyAppOptions);
41
+ }
42
+ //#endregion
43
+ export { FlyApp, FlyAppArgs, FlyAppInputs };
44
+ //# sourceMappingURL=app.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.mts","names":[],"sources":["../../src/fly/app.ts"],"mappings":";;;;;;UAMiB,YAAA;;EAEhB,KAAA;EAF4B;EAK5B,IAAA;EAL4B;EAQ5B,YAAA;AAAA;;KA6HI,aAAA,GAAgB,IAAA,CAAK,MAAA,CAAO,wBAAA;EA7HpB,kCA+HZ,QAAA,EAAU,WAAA;AAAA;;UAIM,UAAA;EANI;EAQpB,IAAA,EAAM,MAAA,CAAO,KAAA;EANQ;;;;EAYrB,YAAA,GAAe,MAAA,CAAO,KAAK;AAAA;;;AAZN;AAItB;;;;;cAmBa,MAAA,SAAe,MAAA,CAAO,iBAAA;EAjBrB;EAAA,SAmBG,EAAA,EAAI,MAAA,CAAO,MAAA;cAEf,IAAA,UAAc,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM,aAAA;AAAA"}
@@ -0,0 +1,100 @@
1
+ import { t as __name } from "../chunk-OPjESj5l.mjs";
2
+ import { FlyClient } from "./client.mjs";
3
+ import * as pulumi from "@pulumi/pulumi";
4
+
5
+ //#region src/fly/app.ts
6
+ /**
7
+ * Dynamic provider implementing adopt-or-create for Fly apps.
8
+ *
9
+ * `create()` does `GET /v1/apps/{name}`; if found it adopts, otherwise it
10
+ * `POST /v1/apps`. `delete()` is a no-op — deleting a Fly app destroys
11
+ * everything in it, so (like Railway/Neon/Vercel top-level resources) Pulumi
12
+ * does not delete apps.
13
+ */
14
+ var FlyAppResourceProvider = class {
15
+ async create(inputs) {
16
+ const client = new FlyClient(inputs.token);
17
+ if (await client.tryGet(`/v1/apps/${inputs.name}`)) pulumi.log.info(`Adopting existing Fly app "${inputs.name}"`);
18
+ else {
19
+ if (!inputs.organization) throw new Error(`FlyApp "${inputs.name}": an organization is required to create a new app — set it on FlyProvider or FlyApp args`);
20
+ pulumi.log.info(`Fly app "${inputs.name}" not found — creating...`);
21
+ await client.post("/v1/apps", {
22
+ app_name: inputs.name,
23
+ org_slug: inputs.organization
24
+ });
25
+ }
26
+ const outs = {
27
+ ...inputs,
28
+ appId: inputs.name
29
+ };
30
+ return {
31
+ id: inputs.name,
32
+ outs
33
+ };
34
+ }
35
+ async read(id, props) {
36
+ const app = await new FlyClient(props.token).tryGet(`/v1/apps/${id}`);
37
+ if (!app) throw new Error(`Fly app "${id}" not found during refresh`);
38
+ return {
39
+ id,
40
+ props: {
41
+ ...props,
42
+ name: app.name,
43
+ appId: app.name
44
+ }
45
+ };
46
+ }
47
+ async update(id, _olds, news) {
48
+ return { outs: {
49
+ ...news,
50
+ appId: id
51
+ } };
52
+ }
53
+ async delete() {
54
+ pulumi.log.warn("Fly app deletion skipped — apps are not deleted by Pulumi (would destroy all contained resources)");
55
+ }
56
+ async diff(_id, olds, news) {
57
+ const replaces = [];
58
+ if (olds.name !== news.name) replaces.push("name");
59
+ if (olds.organization !== news.organization) replaces.push("organization");
60
+ return {
61
+ changes: replaces.length > 0,
62
+ replaces,
63
+ deleteBeforeReplace: true
64
+ };
65
+ }
66
+ };
67
+ /** Internal dynamic resource — not part of the public API. */
68
+ var FlyAppResource = class extends pulumi.dynamic.Resource {
69
+ constructor(name, args, opts) {
70
+ super(new FlyAppResourceProvider(), name, {
71
+ ...args,
72
+ appId: void 0
73
+ }, opts);
74
+ }
75
+ };
76
+ /**
77
+ * Manages a Fly app with adopt-or-create semantics.
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * const app = new FlyApp("api", { name: "rby-api" }, { provider });
82
+ * ```
83
+ */
84
+ var FlyApp = class extends pulumi.ComponentResource {
85
+ constructor(name, args, opts) {
86
+ const { provider, ...pulumiOpts } = opts;
87
+ super("infracraft:fly:App", name, {}, pulumiOpts);
88
+ const resource = new FlyAppResource(`${name}-resource`, {
89
+ token: provider.token,
90
+ name: args.name,
91
+ organization: args.organization ?? provider.organization
92
+ }, { parent: this });
93
+ this.id = resource.appId;
94
+ this.registerOutputs({ id: this.id });
95
+ }
96
+ };
97
+
98
+ //#endregion
99
+ export { FlyApp };
100
+ //# sourceMappingURL=app.mjs.map
@@ -0,0 +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. */\nexport interface 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 */\nclass FlyAppResourceProvider implements pulumi.dynamic.ResourceProvider {\n\tasync create(inputs: FlyAppInputs): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new FlyClient(inputs.token);\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\tthrow new Error(`Fly app \"${id}\" not found during refresh`);\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\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\topts,\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":";;;;;;;;;;;;;AAqCA,IAAM,yBAAN,MAAwE;CACvE,MAAM,OAAO,QAA4D;EACxE,MAAM,SAAS,IAAI,UAAU,OAAO,KAAK;EAKzC,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,KACJ,MAAM,IAAI,MAAM,YAAY,GAAG,2BAA2B;EAG3D,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;EAErB,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,GAC5B,IACD;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"}
@@ -0,0 +1,109 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_chunk = require('../chunk-BVYJZCqc.cjs');
3
+ const require_fly_client = require('./client.cjs');
4
+ let _pulumi_pulumi = require("@pulumi/pulumi");
5
+ _pulumi_pulumi = require_chunk.__toESM(_pulumi_pulumi, 1);
6
+
7
+ //#region src/fly/certificate.ts
8
+ /**
9
+ * Dynamic provider for Fly ACME (Let's Encrypt) certificates. `create()` checks
10
+ * for an existing cert by hostname and adopts it, otherwise it requests one via
11
+ * `POST /v1/apps/{app}/certificates/acme`. The Machines API returns no `id` —
12
+ * the hostname is the resource key.
13
+ */
14
+ var FlyCertificateResourceProvider = class {
15
+ async create(inputs) {
16
+ const client = new require_fly_client.FlyClient(inputs.token);
17
+ const path = `/v1/apps/${inputs.appName}/certificates/${encodeURIComponent(inputs.hostname)}`;
18
+ let cert = await client.tryGet(path);
19
+ if (cert) _pulumi_pulumi.log.info(`Adopting existing Fly certificate "${inputs.hostname}"`);
20
+ else cert = await client.post(`/v1/apps/${inputs.appName}/certificates/acme`, { hostname: inputs.hostname });
21
+ const outs = {
22
+ ...inputs,
23
+ configured: cert.configured ?? false,
24
+ dnsRequirements: cert.dns_requirements ?? {}
25
+ };
26
+ return {
27
+ id: inputs.hostname,
28
+ outs
29
+ };
30
+ }
31
+ async read(id, props) {
32
+ const cert = await new require_fly_client.FlyClient(props.token).tryGet(`/v1/apps/${props.appName}/certificates/${encodeURIComponent(id)}`);
33
+ if (!cert) throw new Error(`Fly certificate "${id}" not found during refresh`);
34
+ return {
35
+ id,
36
+ props: {
37
+ ...props,
38
+ configured: cert.configured ?? false,
39
+ dnsRequirements: cert.dns_requirements ?? {}
40
+ }
41
+ };
42
+ }
43
+ async update(_id, _olds, news) {
44
+ return { outs: {
45
+ ...news,
46
+ configured: false,
47
+ dnsRequirements: {}
48
+ } };
49
+ }
50
+ async delete(id, props) {
51
+ await new require_fly_client.FlyClient(props.token).delete(`/v1/apps/${props.appName}/certificates/${encodeURIComponent(id)}`);
52
+ }
53
+ async diff(_id, olds, news) {
54
+ const replaces = [];
55
+ if (olds.appName !== news.appName) replaces.push("appName");
56
+ if (olds.hostname !== news.hostname) replaces.push("hostname");
57
+ return {
58
+ changes: replaces.length > 0,
59
+ replaces,
60
+ deleteBeforeReplace: true
61
+ };
62
+ }
63
+ };
64
+ /** Internal dynamic resource — not part of the public API. */
65
+ var FlyCertificateResource = class extends _pulumi_pulumi.dynamic.Resource {
66
+ constructor(name, args, opts) {
67
+ super(new FlyCertificateResourceProvider(), name, {
68
+ ...args,
69
+ configured: void 0,
70
+ dnsRequirements: void 0
71
+ }, opts);
72
+ }
73
+ };
74
+ /**
75
+ * Manages a Fly ACME certificate for a custom hostname.
76
+ *
77
+ * Exposes `.configured` and `.dnsRequirements` so the consumer can wire up the
78
+ * required DNS records.
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * const cert = new FlyCertificate("api-cert", {
83
+ * hostname: "api.example.com",
84
+ * }, { provider, app });
85
+ * ```
86
+ */
87
+ var FlyCertificate = class extends _pulumi_pulumi.ComponentResource {
88
+ constructor(name, args, opts) {
89
+ const { provider, app, ...pulumiOpts } = opts;
90
+ super("infracraft:fly:Certificate", name, {}, pulumiOpts);
91
+ const resource = new FlyCertificateResource(`${name}-resource`, {
92
+ token: provider.token,
93
+ appName: app.id,
94
+ hostname: args.hostname
95
+ }, { parent: this });
96
+ this.id = _pulumi_pulumi.output(args.hostname);
97
+ this.configured = resource.configured;
98
+ this.dnsRequirements = resource.dnsRequirements;
99
+ this.registerOutputs({
100
+ id: this.id,
101
+ configured: this.configured,
102
+ dnsRequirements: this.dnsRequirements
103
+ });
104
+ }
105
+ };
106
+
107
+ //#endregion
108
+ exports.FlyCertificate = FlyCertificate;
109
+ //# sourceMappingURL=certificate.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"certificate.cjs","names":["FlyClient","pulumi"],"sources":["../../src/fly/certificate.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\n\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. */\nexport interface 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\tthrow new Error(`Fly certificate \"${id}\" not found during refresh`);\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\tawait client.delete(\n\t\t\t`/v1/apps/${props.appName}/certificates/${encodeURIComponent(id)}`,\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\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\topts,\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":";;;;;;;;;;;;;AAoDA,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,MACJ,MAAM,IAAI,MAAM,oBAAoB,GAAG,2BAA2B;EAGnE,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;EAGrE,MAAM,IAFaA,6BAAU,MAAM,KAExB,EAAE,OACZ,YAAY,MAAM,QAAQ,gBAAgB,mBAAmB,EAAE,GAChE;CACD;CAEA,MAAM,KACL,KACA,MACA,MACqC;EACrC,MAAM,WAAqB,CAAC;EAE5B,IAAI,KAAK,YAAY,KAAK,SACzB,SAAS,KAAK,SAAS;EAExB,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,GAC7D,IACD;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"}
@@ -0,0 +1,65 @@
1
+ import { t as __name } from "../chunk-OPjESj5l.cjs";
2
+ import { FlyProvider } from "./provider.cjs";
3
+ import { FlyApp } from "./app.cjs";
4
+ import * as pulumi from "@pulumi/pulumi";
5
+
6
+ //#region src/fly/certificate.d.ts
7
+ /** DNS records the consumer must create for certificate validation. */
8
+ interface FlyDnsRequirements {
9
+ /** ACME challenge CNAME record. */
10
+ acme_challenge?: {
11
+ name: string;
12
+ target: string;
13
+ };
14
+ /** `_fly-ownership` TXT record. */
15
+ ownership?: {
16
+ name: string;
17
+ app_value: string;
18
+ };
19
+ /** CNAME target for the hostname itself. */
20
+ cname?: string;
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
+ /** Options type for FlyCertificate. */
32
+ type FlyCertificateOptions = Omit<pulumi.ComponentResourceOptions, "provider"> & {
33
+ /** Fly authentication context. */provider: FlyProvider; /** App the certificate belongs to. */
34
+ app: FlyApp;
35
+ };
36
+ /** Args for FlyCertificate. */
37
+ interface FlyCertificateArgs {
38
+ /** Hostname to issue an ACME certificate for (e.g. `"api.example.com"`). */
39
+ hostname: pulumi.Input<string>;
40
+ }
41
+ /**
42
+ * Manages a Fly ACME certificate for a custom hostname.
43
+ *
44
+ * Exposes `.configured` and `.dnsRequirements` so the consumer can wire up the
45
+ * required DNS records.
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * const cert = new FlyCertificate("api-cert", {
50
+ * hostname: "api.example.com",
51
+ * }, { provider, app });
52
+ * ```
53
+ */
54
+ declare class FlyCertificate extends pulumi.ComponentResource {
55
+ /** Certificate identifier (equals the hostname). */
56
+ readonly id: pulumi.Output<string>;
57
+ /** Whether the certificate is fully provisioned. */
58
+ readonly configured: pulumi.Output<boolean>;
59
+ /** DNS records required for validation. */
60
+ readonly dnsRequirements: pulumi.Output<FlyDnsRequirements>;
61
+ constructor(name: string, args: FlyCertificateArgs, opts: FlyCertificateOptions);
62
+ }
63
+ //#endregion
64
+ export { FlyCertificate, FlyCertificateArgs, FlyCertificateInputs, FlyDnsRequirements };
65
+ //# sourceMappingURL=certificate.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"certificate.d.cts","names":[],"sources":["../../src/fly/certificate.ts"],"mappings":";;;;;;;UAOiB,kBAAA;;EAEhB,cAAA;IAAmB,IAAA;IAAc,MAAA;EAAA;EAAjC;EAGA,SAAA;IAAc,IAAA;IAAc,SAAA;EAAA;EAAA;EAG5B,KAAA;AAAA;AAAK;AAAA,UAIW,oBAAA;EAAoB;EAEpC,KAAA;EAFoC;EAKpC,OAAA;EAAA;EAGA,QAAA;AAAA;AAAQ;AAAA,KA+IJ,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"}
@@ -0,0 +1,65 @@
1
+ import { t as __name } from "../chunk-OPjESj5l.mjs";
2
+ import { FlyProvider } from "./provider.mjs";
3
+ import { FlyApp } from "./app.mjs";
4
+ import * as pulumi from "@pulumi/pulumi";
5
+
6
+ //#region src/fly/certificate.d.ts
7
+ /** DNS records the consumer must create for certificate validation. */
8
+ interface FlyDnsRequirements {
9
+ /** ACME challenge CNAME record. */
10
+ acme_challenge?: {
11
+ name: string;
12
+ target: string;
13
+ };
14
+ /** `_fly-ownership` TXT record. */
15
+ ownership?: {
16
+ name: string;
17
+ app_value: string;
18
+ };
19
+ /** CNAME target for the hostname itself. */
20
+ cname?: string;
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
+ /** Options type for FlyCertificate. */
32
+ type FlyCertificateOptions = Omit<pulumi.ComponentResourceOptions, "provider"> & {
33
+ /** Fly authentication context. */provider: FlyProvider; /** App the certificate belongs to. */
34
+ app: FlyApp;
35
+ };
36
+ /** Args for FlyCertificate. */
37
+ interface FlyCertificateArgs {
38
+ /** Hostname to issue an ACME certificate for (e.g. `"api.example.com"`). */
39
+ hostname: pulumi.Input<string>;
40
+ }
41
+ /**
42
+ * Manages a Fly ACME certificate for a custom hostname.
43
+ *
44
+ * Exposes `.configured` and `.dnsRequirements` so the consumer can wire up the
45
+ * required DNS records.
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * const cert = new FlyCertificate("api-cert", {
50
+ * hostname: "api.example.com",
51
+ * }, { provider, app });
52
+ * ```
53
+ */
54
+ declare class FlyCertificate extends pulumi.ComponentResource {
55
+ /** Certificate identifier (equals the hostname). */
56
+ readonly id: pulumi.Output<string>;
57
+ /** Whether the certificate is fully provisioned. */
58
+ readonly configured: pulumi.Output<boolean>;
59
+ /** DNS records required for validation. */
60
+ readonly dnsRequirements: pulumi.Output<FlyDnsRequirements>;
61
+ constructor(name: string, args: FlyCertificateArgs, opts: FlyCertificateOptions);
62
+ }
63
+ //#endregion
64
+ export { FlyCertificate, FlyCertificateArgs, FlyCertificateInputs, FlyDnsRequirements };
65
+ //# sourceMappingURL=certificate.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"certificate.d.mts","names":[],"sources":["../../src/fly/certificate.ts"],"mappings":";;;;;;;UAOiB,kBAAA;;EAEhB,cAAA;IAAmB,IAAA;IAAc,MAAA;EAAA;EAAjC;EAGA,SAAA;IAAc,IAAA;IAAc,SAAA;EAAA;EAAA;EAG5B,KAAA;AAAA;AAAK;AAAA,UAIW,oBAAA;EAAoB;EAEpC,KAAA;EAFoC;EAKpC,OAAA;EAAA;EAGA,QAAA;AAAA;AAAQ;AAAA,KA+IJ,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"}