@visiolab/effect-firebase 0.0.0-stage → 0.3.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 (140) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +81 -2
  3. package/dist/_virtual/_rolldown/runtime.mjs +12 -0
  4. package/dist/app/App.d.mts +27 -0
  5. package/dist/app/App.mjs +27 -0
  6. package/dist/app/index.d.mts +2 -0
  7. package/dist/app/index.mjs +1 -0
  8. package/dist/firestore/Collection.d.mts +423 -0
  9. package/dist/firestore/Collection.mjs +133 -0
  10. package/dist/firestore/CollectionGroup.d.mts +164 -0
  11. package/dist/firestore/CollectionGroup.mjs +84 -0
  12. package/dist/firestore/DocumentPath.d.mts +95 -0
  13. package/dist/firestore/DocumentPath.mjs +71 -0
  14. package/dist/firestore/DocumentSnapshot.d.mts +239 -0
  15. package/dist/firestore/DocumentSnapshot.mjs +134 -0
  16. package/dist/firestore/FieldValue.d.mts +332 -0
  17. package/dist/firestore/FieldValue.mjs +256 -0
  18. package/dist/firestore/Firestore.d.mts +1165 -0
  19. package/dist/firestore/Firestore.mjs +274 -0
  20. package/dist/firestore/FirestoreModel.d.mts +1232 -0
  21. package/dist/firestore/FirestoreModel.mjs +586 -0
  22. package/dist/firestore/FirestoreSchema.d.mts +567 -0
  23. package/dist/firestore/FirestoreSchema.mjs +419 -0
  24. package/dist/firestore/FirestoreValue.d.mts +145 -0
  25. package/dist/firestore/FirestoreValue.mjs +87 -0
  26. package/dist/firestore/GeoPoint.d.mts +90 -0
  27. package/dist/firestore/GeoPoint.mjs +75 -0
  28. package/dist/firestore/Patch.d.mts +73 -0
  29. package/dist/firestore/Patch.mjs +57 -0
  30. package/dist/firestore/QuerySnapshot.d.mts +107 -0
  31. package/dist/firestore/QuerySnapshot.mjs +43 -0
  32. package/dist/firestore/Timestamp.d.mts +273 -0
  33. package/dist/firestore/Timestamp.mjs +255 -0
  34. package/dist/firestore/index.d.mts +14 -0
  35. package/dist/firestore/index.mjs +14 -0
  36. package/dist/firestore/internal/collection.mjs +156 -0
  37. package/dist/firestore/internal/collectionGroup.mjs +64 -0
  38. package/dist/firestore/internal/documentPath.d.mts +4 -0
  39. package/dist/firestore/internal/documentPath.mjs +42 -0
  40. package/dist/firestore/internal/documentSnapshot.mjs +63 -0
  41. package/dist/firestore/internal/fieldValue.d.mts +11 -0
  42. package/dist/firestore/internal/fieldValue.mjs +88 -0
  43. package/dist/firestore/internal/firestore.mjs +145 -0
  44. package/dist/firestore/internal/firestoreError.d.mts +29 -0
  45. package/dist/firestore/internal/firestoreError.mjs +30 -0
  46. package/dist/firestore/internal/firestoreModel.mjs +719 -0
  47. package/dist/firestore/internal/firestoreSchema.mjs +123 -0
  48. package/dist/firestore/internal/firestoreValue.mjs +108 -0
  49. package/dist/firestore/internal/firestoreValueWalk.d.mts +58 -0
  50. package/dist/firestore/internal/firestoreValueWalk.mjs +223 -0
  51. package/dist/firestore/internal/geoPoint.d.mts +4 -0
  52. package/dist/firestore/internal/geoPoint.mjs +39 -0
  53. package/dist/firestore/internal/patch.mjs +19 -0
  54. package/dist/firestore/internal/querySnapshot.mjs +24 -0
  55. package/dist/firestore/internal/schemaAST.mjs +35 -0
  56. package/dist/firestore/internal/snapshotExtra.mjs +35 -0
  57. package/dist/firestore/internal/streamFromListener.mjs +12 -0
  58. package/dist/firestore/internal/timestamp.d.mts +4 -0
  59. package/dist/firestore/internal/timestamp.mjs +66 -0
  60. package/dist/firestore/internal/timestampSchema.mjs +31 -0
  61. package/dist/firestore/internal/transactionFromCallback.mjs +66 -0
  62. package/dist/functions/Callable.d.mts +654 -0
  63. package/dist/functions/Callable.mjs +450 -0
  64. package/dist/functions/CallableError.d.mts +297 -0
  65. package/dist/functions/CallableError.mjs +256 -0
  66. package/dist/functions/CallableMiddleware.d.mts +213 -0
  67. package/dist/functions/CallableMiddleware.mjs +52 -0
  68. package/dist/functions/CallableRequest.d.mts +166 -0
  69. package/dist/functions/CallableRequest.mjs +18 -0
  70. package/dist/functions/Caller.d.mts +103 -0
  71. package/dist/functions/Caller.mjs +115 -0
  72. package/dist/functions/DocumentTrigger.d.mts +795 -0
  73. package/dist/functions/DocumentTrigger.mjs +566 -0
  74. package/dist/functions/FirebaseFunction.d.mts +79 -0
  75. package/dist/functions/FirebaseFunction.mjs +4 -0
  76. package/dist/functions/FunctionGroup.d.mts +175 -0
  77. package/dist/functions/FunctionGroup.mjs +64 -0
  78. package/dist/functions/index.d.mts +9 -0
  79. package/dist/functions/index.mjs +9 -0
  80. package/dist/functions/internal/callable.mjs +167 -0
  81. package/dist/functions/internal/callableMiddleware.d.mts +19 -0
  82. package/dist/functions/internal/callableMiddleware.mjs +15 -0
  83. package/dist/functions/internal/callableRequest.mjs +6 -0
  84. package/dist/functions/internal/documentTrigger.d.mts +10 -0
  85. package/dist/functions/internal/documentTrigger.mjs +73 -0
  86. package/dist/functions/internal/firebaseFunction.d.mts +5 -0
  87. package/dist/functions/internal/firebaseFunction.mjs +24 -0
  88. package/dist/functions/internal/functionGroup.mjs +36 -0
  89. package/package.json +72 -3
  90. package/src/app/App.ts +24 -0
  91. package/src/app/index.ts +7 -0
  92. package/src/firestore/Collection.ts +520 -0
  93. package/src/firestore/CollectionGroup.ts +245 -0
  94. package/src/firestore/DocumentPath.ts +114 -0
  95. package/src/firestore/DocumentSnapshot.ts +308 -0
  96. package/src/firestore/FieldValue.ts +375 -0
  97. package/src/firestore/Firestore.ts +1432 -0
  98. package/src/firestore/FirestoreModel.ts +1884 -0
  99. package/src/firestore/FirestoreSchema.ts +643 -0
  100. package/src/firestore/FirestoreValue.ts +207 -0
  101. package/src/firestore/GeoPoint.ts +105 -0
  102. package/src/firestore/Patch.ts +117 -0
  103. package/src/firestore/QuerySnapshot.ts +150 -0
  104. package/src/firestore/Timestamp.ts +302 -0
  105. package/src/firestore/index.ts +67 -0
  106. package/src/firestore/internal/collection.ts +246 -0
  107. package/src/firestore/internal/collectionGroup.ts +81 -0
  108. package/src/firestore/internal/documentPath.ts +53 -0
  109. package/src/firestore/internal/documentSnapshot.ts +117 -0
  110. package/src/firestore/internal/fieldValue.ts +119 -0
  111. package/src/firestore/internal/firestore.ts +322 -0
  112. package/src/firestore/internal/firestoreError.ts +36 -0
  113. package/src/firestore/internal/firestoreModel.ts +1242 -0
  114. package/src/firestore/internal/firestoreSchema.ts +218 -0
  115. package/src/firestore/internal/firestoreValue.ts +202 -0
  116. package/src/firestore/internal/firestoreValueWalk.ts +349 -0
  117. package/src/firestore/internal/geoPoint.ts +59 -0
  118. package/src/firestore/internal/patch.ts +21 -0
  119. package/src/firestore/internal/querySnapshot.ts +39 -0
  120. package/src/firestore/internal/schemaAST.ts +83 -0
  121. package/src/firestore/internal/snapshotExtra.ts +47 -0
  122. package/src/firestore/internal/streamFromListener.ts +27 -0
  123. package/src/firestore/internal/timestamp.ts +119 -0
  124. package/src/firestore/internal/timestampSchema.ts +42 -0
  125. package/src/firestore/internal/transactionFromCallback.ts +106 -0
  126. package/src/functions/Callable.ts +855 -0
  127. package/src/functions/CallableError.ts +348 -0
  128. package/src/functions/CallableMiddleware.ts +279 -0
  129. package/src/functions/CallableRequest.ts +207 -0
  130. package/src/functions/Caller.ts +141 -0
  131. package/src/functions/DocumentTrigger.ts +927 -0
  132. package/src/functions/FirebaseFunction.ts +96 -0
  133. package/src/functions/FunctionGroup.ts +225 -0
  134. package/src/functions/index.ts +62 -0
  135. package/src/functions/internal/callable.ts +272 -0
  136. package/src/functions/internal/callableMiddleware.ts +54 -0
  137. package/src/functions/internal/callableRequest.ts +8 -0
  138. package/src/functions/internal/documentTrigger.ts +143 -0
  139. package/src/functions/internal/firebaseFunction.ts +58 -0
  140. package/src/functions/internal/functionGroup.ts +47 -0
@@ -0,0 +1,927 @@
1
+ /**
2
+ * Document Triggers: server functions that run when a document of a
3
+ * collection changes.
4
+ *
5
+ * A {@link DocumentTrigger} is declared from a name and a `Collection`
6
+ * definition, with one constructor per change, such as {@link created}. The
7
+ * server implements it with {@link toLayer} and deploys it with
8
+ * `Functions.make` from `@visiolab/effect-firebase-functions`, or as a member
9
+ * of a Function Group, next to Callables, with `Functions.group`. This module
10
+ * imports no Firebase SDK, so a handler and its tests don't depend on
11
+ * `firebase-functions`.
12
+ *
13
+ * Firebase delivers each event at least once, so a handler can run more than
14
+ * once for one change. Make it idempotent, keyed on the event's `id`.
15
+ *
16
+ * @example Declaring a trigger and implementing it
17
+ * ```ts
18
+ * import { Effect, Schema } from "effect";
19
+ * import { Collection, FirestoreModel } from "@visiolab/effect-firebase/firestore";
20
+ * import { DocumentTrigger } from "@visiolab/effect-firebase/functions";
21
+ *
22
+ * class User extends FirestoreModel.Class<User>("User")({ name: Schema.String }) {}
23
+ * class Post extends FirestoreModel.Class<Post>("Post")({ title: Schema.String }) {}
24
+ *
25
+ * const Users = Collection.make("users", User);
26
+ * const Posts = Users.subcollection("posts", Post);
27
+ *
28
+ * const OnPostCreated = DocumentTrigger.created("onPostCreated", Posts);
29
+ *
30
+ * const OnPostCreatedLive = DocumentTrigger.toLayer(OnPostCreated, (event) =>
31
+ * Effect.gen(function* () {
32
+ * const [userId] = event.ref.ancestors;
33
+ * const post = yield* event.snapshot.data;
34
+ * yield* Effect.log(`${userId} wrote ${post.title}`);
35
+ * }),
36
+ * );
37
+ * ```
38
+ *
39
+ * @stability unstable
40
+ * @since 0.3.0
41
+ */
42
+ import type { Effect, Layer, Pipeable } from "effect";
43
+ import type * as Collection from "../firestore/Collection.ts";
44
+ import type * as DocumentSnapshot from "../firestore/DocumentSnapshot.ts";
45
+ import type * as FirebaseFunction from "./FirebaseFunction.ts";
46
+ import type * as FunctionGroup from "./FunctionGroup.ts";
47
+ import * as internal from "./internal/documentTrigger.ts";
48
+ import type * as internalGroup from "./internal/functionGroup.ts";
49
+ import { isFunctionGroup } from "./internal/functionGroup.ts";
50
+
51
+ const TypeId = internal.TypeId;
52
+
53
+ /**
54
+ * The group and the trigger that the arguments of an overload taking
55
+ * `(trigger, ...)` or `(group, name, ...)` name.
56
+ */
57
+ const target = (
58
+ args: ReadonlyArray<unknown>,
59
+ ): readonly [internalGroup.Fields | undefined, internal.Fields] =>
60
+ isFunctionGroup(args[0])
61
+ ? [args[0], args[0].functions[args[1] as string] as internal.Fields]
62
+ : [undefined, args[0] as internal.Fields];
63
+
64
+ /**
65
+ * The change to a document a {@link DocumentTrigger} runs on: `"created"`,
66
+ * `"updated"`, `"deleted"` or `"written"`.
67
+ *
68
+ * @stability unstable
69
+ * @category models
70
+ * @since 0.3.0
71
+ */
72
+ export type EventKind = internal.EventKind;
73
+
74
+ /**
75
+ * A Document Trigger: a server function's name, the collection it watches,
76
+ * and the change it runs on.
77
+ *
78
+ * **Details**
79
+ *
80
+ * A Document Trigger is the kind of {@link FirebaseFunction.FirebaseFunction}
81
+ * that a change to a document runs, and its `kind` is `"DocumentTrigger"`.
82
+ *
83
+ * It watches every document of its collection. On a subcollection, that is
84
+ * the documents under every parent document. It listens to the `(default)`
85
+ * database, the one `Firestore` reads and writes.
86
+ *
87
+ * The name is its identity. A trigger in no group is deployed under its
88
+ * name, so it is a literal type that the server's exports are keyed on.
89
+ *
90
+ * @see {@link Callable.Callable} for a Function the client calls by name
91
+ *
92
+ * @stability unstable
93
+ * @category models
94
+ * @since 0.3.0
95
+ */
96
+ export interface DocumentTrigger<
97
+ out Name extends string,
98
+ out C extends Collection.Any,
99
+ out Kind extends EventKind = EventKind,
100
+ >
101
+ extends FirebaseFunction.FirebaseFunction<"DocumentTrigger", Name>, Pipeable.Pipeable {
102
+ readonly [TypeId]: typeof TypeId;
103
+ /** The trigger's name, which a trigger in no group is deployed under. */
104
+ readonly name: Name;
105
+ /** The change it runs on, such as `"created"`. */
106
+ readonly event: Kind;
107
+ /** The collection whose documents it watches. */
108
+ readonly collection: C;
109
+ }
110
+
111
+ /**
112
+ * Any {@link DocumentTrigger}, whatever its name, collection and change.
113
+ *
114
+ * @stability unstable
115
+ * @category models
116
+ * @since 0.3.0
117
+ */
118
+ export interface Any extends FirebaseFunction.FirebaseFunction<"DocumentTrigger", string> {
119
+ readonly [TypeId]: typeof TypeId;
120
+ readonly event: EventKind;
121
+ readonly collection: Collection.Any;
122
+ }
123
+
124
+ /**
125
+ * What every event of a trigger on `C` carries: the CloudEvent's `id` and
126
+ * `time`, and the document's typed reference.
127
+ *
128
+ * **Details**
129
+ *
130
+ * The ids that a path pattern would capture as wildcards are on `ref`:
131
+ * `ref.ancestors` holds the ids of the parent documents, from the root down,
132
+ * and `ref.id` the document's own id.
133
+ *
134
+ * @stability unstable
135
+ * @category models
136
+ * @since 0.3.0
137
+ */
138
+ export interface BaseEvent<C extends Collection.Any> {
139
+ /**
140
+ * The CloudEvent's id. Firebase delivers an event at least once, and a
141
+ * redelivered event keeps its id, so key idempotent work on it.
142
+ */
143
+ readonly id: string;
144
+ /** When the change happened, as the CloudEvent's RFC 3339 `time`. */
145
+ readonly time: string;
146
+ /** The reference of the document that changed. */
147
+ readonly ref: Collection.DocumentReference<C>;
148
+ }
149
+
150
+ /**
151
+ * The event of a {@link created} trigger: the document that was created.
152
+ *
153
+ * **Details**
154
+ *
155
+ * `snapshot.data` decodes the document through the collection's model when
156
+ * it runs, and fails with a `Schema.SchemaError` when the data doesn't match.
157
+ * `snapshot.raw` holds the stored data as Firestore Values, as a read does.
158
+ *
159
+ * @see {@link createdEvent} for building one
160
+ *
161
+ * @stability unstable
162
+ * @category models
163
+ * @since 0.3.0
164
+ */
165
+ export interface Created<C extends Collection.Any> extends BaseEvent<C> {
166
+ /** The document as it was created. */
167
+ readonly snapshot: DocumentSnapshot.Existing<C>;
168
+ }
169
+
170
+ /**
171
+ * The event of a {@link deleted} trigger: the document as it was just before
172
+ * it was deleted.
173
+ *
174
+ * **Details**
175
+ *
176
+ * `snapshot` holds the document's last data. `snapshot.data` decodes it
177
+ * through the collection's model when it runs, as for {@link Created}.
178
+ *
179
+ * @see {@link deletedEvent} for building one
180
+ *
181
+ * @stability unstable
182
+ * @category models
183
+ * @since 0.3.0
184
+ */
185
+ export interface Deleted<C extends Collection.Any> extends BaseEvent<C> {
186
+ /** The document as it was just before it was deleted. */
187
+ readonly snapshot: DocumentSnapshot.Existing<C>;
188
+ }
189
+
190
+ /**
191
+ * The event of an {@link updated} trigger: the document before and after the
192
+ * update.
193
+ *
194
+ * **Details**
195
+ *
196
+ * Both sides exist. Each side's `data` decodes through the collection's model
197
+ * when it runs, so a handler can compare the two.
198
+ *
199
+ * @see {@link updatedEvent} for building one
200
+ * @see {@link Written} for the event of a change that may create or delete
201
+ *
202
+ * @stability unstable
203
+ * @category models
204
+ * @since 0.3.0
205
+ */
206
+ export interface Updated<C extends Collection.Any> extends BaseEvent<C> {
207
+ /** The document as it was before the update. */
208
+ readonly before: DocumentSnapshot.Existing<C>;
209
+ /** The document as it is after the update. */
210
+ readonly after: DocumentSnapshot.Existing<C>;
211
+ }
212
+
213
+ /**
214
+ * The event of a {@link written} trigger: the document before and after a
215
+ * create, an update or a delete.
216
+ *
217
+ * **Details**
218
+ *
219
+ * Each side is a `DocumentSnapshot`: on a create, `before` is `Missing`; on a
220
+ * delete, `after` is `Missing`; on an update, both are `Existing`. Narrow a
221
+ * side with `DocumentSnapshot.isExisting` or `DocumentSnapshot.isMissing`
222
+ * before reading its data. `ref` is set in every case.
223
+ *
224
+ * @see {@link writtenEvent} for building one
225
+ * @see {@link Updated} for the event of an update alone, where both sides exist
226
+ *
227
+ * @stability unstable
228
+ * @category models
229
+ * @since 0.3.0
230
+ */
231
+ export interface Written<C extends Collection.Any> extends BaseEvent<C> {
232
+ /** The document before the write: `Missing` when the write created it. */
233
+ readonly before: DocumentSnapshot.DocumentSnapshot<C>;
234
+ /** The document after the write: `Missing` when the write deleted it. */
235
+ readonly after: DocumentSnapshot.DocumentSnapshot<C>;
236
+ }
237
+
238
+ /**
239
+ * The event of each change a trigger on `C` can run on, keyed by the change.
240
+ *
241
+ * @stability unstable
242
+ * @category type-level
243
+ * @since 0.3.0
244
+ */
245
+ export interface Events<C extends Collection.Any> {
246
+ readonly created: Created<C>;
247
+ readonly deleted: Deleted<C>;
248
+ readonly updated: Updated<C>;
249
+ readonly written: Written<C>;
250
+ }
251
+
252
+ /**
253
+ * The event a {@link DocumentTrigger} hands its handler, by its change: a
254
+ * {@link Created} for a {@link created} trigger, an {@link Updated} for an
255
+ * {@link updated} one, a {@link Deleted} for a {@link deleted} one and a
256
+ * {@link Written} for a {@link written} one.
257
+ *
258
+ * @stability unstable
259
+ * @category type-level
260
+ * @since 0.3.0
261
+ */
262
+ export type Event<T extends Any> = Events<T["collection"]>[T["event"]];
263
+
264
+ /**
265
+ * The service a {@link toLayer} Layer provides: the handler of the trigger
266
+ * `Name`, as served in `Group`. It is the {@link FirebaseFunction.Handler}
267
+ * every kind of Function is served by.
268
+ *
269
+ * @stability unstable
270
+ * @category models
271
+ * @since 0.3.0
272
+ */
273
+ export type Handler<Group, Name extends string> = FirebaseFunction.Handler<Group, Name>;
274
+
275
+ /**
276
+ * The {@link Handler} of a trigger in no group.
277
+ *
278
+ * @stability unstable
279
+ * @category type-level
280
+ * @since 0.3.0
281
+ */
282
+ export type HandlerFor<T extends Any> = FirebaseFunction.HandlerFor<T>;
283
+
284
+ /**
285
+ * What implements a trigger: a function from its {@link Event} to an Effect
286
+ * that runs on it.
287
+ *
288
+ * **Details**
289
+ *
290
+ * Its error channel is open: any failure fails the event.
291
+ *
292
+ * @stability unstable
293
+ * @category models
294
+ * @since 0.3.0
295
+ */
296
+ export type HandlerFunction<T extends Any, R> = (
297
+ event: Event<T>,
298
+ ) => Effect.Effect<void, unknown, R>;
299
+
300
+ /**
301
+ * Declares a trigger that runs when a document of `collection` is created.
302
+ *
303
+ * **When to use**
304
+ *
305
+ * Use to react to new documents of a collection on the server. Use a
306
+ * `Callable` instead when the client asks for the work by name.
307
+ *
308
+ * **Details**
309
+ *
310
+ * Its handler gets a {@link Created} event. It takes one collection,
311
+ * whatever its depth: the path pattern it is deployed with is derived from
312
+ * the collection's path, with a wildcard for each parent document's id and
313
+ * for the document's id. A collection group can't be watched; declare a
314
+ * trigger for each of its collections.
315
+ *
316
+ * Firebase delivers each event at least once. Make the handler idempotent,
317
+ * keyed on the event's `id`.
318
+ *
319
+ * @example Declaring a trigger on a subcollection
320
+ * ```ts
321
+ * import { Schema } from "effect";
322
+ * import { Collection, FirestoreModel } from "@visiolab/effect-firebase/firestore";
323
+ * import { DocumentTrigger } from "@visiolab/effect-firebase/functions";
324
+ *
325
+ * class User extends FirestoreModel.Class<User>("User")({ name: Schema.String }) {}
326
+ * class Post extends FirestoreModel.Class<Post>("Post")({ title: Schema.String }) {}
327
+ *
328
+ * const Posts = Collection.make("users", User).subcollection("posts", Post);
329
+ *
330
+ * // Runs for each post created under any user.
331
+ * const OnPostCreated = DocumentTrigger.created("onPostCreated", Posts);
332
+ * ```
333
+ *
334
+ * @see {@link updated} for running when an existing document changes
335
+ * @see {@link deleted} for running when a document is deleted
336
+ * @see {@link written} for running on a create, an update and a delete alike
337
+ * @see {@link toLayer} for implementing the trigger
338
+ * @see {@link createdEvent} for building its event in a test
339
+ * @see {@link FunctionGroup.make} for collecting Functions under one prefix
340
+ * @see {@link Callable.make} for declaring a Function the client calls
341
+ *
342
+ * @stability unstable
343
+ * @category constructors
344
+ * @since 0.3.0
345
+ */
346
+ export const created = <const Name extends string, C extends Collection.Any>(
347
+ name: Name,
348
+ collection: C,
349
+ ): DocumentTrigger<Name, C, "created"> =>
350
+ internal.make({ kind: internal.kind, name, event: "created", collection }) as never;
351
+
352
+ /**
353
+ * Builds the event of a {@link created} trigger from the created document's
354
+ * snapshot.
355
+ *
356
+ * **When to use**
357
+ *
358
+ * Use in a test, to run a handler through {@link serve} with an event of
359
+ * your own. The functions package builds its events with it too.
360
+ *
361
+ * **Details**
362
+ *
363
+ * The event's `ref` is the snapshot's. Build the snapshot with
364
+ * `DocumentSnapshot.existing` and the stored data as Firestore Values.
365
+ *
366
+ * @example Building an event for a test
367
+ * ```ts
368
+ * import { Schema } from "effect";
369
+ * import { Collection, DocumentSnapshot, FirestoreModel } from "@visiolab/effect-firebase/firestore";
370
+ * import { DocumentTrigger } from "@visiolab/effect-firebase/functions";
371
+ *
372
+ * class Post extends FirestoreModel.Class<Post>("Post")({ title: Schema.String }) {}
373
+ *
374
+ * const Posts = Collection.make("posts", Post);
375
+ *
376
+ * const event = DocumentTrigger.createdEvent({
377
+ * id: "event-1",
378
+ * time: "2026-01-01T00:00:00.000Z",
379
+ * snapshot: DocumentSnapshot.existing(Posts.doc(Posts.id.make("hello")), { title: "Hello" }),
380
+ * });
381
+ * ```
382
+ *
383
+ * @see {@link created} for declaring the trigger
384
+ * @see {@link serve} for running the event through the handler
385
+ * @see {@link Created} for the event it builds
386
+ *
387
+ * @stability unstable
388
+ * @category constructors
389
+ * @since 0.3.0
390
+ */
391
+ export const createdEvent: <C extends Collection.Any>(input: {
392
+ readonly id: string;
393
+ readonly time: string;
394
+ readonly snapshot: DocumentSnapshot.Existing<C>;
395
+ }) => Created<C> = internal.createdEvent;
396
+
397
+ /**
398
+ * Declares a trigger that runs when a document of `collection` is deleted.
399
+ *
400
+ * **When to use**
401
+ *
402
+ * Use to clean up after a document of a collection is deleted, such as
403
+ * removing what refers to it.
404
+ *
405
+ * **Details**
406
+ *
407
+ * Its handler gets a {@link Deleted} event, with the document as it was just
408
+ * before it was deleted. It is deployed at the same path pattern as a
409
+ * {@link created} trigger on the same collection.
410
+ *
411
+ * Firebase delivers each event at least once. Make the handler idempotent,
412
+ * keyed on the event's `id`.
413
+ *
414
+ * @example Reading the deleted document
415
+ * ```ts
416
+ * import { Effect, Schema } from "effect";
417
+ * import { Collection, FirestoreModel } from "@visiolab/effect-firebase/firestore";
418
+ * import { DocumentTrigger } from "@visiolab/effect-firebase/functions";
419
+ *
420
+ * class Post extends FirestoreModel.Class<Post>("Post")({ title: Schema.String }) {}
421
+ *
422
+ * const OnPostDeleted = DocumentTrigger.deleted("onPostDeleted", Collection.make("posts", Post));
423
+ *
424
+ * const OnPostDeletedLive = DocumentTrigger.toLayer(OnPostDeleted, (event) =>
425
+ * Effect.flatMap(event.snapshot.data, (post) => Effect.log(`Deleted ${post.title}`)),
426
+ * );
427
+ * ```
428
+ *
429
+ * @see {@link created} for running when a document is created
430
+ * @see {@link updated} for running when an existing document changes
431
+ * @see {@link written} for running on a create, an update and a delete alike
432
+ * @see {@link toLayer} for implementing the trigger
433
+ * @see {@link deletedEvent} for building its event in a test
434
+ * @see {@link FunctionGroup.make} for collecting Functions under one prefix
435
+ *
436
+ * @stability unstable
437
+ * @category constructors
438
+ * @since 0.3.0
439
+ */
440
+ export const deleted = <const Name extends string, C extends Collection.Any>(
441
+ name: Name,
442
+ collection: C,
443
+ ): DocumentTrigger<Name, C, "deleted"> =>
444
+ internal.make({ kind: internal.kind, name, event: "deleted", collection }) as never;
445
+
446
+ /**
447
+ * Builds the event of a {@link deleted} trigger from the snapshot of the
448
+ * document as it was just before it was deleted.
449
+ *
450
+ * **When to use**
451
+ *
452
+ * Use in a test, to run a handler through {@link serve} with an event of
453
+ * your own. The functions package builds its events with it too.
454
+ *
455
+ * **Details**
456
+ *
457
+ * The event's `ref` is the snapshot's. Build the snapshot with
458
+ * `DocumentSnapshot.existing` and the document's last data as Firestore
459
+ * Values.
460
+ *
461
+ * @example Building an event for a test
462
+ * ```ts
463
+ * import { Schema } from "effect";
464
+ * import { Collection, DocumentSnapshot, FirestoreModel } from "@visiolab/effect-firebase/firestore";
465
+ * import { DocumentTrigger } from "@visiolab/effect-firebase/functions";
466
+ *
467
+ * class Post extends FirestoreModel.Class<Post>("Post")({ title: Schema.String }) {}
468
+ *
469
+ * const Posts = Collection.make("posts", Post);
470
+ *
471
+ * const event = DocumentTrigger.deletedEvent({
472
+ * id: "event-1",
473
+ * time: "2026-01-01T00:00:00.000Z",
474
+ * snapshot: DocumentSnapshot.existing(Posts.doc(Posts.id.make("hello")), { title: "Hello" }),
475
+ * });
476
+ * ```
477
+ *
478
+ * @see {@link deleted} for declaring the trigger
479
+ * @see {@link serve} for running the event through the handler
480
+ * @see {@link Deleted} for the event it builds
481
+ *
482
+ * @stability unstable
483
+ * @category constructors
484
+ * @since 0.3.0
485
+ */
486
+ export const deletedEvent: <C extends Collection.Any>(input: {
487
+ readonly id: string;
488
+ readonly time: string;
489
+ readonly snapshot: DocumentSnapshot.Existing<C>;
490
+ }) => Deleted<C> = internal.deletedEvent;
491
+
492
+ /**
493
+ * Declares a trigger that runs when a document of `collection` that already
494
+ * exists is changed.
495
+ *
496
+ * **When to use**
497
+ *
498
+ * Use to react to changes to existing documents, with the data before and
499
+ * after the change at hand.
500
+ *
501
+ * **Details**
502
+ *
503
+ * Its handler gets an {@link Updated} event, with the document before and
504
+ * after the update. Creating or deleting a document doesn't run it.
505
+ *
506
+ * Firebase delivers each event at least once. Make the handler idempotent,
507
+ * keyed on the event's `id`.
508
+ *
509
+ * @example Reacting to a changed title
510
+ * ```ts
511
+ * import { Effect, Schema } from "effect";
512
+ * import { Collection, FirestoreModel } from "@visiolab/effect-firebase/firestore";
513
+ * import { DocumentTrigger } from "@visiolab/effect-firebase/functions";
514
+ *
515
+ * class Post extends FirestoreModel.Class<Post>("Post")({ title: Schema.String }) {}
516
+ *
517
+ * const OnPostUpdated = DocumentTrigger.updated("onPostUpdated", Collection.make("posts", Post));
518
+ *
519
+ * const OnPostUpdatedLive = DocumentTrigger.toLayer(OnPostUpdated, (event) =>
520
+ * Effect.gen(function* () {
521
+ * const before = yield* event.before.data;
522
+ * const after = yield* event.after.data;
523
+ * if (before.title !== after.title) {
524
+ * yield* Effect.log(`Renamed ${before.title} to ${after.title}`);
525
+ * }
526
+ * }),
527
+ * );
528
+ * ```
529
+ *
530
+ * @see {@link created} for running when a document is created
531
+ * @see {@link deleted} for running when a document is deleted
532
+ * @see {@link written} for running on a create and a delete too
533
+ * @see {@link toLayer} for implementing the trigger
534
+ * @see {@link updatedEvent} for building its event in a test
535
+ * @see {@link FunctionGroup.make} for collecting Functions under one prefix
536
+ *
537
+ * @stability unstable
538
+ * @category constructors
539
+ * @since 0.3.0
540
+ */
541
+ export const updated = <const Name extends string, C extends Collection.Any>(
542
+ name: Name,
543
+ collection: C,
544
+ ): DocumentTrigger<Name, C, "updated"> =>
545
+ internal.make({ kind: internal.kind, name, event: "updated", collection }) as never;
546
+
547
+ /**
548
+ * Builds the event of an {@link updated} trigger from the snapshots of the
549
+ * document before and after the update.
550
+ *
551
+ * **When to use**
552
+ *
553
+ * Use in a test, to run a handler through {@link serve} with an event of
554
+ * your own. The functions package builds its events with it too.
555
+ *
556
+ * **Details**
557
+ *
558
+ * Both snapshots are of the same document. The event's `ref` is the one of
559
+ * `after`. Build each with `DocumentSnapshot.existing`.
560
+ *
561
+ * @example Building an event for a test
562
+ * ```ts
563
+ * import { Schema } from "effect";
564
+ * import { Collection, DocumentSnapshot, FirestoreModel } from "@visiolab/effect-firebase/firestore";
565
+ * import { DocumentTrigger } from "@visiolab/effect-firebase/functions";
566
+ *
567
+ * class Post extends FirestoreModel.Class<Post>("Post")({ title: Schema.String }) {}
568
+ *
569
+ * const Posts = Collection.make("posts", Post);
570
+ * const ref = Posts.doc(Posts.id.make("hello"));
571
+ *
572
+ * const event = DocumentTrigger.updatedEvent({
573
+ * id: "event-1",
574
+ * time: "2026-01-01T00:00:00.000Z",
575
+ * before: DocumentSnapshot.existing(ref, { title: "Draft" }),
576
+ * after: DocumentSnapshot.existing(ref, { title: "Final" }),
577
+ * });
578
+ * ```
579
+ *
580
+ * @see {@link updated} for declaring the trigger
581
+ * @see {@link serve} for running the event through the handler
582
+ * @see {@link Updated} for the event it builds
583
+ *
584
+ * @stability unstable
585
+ * @category constructors
586
+ * @since 0.3.0
587
+ */
588
+ export const updatedEvent: <C extends Collection.Any>(input: {
589
+ readonly id: string;
590
+ readonly time: string;
591
+ readonly before: DocumentSnapshot.Existing<C>;
592
+ readonly after: DocumentSnapshot.Existing<C>;
593
+ }) => Updated<C> = internal.changeEvent;
594
+
595
+ /**
596
+ * Declares a trigger that runs when a document of `collection` is created,
597
+ * updated or deleted.
598
+ *
599
+ * **When to use**
600
+ *
601
+ * Use to handle every change to a collection's documents in one handler, such
602
+ * as keeping a copy or a count in sync. Prefer {@link created},
603
+ * {@link updated} or {@link deleted} when the handler acts on one change only.
604
+ *
605
+ * **Details**
606
+ *
607
+ * Its handler gets a {@link Written} event, whose `before` and `after` are
608
+ * `DocumentSnapshot`s: `before` is `Missing` on a create, and `after` is
609
+ * `Missing` on a delete. Narrow each with `DocumentSnapshot.isExisting` or
610
+ * `DocumentSnapshot.isMissing`.
611
+ *
612
+ * Firebase delivers each event at least once. Make the handler idempotent,
613
+ * keyed on the event's `id`.
614
+ *
615
+ * @example Telling a create, an update and a delete apart
616
+ * ```ts
617
+ * import { Effect, Schema } from "effect";
618
+ * import { Collection, DocumentSnapshot, FirestoreModel } from "@visiolab/effect-firebase/firestore";
619
+ * import { DocumentTrigger } from "@visiolab/effect-firebase/functions";
620
+ *
621
+ * class Post extends FirestoreModel.Class<Post>("Post")({ title: Schema.String }) {}
622
+ *
623
+ * const OnPostWritten = DocumentTrigger.written("onPostWritten", Collection.make("posts", Post));
624
+ *
625
+ * const OnPostWrittenLive = DocumentTrigger.toLayer(OnPostWritten, (event) => {
626
+ * if (DocumentSnapshot.isMissing(event.after)) {
627
+ * return Effect.log(`Deleted ${event.ref.id}`);
628
+ * }
629
+ * const verb = DocumentSnapshot.isExisting(event.before) ? "Updated" : "Created";
630
+ * return Effect.flatMap(event.after.data, (post) => Effect.log(`${verb} ${post.title}`));
631
+ * });
632
+ * ```
633
+ *
634
+ * @see {@link created} for running on a create only, with the document always there
635
+ * @see {@link updated} for running on an update only, with both sides always there
636
+ * @see {@link deleted} for running on a delete only, with the last data always there
637
+ * @see {@link toLayer} for implementing the trigger
638
+ * @see {@link writtenEvent} for building its event in a test
639
+ * @see {@link FunctionGroup.make} for collecting Functions under one prefix
640
+ *
641
+ * @stability unstable
642
+ * @category constructors
643
+ * @since 0.3.0
644
+ */
645
+ export const written = <const Name extends string, C extends Collection.Any>(
646
+ name: Name,
647
+ collection: C,
648
+ ): DocumentTrigger<Name, C, "written"> =>
649
+ internal.make({ kind: internal.kind, name, event: "written", collection }) as never;
650
+
651
+ /**
652
+ * Builds the event of a {@link written} trigger from the snapshots of the
653
+ * document before and after the write.
654
+ *
655
+ * **When to use**
656
+ *
657
+ * Use in a test, to run a handler through {@link serve} with an event of
658
+ * your own. The functions package builds its events with it too.
659
+ *
660
+ * **Details**
661
+ *
662
+ * Both snapshots are of the same document. The event's `ref` is the one of
663
+ * `after`, which a `Missing` snapshot carries too. Build a side that exists
664
+ * with `DocumentSnapshot.existing` and one that doesn't with
665
+ * `DocumentSnapshot.missing`.
666
+ *
667
+ * @example Building the event of a create for a test
668
+ * ```ts
669
+ * import { Schema } from "effect";
670
+ * import { Collection, DocumentSnapshot, FirestoreModel } from "@visiolab/effect-firebase/firestore";
671
+ * import { DocumentTrigger } from "@visiolab/effect-firebase/functions";
672
+ *
673
+ * class Post extends FirestoreModel.Class<Post>("Post")({ title: Schema.String }) {}
674
+ *
675
+ * const Posts = Collection.make("posts", Post);
676
+ * const ref = Posts.doc(Posts.id.make("hello"));
677
+ *
678
+ * const event = DocumentTrigger.writtenEvent({
679
+ * id: "event-1",
680
+ * time: "2026-01-01T00:00:00.000Z",
681
+ * before: DocumentSnapshot.missing(ref),
682
+ * after: DocumentSnapshot.existing(ref, { title: "Hello" }),
683
+ * });
684
+ * ```
685
+ *
686
+ * @see {@link written} for declaring the trigger
687
+ * @see {@link serve} for running the event through the handler
688
+ * @see {@link Written} for the event it builds
689
+ *
690
+ * @stability unstable
691
+ * @category constructors
692
+ * @since 0.3.0
693
+ */
694
+ export const writtenEvent: <C extends Collection.Any>(input: {
695
+ readonly id: string;
696
+ readonly time: string;
697
+ readonly before: DocumentSnapshot.DocumentSnapshot<C>;
698
+ readonly after: DocumentSnapshot.DocumentSnapshot<C>;
699
+ }) => Written<C> = internal.changeEvent;
700
+
701
+ /**
702
+ * Implements a Document Trigger as a Layer.
703
+ *
704
+ * **When to use**
705
+ *
706
+ * Use to write the server side of a trigger. The Layer is what
707
+ * `Functions.make` and `Functions.group` from
708
+ * `@visiolab/effect-firebase-functions` serve, and what {@link serve} runs
709
+ * in a test.
710
+ *
711
+ * **Details**
712
+ *
713
+ * Takes the handler itself, or an Effect that builds it. The Effect runs
714
+ * once, when the Layer is built, so do per-instance setup there.
715
+ *
716
+ * For a trigger in a Function Group, pass the group and the member's name.
717
+ * Each group implements its members separately, so the Layer of the trigger
718
+ * on its own doesn't serve it in a group, and the Layer of one group's
719
+ * member doesn't serve it in another.
720
+ *
721
+ * The Layer requires what the handler needs on each event and what building
722
+ * it needs. Both are provided where the Layer is built, and shared by every
723
+ * event. Reading `snapshot.data` needs what the collection's model needs to
724
+ * decode.
725
+ *
726
+ * Firebase delivers each event at least once. Make the handler idempotent,
727
+ * keyed on the event's `id`.
728
+ *
729
+ * @example Building the handler once per instance
730
+ * ```ts
731
+ * import { Effect, Schema } from "effect";
732
+ * import { Collection, FirestoreModel } from "@visiolab/effect-firebase/firestore";
733
+ * import { DocumentTrigger } from "@visiolab/effect-firebase/functions";
734
+ *
735
+ * class Post extends FirestoreModel.Class<Post>("Post")({ title: Schema.String }) {}
736
+ *
737
+ * const OnPostCreated = DocumentTrigger.created("onPostCreated", Collection.make("posts", Post));
738
+ *
739
+ * const OnPostCreatedLive = DocumentTrigger.toLayer(
740
+ * OnPostCreated,
741
+ * Effect.gen(function* () {
742
+ * const prefix = yield* Effect.succeed("New post");
743
+ * return (event) => Effect.log(`${prefix}: ${event.ref.id}`);
744
+ * }),
745
+ * );
746
+ * ```
747
+ *
748
+ * @example Implementing a trigger in a Function Group
749
+ * ```ts
750
+ * import { Effect, Schema } from "effect";
751
+ * import { Collection, FirestoreModel } from "@visiolab/effect-firebase/firestore";
752
+ * import { Callable, DocumentTrigger, FunctionGroup } from "@visiolab/effect-firebase/functions";
753
+ *
754
+ * class Post extends FirestoreModel.Class<Post>("Post")({ title: Schema.String }) {}
755
+ *
756
+ * const Publish = Callable.make("publish", { payload: { id: Schema.String } });
757
+ * const OnCreated = DocumentTrigger.created("onCreated", Collection.make("posts", Post));
758
+ *
759
+ * class Posts extends FunctionGroup.make("posts").add(Publish, OnCreated) {}
760
+ *
761
+ * // Serves `posts-onCreated`.
762
+ * const OnCreatedLive = DocumentTrigger.toLayer(Posts, "onCreated", (event) =>
763
+ * Effect.log(`New post: ${event.ref.id}`),
764
+ * );
765
+ * ```
766
+ *
767
+ * @see {@link created}, {@link updated}, {@link deleted} and {@link written} for declaring the trigger
768
+ * @see {@link serve} for running an event through the handler
769
+ * @see {@link Callable.toLayer} for implementing a Callable
770
+ * @see {@link FunctionGroup.make} for collecting Functions under one prefix
771
+ *
772
+ * @stability unstable
773
+ * @category constructors
774
+ * @since 0.3.0
775
+ */
776
+ export const toLayer: {
777
+ <T extends Any, R = never, EB = never, RB = never>(
778
+ trigger: T,
779
+ handler: HandlerFunction<T, R> | Effect.Effect<HandlerFunction<T, R>, EB, RB>,
780
+ ): Layer.Layer<HandlerFor<T>, EB, R | RB>;
781
+ <
782
+ G extends FunctionGroup.Any,
783
+ const Name extends FunctionGroup.Names<G, Any>,
784
+ R = never,
785
+ EB = never,
786
+ RB = never,
787
+ >(
788
+ group: G,
789
+ name: Name,
790
+ handler:
791
+ | HandlerFunction<FunctionGroup.Member<G, Name, Any>, R>
792
+ | Effect.Effect<HandlerFunction<FunctionGroup.Member<G, Name, Any>, R>, EB, RB>,
793
+ ): Layer.Layer<Handler<G["identifier"], Name>, EB, R | RB>;
794
+ } = ((...args: ReadonlyArray<unknown>) => {
795
+ const [group, trigger] = target(args);
796
+ // The handler's requirements are checked by the signatures, and provided
797
+ // where the Layer is built.
798
+ return internal.toLayer(
799
+ group?.identifier,
800
+ trigger.name,
801
+ args[group === undefined ? 1 : 2] as internal.HandlerInput,
802
+ );
803
+ }) as never;
804
+
805
+ /**
806
+ * Runs events of a Document Trigger through its handler.
807
+ *
808
+ * **When to use**
809
+ *
810
+ * Use to test a trigger's handler in process, without the emulator and
811
+ * without `firebase-functions`: build an event with {@link createdEvent},
812
+ * {@link updatedEvent}, {@link deletedEvent} or {@link writtenEvent} and
813
+ * provide the Layer from {@link toLayer}. `Functions.make` from
814
+ * `@visiolab/effect-firebase-functions` runs every real event through it too.
815
+ *
816
+ * **Details**
817
+ *
818
+ * Requires the trigger's handler, which it reads once. Returns a function of
819
+ * the event, which fails with whatever the handler fails with.
820
+ *
821
+ * For a trigger in a Function Group, pass the group and the member's name:
822
+ * it then requires the handler from `toLayer(group, name, handler)`.
823
+ *
824
+ * @example Running an event in a test
825
+ * ```ts
826
+ * import { Effect, Schema } from "effect";
827
+ * import { Collection, DocumentSnapshot, FirestoreModel } from "@visiolab/effect-firebase/firestore";
828
+ * import { DocumentTrigger } from "@visiolab/effect-firebase/functions";
829
+ *
830
+ * class Post extends FirestoreModel.Class<Post>("Post")({ title: Schema.String }) {}
831
+ *
832
+ * const Posts = Collection.make("posts", Post);
833
+ * const OnPostCreated = DocumentTrigger.created("onPostCreated", Posts);
834
+ *
835
+ * const OnPostCreatedLive = DocumentTrigger.toLayer(OnPostCreated, (event) =>
836
+ * Effect.flatMap(event.snapshot.data, (post) => Effect.log(post.title)),
837
+ * );
838
+ *
839
+ * const program = DocumentTrigger.serve(OnPostCreated).pipe(
840
+ * Effect.flatMap((run) =>
841
+ * run(
842
+ * DocumentTrigger.createdEvent({
843
+ * id: "event-1",
844
+ * time: "2026-01-01T00:00:00.000Z",
845
+ * snapshot: DocumentSnapshot.existing(Posts.doc(Posts.id.make("hello")), {
846
+ * title: "Hello",
847
+ * }),
848
+ * }),
849
+ * ),
850
+ * ),
851
+ * Effect.provide(OnPostCreatedLive),
852
+ * );
853
+ * ```
854
+ *
855
+ * @see {@link toLayer} for providing the handler
856
+ * @see {@link createdEvent} for building the event of a `created` trigger
857
+ * @see {@link deletedEvent} for building the event of a `deleted` trigger
858
+ * @see {@link updatedEvent} for building the event of an `updated` trigger
859
+ * @see {@link writtenEvent} for building the event of a `written` trigger
860
+ * @see {@link Functions.make} for deploying the trigger through `firebase-functions`
861
+ * @see {@link Callable.serve} for running a call to a Callable
862
+ *
863
+ * @stability unstable
864
+ * @category serving
865
+ * @since 0.3.0
866
+ */
867
+ export const serve: {
868
+ <T extends Any>(
869
+ trigger: T,
870
+ ): Effect.Effect<(event: Event<T>) => Effect.Effect<void, unknown>, never, HandlerFor<T>>;
871
+ <G extends FunctionGroup.Any, const Name extends FunctionGroup.Names<G, Any>>(
872
+ group: G,
873
+ name: Name,
874
+ ): Effect.Effect<
875
+ (event: Event<FunctionGroup.Member<G, Name, Any>>) => Effect.Effect<void, unknown>,
876
+ never,
877
+ Handler<G["identifier"], Name>
878
+ >;
879
+ } = ((...args: ReadonlyArray<unknown>) => internal.serve(...target(args))) as never;
880
+
881
+ /**
882
+ * Where a Document Trigger is deployed: the name it is exported under and
883
+ * the path pattern of the documents it watches.
884
+ *
885
+ * @stability unstable
886
+ * @category models
887
+ * @since 0.3.0
888
+ */
889
+ export interface Deployment {
890
+ /**
891
+ * The name the trigger is deployed under: its own in no group, and
892
+ * `<group>-<name>` in a group.
893
+ */
894
+ readonly name: string;
895
+ /**
896
+ * The path pattern of the documents it watches, with a wildcard for each
897
+ * parent document's id and for the document's id. The wildcards' names are
898
+ * not part of the API: read the ids from the event's `ref`.
899
+ */
900
+ readonly document: string;
901
+ }
902
+
903
+ /**
904
+ * Returns the {@link Deployment} of a Document Trigger: its deployed name and
905
+ * its document path pattern. A building block of the functions package. Most
906
+ * apps don't need it.
907
+ *
908
+ * **When to use**
909
+ *
910
+ * Use when deploying triggers with a transport of your own. `Functions`
911
+ * already uses it.
912
+ *
913
+ * **Details**
914
+ *
915
+ * Pass the trigger for one in no group, or a Function Group and a trigger
916
+ * member's name for one in a group, which is deployed as `<group>-<name>`.
917
+ *
918
+ * @see {@link Callable.deployment} for where a Callable is served
919
+ *
920
+ * @stability unstable
921
+ * @category serving
922
+ * @since 0.3.0
923
+ */
924
+ export const deployment: {
925
+ (trigger: Any): Deployment;
926
+ <G extends FunctionGroup.Any>(group: G, name: FunctionGroup.Names<G, Any>): Deployment;
927
+ } = ((...args: ReadonlyArray<unknown>) => internal.deployment(...target(args))) as never;