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