@homeflare/alchemy 0.32.0 → 0.34.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 (83) hide show
  1. package/dist/grafana/alerting-provenance.d.ts +80 -0
  2. package/dist/grafana/alerting-provenance.d.ts.map +1 -0
  3. package/dist/grafana/contact-point-fixtures.d.ts +28 -0
  4. package/dist/grafana/contact-point-fixtures.d.ts.map +1 -0
  5. package/dist/grafana/contact-point.d.ts +99 -0
  6. package/dist/grafana/contact-point.d.ts.map +1 -0
  7. package/dist/grafana/dashboard-model.d.ts +47 -0
  8. package/dist/grafana/dashboard-model.d.ts.map +1 -0
  9. package/dist/grafana/dashboard.d.ts +98 -0
  10. package/dist/grafana/dashboard.d.ts.map +1 -0
  11. package/dist/grafana/datasource.d.ts +2 -9
  12. package/dist/grafana/datasource.d.ts.map +1 -1
  13. package/dist/grafana/folder.d.ts +100 -0
  14. package/dist/grafana/folder.d.ts.map +1 -0
  15. package/dist/grafana/index.d.ts +16 -9
  16. package/dist/grafana/index.d.ts.map +1 -1
  17. package/dist/grafana/index.js +325 -16
  18. package/dist/grafana/index.js.map +15 -5
  19. package/dist/grafana/message-template.d.ts +70 -0
  20. package/dist/grafana/message-template.d.ts.map +1 -0
  21. package/dist/grafana/mute-timing.d.ts +112 -0
  22. package/dist/grafana/mute-timing.d.ts.map +1 -0
  23. package/dist/grafana/providers.d.ts +1 -1
  24. package/dist/grafana/providers.d.ts.map +1 -1
  25. package/dist/grafana/provisioned.d.ts +11 -0
  26. package/dist/grafana/provisioned.d.ts.map +1 -0
  27. package/dist/grafana/secret-refs.d.ts +19 -0
  28. package/dist/grafana/secret-refs.d.ts.map +1 -0
  29. package/dist/grafana/subset-match.d.ts +2 -0
  30. package/dist/grafana/subset-match.d.ts.map +1 -0
  31. package/dist/linux/index.d.ts +1 -1
  32. package/dist/linux/index.d.ts.map +1 -1
  33. package/dist/linux/index.js +3 -1
  34. package/dist/linux/index.js.map +1 -1
  35. package/dist/proxmox/index.js +76 -45
  36. package/dist/proxmox/index.js.map +6 -6
  37. package/dist/proxmox/zfs-pool-form.d.ts +124 -0
  38. package/dist/proxmox/zfs-pool-form.d.ts.map +1 -0
  39. package/dist/proxmox/zfs-pool-wire.d.ts +78 -0
  40. package/dist/proxmox/zfs-pool-wire.d.ts.map +1 -0
  41. package/dist/proxmox/zfs-pool.d.ts +27 -52
  42. package/dist/proxmox/zfs-pool.d.ts.map +1 -1
  43. package/docs/grafana-alerting.md +145 -0
  44. package/docs/grafana-folder-dashboard.md +145 -0
  45. package/docs/grafana.md +12 -10
  46. package/docs/upstream-conformance.md +31 -4
  47. package/package.json +1 -1
  48. package/src/grafana/alerting-provenance.ts +109 -0
  49. package/src/grafana/contact-point-fixtures.ts +25 -0
  50. package/src/grafana/contact-point-provenance.test.ts +113 -0
  51. package/src/grafana/contact-point-secrets.test.ts +117 -0
  52. package/src/grafana/contact-point.test.ts +123 -0
  53. package/src/grafana/contact-point.ts +179 -0
  54. package/src/grafana/dashboard-model.test.ts +111 -0
  55. package/src/grafana/dashboard-model.ts +62 -0
  56. package/src/grafana/dashboard.test.ts +232 -0
  57. package/src/grafana/dashboard.ts +161 -0
  58. package/src/grafana/datasource.ts +5 -27
  59. package/src/grafana/folder.test.ts +212 -0
  60. package/src/grafana/folder.ts +161 -0
  61. package/src/grafana/index.ts +42 -9
  62. package/src/grafana/message-template.test.ts +212 -0
  63. package/src/grafana/message-template.ts +114 -0
  64. package/src/grafana/mute-timing.test.ts +227 -0
  65. package/src/grafana/mute-timing.ts +160 -0
  66. package/src/grafana/providers.ts +13 -1
  67. package/src/grafana/provisioned.ts +49 -0
  68. package/src/grafana/secret-refs.ts +48 -0
  69. package/src/grafana/subset-match.ts +71 -0
  70. package/src/linux/index-export.test.ts +25 -0
  71. package/src/linux/index.ts +15 -1
  72. package/src/proxmox/constraints-host-forms.test.ts +1 -1
  73. package/src/proxmox/zfs-pool-adopt.test.ts +26 -0
  74. package/src/proxmox/zfs-pool-form.ts +236 -0
  75. package/src/proxmox/zfs-pool-read-failure.test.ts +118 -0
  76. package/src/proxmox/zfs-pool-wire.ts +132 -0
  77. package/src/proxmox/zfs-pool.ts +106 -76
  78. package/dist/proxmox/zfs-pool-spec.d.ts +0 -27
  79. package/dist/proxmox/zfs-pool-spec.d.ts.map +0 -1
  80. package/dist/proxmox/zfs-pool-write.d.ts +0 -128
  81. package/dist/proxmox/zfs-pool-write.d.ts.map +0 -1
  82. package/src/proxmox/zfs-pool-spec.ts +0 -76
  83. package/src/proxmox/zfs-pool-write.ts +0 -196
@@ -2,8 +2,7 @@
2
2
  import { Resource } from "alchemy";
3
3
  import * as Provider from "alchemy/Provider";
4
4
  import * as grafana from "@distilled.cloud/grafana";
5
- import * as Data from "effect/Data";
6
- import * as Effect2 from "effect/Effect";
5
+ import * as Effect3 from "effect/Effect";
7
6
 
8
7
  // src/grafana/resource.ts
9
8
  import { isResolved } from "alchemy/Diff";
@@ -57,12 +56,13 @@ var grafanaHandlers = (spec) => {
57
56
  };
58
57
  };
59
58
 
60
- // src/grafana/datasource.ts
61
- var GrafanaDatasource = Resource("Grafana.Datasource");
59
+ // src/grafana/secret-refs.ts
60
+ import * as Data from "effect/Data";
61
+ import * as Effect2 from "effect/Effect";
62
62
 
63
63
  class GrafanaSecretRefUnsetError extends Data.TaggedError("GrafanaSecretRefUnsetError") {
64
64
  }
65
- var resolveSecureJsonData = (refs) => Effect2.gen(function* () {
65
+ var resolveSecretRefs = (refs, describeField) => Effect2.gen(function* () {
66
66
  if (refs === undefined)
67
67
  return;
68
68
  const out = {};
@@ -70,13 +70,17 @@ var resolveSecureJsonData = (refs) => Effect2.gen(function* () {
70
70
  const raw = process.env[envVar];
71
71
  if (raw === undefined || raw.trim() === "") {
72
72
  return yield* Effect2.fail(new GrafanaSecretRefUnsetError({
73
- message: `${envVar} is unset. Export the value of secureJsonData.${field} there — ` + "never as an Alchemy prop."
73
+ message: `${envVar} is unset. Export the value of ${describeField(field)} there — ` + "never as an Alchemy prop."
74
74
  }));
75
75
  }
76
76
  out[field] = raw.trim();
77
77
  }
78
78
  return out;
79
79
  });
80
+
81
+ // src/grafana/datasource.ts
82
+ var GrafanaDatasource = Resource("Grafana.Datasource");
83
+ var resolveSecureJsonData = (refs) => resolveSecretRefs(refs, (field) => `secureJsonData.${field}`);
80
84
  var fields = (props) => ({
81
85
  name: props.name,
82
86
  type: props.type,
@@ -103,15 +107,15 @@ var spec = {
103
107
  url: live.url ?? "",
104
108
  version: live.version ?? 0
105
109
  }),
106
- create: (props) => Effect2.flatMap(resolveSecureJsonData(props.secureJsonDataRefs), (secureJsonData) => grafana.addDataSource({
110
+ create: (props) => Effect3.flatMap(resolveSecureJsonData(props.secureJsonDataRefs), (secureJsonData) => grafana.addDataSource({
107
111
  ...fields(props),
108
112
  ...secureJsonData === undefined ? {} : { secureJsonData },
109
113
  uid: props.uid
110
114
  })),
111
115
  destroy: (props) => grafana.deleteDataSourceByUID({ uid: props.uid }),
112
- fetchLive: (props) => grafana.getDataSourceByUID({ uid: props.uid }).pipe(Effect2.catchTag("NotFound", () => Effect2.succeed(undefined))),
116
+ fetchLive: (props) => grafana.getDataSourceByUID({ uid: props.uid }).pipe(Effect3.catchTag("NotFound", () => Effect3.succeed(undefined))),
113
117
  matches: (attributes, props) => (props.name === undefined || attributes.name === props.name) && (props.type === undefined || attributes.type === props.type) && (props.url === undefined || attributes.url === props.url) && (props.access === undefined || attributes.access === props.access) && (props.isDefault === undefined || attributes.isDefault === props.isDefault),
114
- update: (props, live) => Effect2.flatMap(resolveSecureJsonData(props.secureJsonDataRefs), (secureJsonData) => grafana.updateDataSourceByUID({
118
+ update: (props, live) => Effect3.flatMap(resolveSecureJsonData(props.secureJsonDataRefs), (secureJsonData) => grafana.updateDataSourceByUID({
115
119
  ...fields(props),
116
120
  ...secureJsonData === undefined ? {} : { secureJsonData },
117
121
  ...live.version === undefined ? {} : { version: live.version },
@@ -119,31 +123,336 @@ var spec = {
119
123
  }))
120
124
  };
121
125
  var handlers = grafanaHandlers(spec);
122
- var GrafanaDatasourceProvider = () => Provider.effect(GrafanaDatasource, Effect2.succeed(GrafanaDatasource.Provider.of(handlers)));
126
+ var GrafanaDatasourceProvider = () => Provider.effect(GrafanaDatasource, Effect3.succeed(GrafanaDatasource.Provider.of(handlers)));
127
+ // src/grafana/dashboard.ts
128
+ import { Resource as Resource2 } from "alchemy";
129
+ import * as Provider2 from "alchemy/Provider";
130
+ import * as grafana2 from "@distilled.cloud/grafana";
131
+ import * as Effect5 from "effect/Effect";
132
+
133
+ // src/grafana/subset-match.ts
134
+ var isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
135
+ var declaredContentMatches = (declared, live) => {
136
+ if (declared == null)
137
+ return true;
138
+ if (Array.isArray(declared)) {
139
+ return Array.isArray(live) && declared.length === live.length && declared.every((item, index) => declaredContentMatches(item, live[index]));
140
+ }
141
+ if (isPlainObject(declared)) {
142
+ return isPlainObject(live) && Object.entries(declared).every(([key, value]) => declaredContentMatches(value, live[key]));
143
+ }
144
+ return declared === live;
145
+ };
146
+
147
+ // src/grafana/dashboard-model.ts
148
+ var VOLATILE_FIELDS = ["id", "version", "iteration"];
149
+ var normalizeModel = (model, uid) => {
150
+ const normalized = {};
151
+ for (const [key, value] of Object.entries(model)) {
152
+ if (key === "uid")
153
+ continue;
154
+ if (VOLATILE_FIELDS.includes(key))
155
+ continue;
156
+ normalized[key] = value;
157
+ }
158
+ normalized.uid = uid;
159
+ return normalized;
160
+ };
161
+ var modelTitle = (model) => typeof model.title === "string" ? model.title : "";
162
+
163
+ // src/grafana/provisioned.ts
164
+ import * as Data2 from "effect/Data";
165
+ import * as Effect4 from "effect/Effect";
166
+
167
+ class GrafanaProvisionedObjectError extends Data2.TaggedError("GrafanaProvisionedObjectError") {
168
+ }
169
+ var refuseIfProvisioned = (kind, uid, owner) => {
170
+ const ownerClause = owner === undefined || owner === "" ? `(this Grafana instance did not report an owning file)` : `by ${owner}`;
171
+ return Effect4.fail(new GrafanaProvisionedObjectError({
172
+ message: `${kind} '${uid}' is file-provisioned ${ownerClause} and read-only through the classic ` + `write API this family calls. Edit the provisioning file instead — declaring this ` + `object read-only (a declaration matching what is live) is safe and will never reach ` + `this refusal.`
173
+ }));
174
+ };
175
+
176
+ // src/grafana/dashboard.ts
177
+ var GrafanaDashboard = Resource2("Grafana.Dashboard");
178
+ var modelOf = (live) => live.dashboard !== null && typeof live.dashboard === "object" ? live.dashboard : {};
179
+ var spec2 = {
180
+ attributes: (live, props) => {
181
+ const model = normalizeModel(modelOf(live), props.uid);
182
+ return {
183
+ dashboard: model,
184
+ folderUid: live.meta?.folderUid ?? "",
185
+ provisioned: live.meta?.provisioned ?? false,
186
+ provisionedExternalId: live.meta?.provisionedExternalId ?? "",
187
+ title: modelTitle(model),
188
+ uid: props.uid,
189
+ url: live.meta?.url ?? "",
190
+ version: live.meta?.version ?? 0
191
+ };
192
+ },
193
+ create: (props) => grafana2.postDashboard({
194
+ dashboard: normalizeModel(props.dashboard, props.uid),
195
+ ...props.folderUid === undefined ? {} : { folderUid: props.folderUid }
196
+ }),
197
+ destroy: (props, live) => Effect5.gen(function* () {
198
+ if (live.meta?.provisioned) {
199
+ return yield* refuseIfProvisioned("Grafana.Dashboard", props.uid, live.meta.provisionedExternalId);
200
+ }
201
+ yield* grafana2.deleteDashboard({ uid: props.uid });
202
+ }),
203
+ fetchLive: (props) => grafana2.getDashboard({ uid: props.uid }).pipe(Effect5.catchTag("NotFound", () => Effect5.succeed(undefined))),
204
+ matches: (attributes, props) => (props.folderUid === undefined || attributes.folderUid === props.folderUid) && declaredContentMatches(normalizeModel(props.dashboard, props.uid), attributes.dashboard),
205
+ update: (props, live) => Effect5.gen(function* () {
206
+ if (live.meta?.provisioned) {
207
+ return yield* refuseIfProvisioned("Grafana.Dashboard", props.uid, live.meta.provisionedExternalId);
208
+ }
209
+ return yield* grafana2.postDashboard({
210
+ dashboard: {
211
+ ...normalizeModel(props.dashboard, props.uid),
212
+ ...live.meta?.version === undefined ? {} : { version: live.meta.version }
213
+ },
214
+ ...props.folderUid === undefined ? {} : { folderUid: props.folderUid }
215
+ });
216
+ })
217
+ };
218
+ var handlers2 = grafanaHandlers(spec2);
219
+ var GrafanaDashboardProvider = () => Provider2.effect(GrafanaDashboard, Effect5.succeed(GrafanaDashboard.Provider.of(handlers2)));
220
+ // src/grafana/folder.ts
221
+ import { Resource as Resource3 } from "alchemy";
222
+ import * as Provider3 from "alchemy/Provider";
223
+ import * as grafana3 from "@distilled.cloud/grafana";
224
+ import * as Data3 from "effect/Data";
225
+ import * as Effect6 from "effect/Effect";
226
+ var GrafanaFolder = Resource3("Grafana.Folder", {
227
+ defaultRemovalPolicy: "retain"
228
+ });
229
+
230
+ class GrafanaFolderReparentError extends Data3.TaggedError("GrafanaFolderReparentError") {
231
+ }
232
+ var spec3 = {
233
+ attributes: (live) => ({
234
+ id: live.id ?? 0,
235
+ managedBy: live.managedBy ?? "",
236
+ parentUid: live.parentUid ?? "",
237
+ title: live.title ?? "",
238
+ uid: live.uid ?? "",
239
+ url: live.url ?? "",
240
+ version: live.version ?? 0
241
+ }),
242
+ create: (props) => grafana3.createFolder({
243
+ uid: props.uid,
244
+ title: props.title,
245
+ ...props.description === undefined ? {} : { description: props.description },
246
+ ...props.parentUid === undefined ? {} : { parentUid: props.parentUid }
247
+ }),
248
+ destroy: (props, live) => Effect6.gen(function* () {
249
+ if (live.managedBy) {
250
+ return yield* refuseIfProvisioned("Grafana.Folder", props.uid, live.managedBy);
251
+ }
252
+ yield* grafana3.deleteFolder({ folder_uid: props.uid });
253
+ }),
254
+ fetchLive: (props) => grafana3.getFolderByUID({ folder_uid: props.uid }).pipe(Effect6.catchTag("NotFound", () => Effect6.succeed(undefined))),
255
+ matches: (attributes, props) => attributes.title === props.title && (props.parentUid === undefined || attributes.parentUid === props.parentUid),
256
+ update: (props, live) => Effect6.gen(function* () {
257
+ if (live.managedBy) {
258
+ return yield* refuseIfProvisioned("Grafana.Folder", props.uid, live.managedBy);
259
+ }
260
+ if (props.parentUid !== undefined && props.parentUid !== (live.parentUid ?? undefined)) {
261
+ return yield* Effect6.fail(new GrafanaFolderReparentError({
262
+ message: `Grafana.Folder '${props.uid}' declares parentUid '${props.parentUid}' but is ` + `live under '${live.parentUid ?? "(root)"}'. PUT /folders/{uid} cannot reparent a ` + `folder — move it by hand in Grafana, then update the declaration to match.`
263
+ }));
264
+ }
265
+ return yield* grafana3.updateFolder({
266
+ folder_uid: props.uid,
267
+ title: props.title,
268
+ ...props.description === undefined ? {} : { description: props.description },
269
+ ...live.version === undefined ? {} : { version: live.version }
270
+ });
271
+ })
272
+ };
273
+ var handlers3 = grafanaHandlers(spec3);
274
+ var GrafanaFolderProvider = () => Provider3.effect(GrafanaFolder, Effect6.succeed(GrafanaFolder.Provider.of(handlers3)));
275
+ // src/grafana/contact-point.ts
276
+ import { Resource as Resource4 } from "alchemy";
277
+ import * as Provider4 from "alchemy/Provider";
278
+ import * as grafana4 from "@distilled.cloud/grafana";
279
+ import * as Effect8 from "effect/Effect";
280
+
281
+ // src/grafana/alerting-provenance.ts
282
+ import * as Effect7 from "effect/Effect";
283
+ var WRITABLE_PROVENANCES = new Set(["", "api"]);
284
+ var isForeignProvenance = (provenance) => provenance === undefined || !WRITABLE_PROVENANCES.has(provenance);
285
+ var refuseIfForeignProvenance = (kind, id, provenance) => {
286
+ const reason = provenance === undefined ? `did not report a provenance at all — this family cannot tell whether it is safe to own` : `has provenance '${provenance}', not '(none)' or 'api'`;
287
+ return Effect7.fail(new GrafanaProvisionedObjectError({
288
+ message: `${kind} '${id}' ${reason} — something other than this API may own it (file ` + `provisioning, the Prometheus-rules importer, or similar), and writing here could take ` + `over or corrupt an object this family does not actually control. Edit it at its actual ` + `source instead — declaring this object read-only (a declaration matching what is live) ` + `is safe and will never reach this refusal.`
289
+ }));
290
+ };
291
+
292
+ // src/grafana/contact-point.ts
293
+ var GrafanaContactPoint = Resource4("Grafana.ContactPoint");
294
+ var nonSecretSettings = (props) => {
295
+ const refs = props.secureSettingsRefs;
296
+ if (refs === undefined)
297
+ return props.settings;
298
+ const out = {};
299
+ for (const [key, value] of Object.entries(props.settings)) {
300
+ if (!(key in refs))
301
+ out[key] = value;
302
+ }
303
+ return out;
304
+ };
305
+ var resolveSettings = (props) => Effect8.map(resolveSecretRefs(props.secureSettingsRefs, (field) => `settings.${field}`), (secrets) => secrets === undefined ? props.settings : { ...props.settings, ...secrets });
306
+ var spec4 = {
307
+ attributes: (live) => ({
308
+ disableResolveMessage: live.disableResolveMessage ?? false,
309
+ name: live.name ?? "",
310
+ provenance: live.provenance,
311
+ settings: live.settings ?? {},
312
+ type: live.type,
313
+ uid: live.uid ?? ""
314
+ }),
315
+ create: (props) => Effect8.flatMap(resolveSettings(props), (settings) => grafana4.routePostContactpoints({
316
+ name: props.name,
317
+ settings,
318
+ type: props.type,
319
+ uid: props.uid,
320
+ ...props.disableResolveMessage === undefined ? {} : { disableResolveMessage: props.disableResolveMessage }
321
+ })),
322
+ destroy: (props, live) => Effect8.gen(function* () {
323
+ if (isForeignProvenance(live.provenance)) {
324
+ return yield* refuseIfForeignProvenance("Grafana.ContactPoint", props.uid, live.provenance);
325
+ }
326
+ yield* grafana4.routeDeleteContactpoints({ UID: props.uid });
327
+ }),
328
+ fetchLive: (props) => grafana4.routeGetContactpoints({}).pipe(Effect8.map((points) => points.find((point) => point.uid === props.uid))),
329
+ matches: (attributes, props) => attributes.name === props.name && attributes.type === props.type && attributes.disableResolveMessage === (props.disableResolveMessage ?? false) && declaredContentMatches(nonSecretSettings(props), attributes.settings),
330
+ update: (props, live) => Effect8.gen(function* () {
331
+ if (isForeignProvenance(live.provenance)) {
332
+ return yield* refuseIfForeignProvenance("Grafana.ContactPoint", props.uid, live.provenance);
333
+ }
334
+ const settings = yield* resolveSettings(props);
335
+ yield* grafana4.routePutContactpoint({
336
+ UID: props.uid,
337
+ name: props.name,
338
+ settings,
339
+ type: props.type,
340
+ uid: props.uid,
341
+ ...props.disableResolveMessage === undefined ? {} : { disableResolveMessage: props.disableResolveMessage }
342
+ });
343
+ })
344
+ };
345
+ var handlers4 = grafanaHandlers(spec4);
346
+ var GrafanaContactPointProvider = () => Provider4.effect(GrafanaContactPoint, Effect8.succeed(GrafanaContactPoint.Provider.of(handlers4)));
347
+ // src/grafana/message-template.ts
348
+ import { Resource as Resource5 } from "alchemy";
349
+ import * as Provider5 from "alchemy/Provider";
350
+ import * as grafana5 from "@distilled.cloud/grafana";
351
+ import * as Effect9 from "effect/Effect";
352
+ var GrafanaMessageTemplate = Resource5("Grafana.MessageTemplate");
353
+ var spec5 = {
354
+ attributes: (live) => ({
355
+ name: live.name ?? "",
356
+ provenance: live.provenance,
357
+ template: live.template ?? ""
358
+ }),
359
+ create: (props) => grafana5.routePutTemplate({ name: props.name, template: props.template }),
360
+ destroy: (props, live) => Effect9.gen(function* () {
361
+ if (isForeignProvenance(live.provenance)) {
362
+ return yield* refuseIfForeignProvenance("Grafana.MessageTemplate", props.name, live.provenance);
363
+ }
364
+ yield* grafana5.routeDeleteTemplate({ name: props.name });
365
+ }),
366
+ fetchLive: (props) => grafana5.routeGetTemplate({ name: props.name }).pipe(Effect9.catchTag("NotFound", () => Effect9.succeed(undefined))),
367
+ matches: (attributes, props) => attributes.template === props.template,
368
+ update: (props, live) => Effect9.gen(function* () {
369
+ if (isForeignProvenance(live.provenance)) {
370
+ return yield* refuseIfForeignProvenance("Grafana.MessageTemplate", props.name, live.provenance);
371
+ }
372
+ yield* grafana5.routePutTemplate({
373
+ name: props.name,
374
+ template: props.template,
375
+ ...live.version === undefined ? {} : { version: live.version }
376
+ });
377
+ })
378
+ };
379
+ var handlers5 = grafanaHandlers(spec5);
380
+ var GrafanaMessageTemplateProvider = () => Provider5.effect(GrafanaMessageTemplate, Effect9.succeed(GrafanaMessageTemplate.Provider.of(handlers5)));
381
+ // src/grafana/mute-timing.ts
382
+ import { Resource as Resource6 } from "alchemy";
383
+ import * as Provider6 from "alchemy/Provider";
384
+ import * as grafana6 from "@distilled.cloud/grafana";
385
+ import * as Effect10 from "effect/Effect";
386
+ var GrafanaMuteTiming = Resource6("Grafana.MuteTiming");
387
+ var spec6 = {
388
+ attributes: (live) => ({
389
+ name: live.name ?? "",
390
+ provenance: live.provenance,
391
+ timeIntervals: live.time_intervals ?? []
392
+ }),
393
+ create: (props) => grafana6.routePostMuteTiming({
394
+ name: props.name,
395
+ time_intervals: props.timeIntervals
396
+ }),
397
+ destroy: (props, live) => Effect10.gen(function* () {
398
+ if (isForeignProvenance(live.provenance)) {
399
+ return yield* refuseIfForeignProvenance("Grafana.MuteTiming", props.name, live.provenance);
400
+ }
401
+ yield* grafana6.routeDeleteMuteTiming({
402
+ name: props.name,
403
+ ...live.version === undefined ? {} : { version: live.version }
404
+ });
405
+ }),
406
+ fetchLive: (props) => grafana6.routeGetMuteTiming({ name: props.name }).pipe(Effect10.map((live) => live), Effect10.catchTag("NotFound", () => Effect10.succeed(undefined))),
407
+ matches: (attributes, props) => declaredContentMatches(props.timeIntervals, attributes.timeIntervals),
408
+ update: (props, live) => Effect10.gen(function* () {
409
+ if (isForeignProvenance(live.provenance)) {
410
+ return yield* refuseIfForeignProvenance("Grafana.MuteTiming", props.name, live.provenance);
411
+ }
412
+ yield* grafana6.routePutMuteTiming({
413
+ name: props.name,
414
+ time_intervals: props.timeIntervals
415
+ });
416
+ })
417
+ };
418
+ var handlers6 = grafanaHandlers(spec6);
419
+ var GrafanaMuteTimingProvider = () => Provider6.effect(GrafanaMuteTiming, Effect10.succeed(GrafanaMuteTiming.Provider.of(handlers6)));
123
420
  // src/grafana/credentials.ts
124
421
  import { Credentials } from "@distilled.cloud/grafana/Credentials";
125
422
  import { ConfigError } from "@distilled.cloud/grafana/Errors";
126
- import * as Effect3 from "effect/Effect";
423
+ import * as Effect11 from "effect/Effect";
127
424
  import * as Layer from "effect/Layer";
128
425
  import * as Redacted from "effect/Redacted";
129
- var resolve = (target) => Effect3.sync(() => process.env[target.tokenEnv]).pipe(Effect3.flatMap((raw) => raw === undefined || raw.trim() === "" ? Effect3.fail(new ConfigError({
426
+ var resolve = (target) => Effect11.sync(() => process.env[target.tokenEnv]).pipe(Effect11.flatMap((raw) => raw === undefined || raw.trim() === "" ? Effect11.fail(new ConfigError({
130
427
  message: `${target.tokenEnv} is not set. Export the Grafana service-account token there ` + `— never as an Alchemy prop — before running a stack that declares a resource ` + `against ${target.baseUrl}.`
131
- })) : Effect3.succeed({
428
+ })) : Effect11.succeed({
132
429
  apiBaseUrl: target.baseUrl.replace(/\/+$/, ""),
133
430
  token: Redacted.make(raw.trim()),
134
431
  ...target.orgId === undefined ? {} : { orgId: target.orgId }
135
- })), Effect3.orDie);
432
+ })), Effect11.orDie);
136
433
  var grafanaCredentials = (target) => Layer.succeed(Credentials, resolve(target));
137
434
  // src/grafana/providers.ts
138
435
  import * as Layer2 from "effect/Layer";
139
- var grafanaProviders = (target) => GrafanaDatasourceProvider().pipe(Layer2.provide(grafanaCredentials(target)));
436
+ var grafanaProviders = (target) => Layer2.mergeAll(GrafanaDatasourceProvider(), GrafanaFolderProvider(), GrafanaDashboardProvider(), GrafanaContactPointProvider(), GrafanaMuteTimingProvider(), GrafanaMessageTemplateProvider()).pipe(Layer2.provide(grafanaCredentials(target)));
140
437
  export {
438
+ GrafanaContactPoint,
439
+ GrafanaContactPointProvider,
440
+ GrafanaDashboard,
441
+ GrafanaDashboardProvider,
141
442
  GrafanaDatasource,
142
443
  GrafanaDatasourceProvider,
444
+ GrafanaFolder,
445
+ GrafanaFolderProvider,
446
+ GrafanaFolderReparentError,
447
+ GrafanaMessageTemplate,
448
+ GrafanaMessageTemplateProvider,
449
+ GrafanaMuteTiming,
450
+ GrafanaMuteTimingProvider,
451
+ GrafanaProvisionedObjectError,
143
452
  GrafanaSecretRefUnsetError,
144
453
  grafanaCredentials,
145
454
  grafanaProviders
146
455
  };
147
456
 
148
- //# debugId=DA921F3915B68A6164756E2164756E21
457
+ //# debugId=D93AD79265681B5F64756E2164756E21
149
458
  //# sourceMappingURL=index.js.map