@visiolab/effect-firebase 0.0.0-stage → 0.3.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 (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 +66 -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,1232 @@
1
+ import { ArrayOr, DeleteField, DeleteFieldOr, IncrementOr, ServerTimestampOr, TimeSchema } from "./FirestoreSchema.mjs";
2
+ import { Replace } from "./Patch.mjs";
3
+ import { Schema, SchemaAST, Struct as Struct$1, Types } from "effect";
4
+ import { VariantSchema } from "effect/schema";
5
+ declare namespace FirestoreModel_d_exports {
6
+ export { Any, Array, Class, Field, FieldExcept, FieldOnly, Immutable, Number, Optional, Record, Struct, Timestamp, Union, UnionUpdate, Update, UpdateFields, UpdateMode, UpdatePaths, Value, Variant, extract, fieldEvolve, fields };
7
+ }
8
+ /**
9
+ * The shapes a document is read and written in.
10
+ *
11
+ * **Details**
12
+ *
13
+ * - `read` is what a snapshot's data decodes into.
14
+ * - `create` is what `setDoc` writes: a whole document.
15
+ * - `update` is what `updateDoc` writes: the fields that change.
16
+ *
17
+ * `read` is the default variant, so a {@link Class} itself is the read shape
18
+ * and the write shapes hang off it.
19
+ *
20
+ * @stability unstable
21
+ * @category models
22
+ * @since 0.2.0
23
+ */
24
+ export type Variant = "read" | "create" | "update";
25
+ /**
26
+ * Declares a field with a different schema per variant.
27
+ *
28
+ * **When to use**
29
+ *
30
+ * Use when a field is read and written in shapes no ready-made field covers.
31
+ * Leave a variant out to keep the field out of that shape.
32
+ *
33
+ * @example A field written as a sentinel and read as a timestamp
34
+ * ```ts
35
+ * import { FirestoreModel, FirestoreSchema } from "@visiolab/effect-firebase/firestore";
36
+ *
37
+ * class Post extends FirestoreModel.Class<Post>("Post")({
38
+ * publishedAt: FirestoreModel.Field({
39
+ * read: FirestoreSchema.Timestamp,
40
+ * create: FirestoreSchema.ServerTimestamp,
41
+ * }),
42
+ * }) {}
43
+ * ```
44
+ *
45
+ * @see {@link FieldOnly} for the same schema in some variants
46
+ * @see {@link FieldExcept} for the same schema in all but some variants
47
+ * @see {@link Timestamp} for a timestamp the client or the server may set
48
+ *
49
+ * @stability unstable
50
+ * @category constructors
51
+ * @since 0.2.0
52
+ */
53
+ export declare const Field: <const A extends VariantSchema.Field.ConfigWithKeys<"create" | "read" | "update">>(config: A & { readonly [K in Exclude<keyof A, "create" | "read" | "update">]: never; }) => VariantSchema.Field<A>;
54
+ /**
55
+ * Declares a field with one schema that appears only in the named variants.
56
+ *
57
+ * **When to use**
58
+ *
59
+ * Use for a field only some shapes carry, such as one only ever read, or one
60
+ * only ever written.
61
+ *
62
+ * @example A field only read
63
+ * ```ts
64
+ * import { Schema } from "effect";
65
+ * import { FirestoreModel } from "@visiolab/effect-firebase/firestore";
66
+ *
67
+ * class Account extends FirestoreModel.Class<Account>("Account")({
68
+ * plan: FirestoreModel.FieldOnly(["read"])(Schema.Literals(["free", "paid"])),
69
+ * }) {}
70
+ * ```
71
+ *
72
+ * @see {@link FieldExcept} for naming the variants to leave out instead
73
+ * @see {@link Field} for a different schema per variant
74
+ * @see {@link Immutable} for a field read and created, but never updated
75
+ *
76
+ * @stability unstable
77
+ * @category constructors
78
+ * @since 0.2.0
79
+ */
80
+ export declare const FieldOnly: <const Keys extends ReadonlyArray<"create" | "read" | "update">>(keys: Keys) => <S extends Schema.Top>(schema: S) => VariantSchema.Field<{ readonly [K in Keys[number]]: S; }>;
81
+ /**
82
+ * Declares a field with one schema that appears in every variant but the named
83
+ * ones.
84
+ *
85
+ * **When to use**
86
+ *
87
+ * Use when a field belongs in most shapes and only a few leave it out.
88
+ *
89
+ * @see {@link FieldOnly} for naming the variants to keep instead
90
+ * @see {@link Field} for a different schema per variant
91
+ *
92
+ * @stability unstable
93
+ * @category constructors
94
+ * @since 0.2.0
95
+ */
96
+ export declare const FieldExcept: <const Keys extends ReadonlyArray<"create" | "read" | "update">>(keys: Keys) => <S extends Schema.Top>(schema: S) => VariantSchema.Field<{ readonly [K in Exclude<"create", Keys[number]> | Exclude<"read", Keys[number]> | Exclude<"update", Keys[number]>]: S; }>;
97
+ /**
98
+ * Declares a set of fields without building a class.
99
+ *
100
+ * **When to use**
101
+ *
102
+ * Use for a nested map inside a document, or for fields shared between several
103
+ * documents. An update reaches into a struct field by field, unlike a plain
104
+ * `Schema.Struct`, which is a value written whole.
105
+ *
106
+ * @example A nested address
107
+ * ```ts
108
+ * import { Schema } from "effect";
109
+ * import { FirestoreModel } from "@visiolab/effect-firebase/firestore";
110
+ *
111
+ * const Address = FirestoreModel.Struct({ city: Schema.String, zip: Schema.String });
112
+ *
113
+ * class Customer extends FirestoreModel.Class<Customer>("Customer")({
114
+ * address: Address,
115
+ * }) {}
116
+ *
117
+ * Customer.update.make({ address: { city: "Berlin" } }); // written at "address.city"
118
+ * ```
119
+ *
120
+ * @see {@link Class} for a whole document
121
+ * @see {@link Patch.replace} for writing a struct whole in an update
122
+ *
123
+ * @stability unstable
124
+ * @category constructors
125
+ * @since 0.2.0
126
+ */
127
+ export declare const Struct: <const A extends VariantSchema.Struct.Fields>(fields: A & VariantSchema.Struct.Validate<A, "create" | "read" | "update">) => VariantSchema.Struct<A>;
128
+ /**
129
+ * Rewrites the schemas of a field, variant by variant.
130
+ *
131
+ * **When to use**
132
+ *
133
+ * Use to derive a field from another one, such as narrowing what one variant
134
+ * takes while keeping the others.
135
+ *
136
+ * @see {@link Field} for declaring a field per variant directly
137
+ *
138
+ * @stability unstable
139
+ * @category transforming
140
+ * @since 0.2.0
141
+ */
142
+ export declare const fieldEvolve: {
143
+ <Self extends VariantSchema.Field<any> | Schema.Top, const Mapping extends (Self extends VariantSchema.Field<infer S> ? { readonly [K in keyof S]?: (variant: S[K]) => Schema.Top; } : { readonly [K in "create" | "read" | "update"]?: (variant: Self) => Schema.Top; })>(f: Mapping): (self: Self) => VariantSchema.Field<Self extends VariantSchema.Field<infer S extends VariantSchema.Field.Config> ? { readonly [K in keyof S]: K extends keyof Mapping ? Mapping[K] extends ((arg: any) => any) ? ReturnType<Mapping[K]> : S[K] : S[K]; } : {
144
+ readonly create: "create" extends (infer T) ? T extends "create" ? T extends keyof Mapping ? Mapping[T] extends ((arg: any) => any) ? ReturnType<Mapping[T]> : Self : Self : never : never;
145
+ readonly read: "read" extends (infer T_1) ? T_1 extends "read" ? T_1 extends keyof Mapping ? Mapping[T_1] extends ((arg: any) => any) ? ReturnType<Mapping[T_1]> : Self : Self : never : never;
146
+ readonly update: "update" extends (infer T_2) ? T_2 extends "update" ? T_2 extends keyof Mapping ? Mapping[T_2] extends ((arg: any) => any) ? ReturnType<Mapping[T_2]> : Self : Self : never : never;
147
+ }>;
148
+ <Self extends VariantSchema.Field<any> | Schema.Top, const Mapping extends (Self extends VariantSchema.Field<infer S> ? { readonly [K in keyof S]?: (variant: S[K]) => Schema.Top; } : { readonly [K in "create" | "read" | "update"]?: (variant: Self) => Schema.Top; })>(self: Self, f: Mapping): VariantSchema.Field<Self extends VariantSchema.Field<infer S extends VariantSchema.Field.Config> ? { readonly [K in keyof S]: K extends keyof Mapping ? Mapping[K] extends ((arg: any) => any) ? ReturnType<Mapping[K]> : S[K] : S[K]; } : {
149
+ readonly create: "create" extends (infer T) ? T extends "create" ? T extends keyof Mapping ? Mapping[T] extends ((arg: any) => any) ? ReturnType<Mapping[T]> : Self : Self : never : never;
150
+ readonly read: "read" extends (infer T_1) ? T_1 extends "read" ? T_1 extends keyof Mapping ? Mapping[T_1] extends ((arg: any) => any) ? ReturnType<Mapping[T_1]> : Self : Self : never : never;
151
+ readonly update: "update" extends (infer T_2) ? T_2 extends "update" ? T_2 extends keyof Mapping ? Mapping[T_2] extends ((arg: any) => any) ? ReturnType<Mapping[T_2]> : Self : Self : never : never;
152
+ }>;
153
+ };
154
+ /**
155
+ * Pulls one variant out of a struct as a plain schema.
156
+ *
157
+ * **When to use**
158
+ *
159
+ * Use to get a struct's `read` or `create` shape as an ordinary schema, for
160
+ * example to validate data outside Firestore.
161
+ *
162
+ * **Details**
163
+ *
164
+ * The `update` variant it returns is the one the fields declare: it is neither
165
+ * made partial nor flattened into paths. Use {@link Class.update} for the
166
+ * update a document is written through.
167
+ *
168
+ * @see {@link fields} for the field declarations themselves
169
+ *
170
+ * @stability unstable
171
+ * @category converting
172
+ * @since 0.2.0
173
+ */
174
+ export declare const extract: {
175
+ <V extends "create" | "read" | "update">(variant: V): <A extends VariantSchema.Struct<any>>(self: A) => VariantSchema.Extract<V, A, V extends "read" ? true : false>;
176
+ <V extends "create" | "read" | "update", A extends VariantSchema.Struct<any>>(self: A, variant: V): VariantSchema.Extract<V, A, V extends "read" ? true : false>;
177
+ };
178
+ /**
179
+ * Returns the field declarations a {@link Class} or {@link Struct} was built
180
+ * from.
181
+ *
182
+ * **When to use**
183
+ *
184
+ * Use to build a new struct or class from the fields of an existing one.
185
+ *
186
+ * @see {@link extract} for one variant of a struct as a plain schema
187
+ *
188
+ * @stability unstable
189
+ * @category getters
190
+ * @since 0.2.0
191
+ */
192
+ export declare const fields: <A extends VariantSchema.Struct<any>>(self: A) => A[typeof VariantSchema.TypeId];
193
+ /**
194
+ * Any document schema: a {@link Class}, or a {@link Union} of classes.
195
+ *
196
+ * **Details**
197
+ *
198
+ * Unlike Effect's `Model.Any`, it asks for no `fields`: nothing that takes it
199
+ * reads them, and a union has none.
200
+ *
201
+ * @stability unstable
202
+ * @category models
203
+ * @since 0.2.0
204
+ */
205
+ export type Any = Schema.Top & {
206
+ readonly create: Schema.Top;
207
+ readonly update: Schema.Top;
208
+ readonly updateUnchecked: Schema.Top;
209
+ };
210
+ declare const RecordTypeId = "~@visiolab/effect-firebase/firestore/FirestoreModel/Record";
211
+ declare const UnionTypeId = "~@visiolab/effect-firebase/firestore/FirestoreModel/Union";
212
+ /**
213
+ * Anything a field may be declared as: a schema, a field, a struct or a
214
+ * {@link Record}.
215
+ *
216
+ * @stability unstable
217
+ * @category models
218
+ * @since 0.2.0
219
+ */
220
+ export type Value = VariantSchema.Field<any> | VariantSchema.Struct<any> | Schema.Top;
221
+ /** The schema a field is written through in `V`, or `never` where it is not. */
222
+ type VariantSchemaOf<F, V extends "create" | "update"> = F extends VariantSchema.Field<infer S> ? V extends keyof S ? S[V] extends Schema.Top ? S[V] : never : never : F extends Schema.Top ? F : never;
223
+ /** The schema a field is updated through, or `never` where it cannot be. */
224
+ type UpdateSchema<F> = VariantSchemaOf<F, "update">;
225
+ /** The schema `S` is made from, where it is made an optional key. */
226
+ type WithoutOptionalKey<S extends Schema.Top> = S extends Schema.optionalKey<infer X extends Schema.Top> ? X : S;
227
+ /** The keys out of `K` that are known up front, which a Record holds every one of. */
228
+ type KnownKeys<K> = K extends PropertyKey ? {} extends { readonly [_ in K]: unknown; } ? never : K : never;
229
+ /** Whether a Record keyed by `K` holds keys only the data names. */
230
+ type IsOpen<K extends Schema.Record.Key> = [Exclude<K["Type"], KnownKeys<K["Type"]>>] extends [never] ? false : true;
231
+ /** The schema `V` is declared as in `Variant`, or `never` where it has none. */
232
+ type ValueSchema<V, Variant extends "read" | "create"> = V extends VariantSchema.Struct<any> ? VariantSchema.Extract<Variant, V> : V extends VariantSchema.Field<infer S> ? Variant extends keyof S ? S[Variant] extends Schema.Top ? S[Variant] : never : never : V extends Schema.Top ? V : never;
233
+ /** A Record of `S` keyed by `K`, as a document holds it. */
234
+ type RecordSchema<K extends Schema.Record.Key, S extends Schema.Top> = Schema.$Record<K, IsOpen<K> extends true ? WithoutOptionalKey<S> : S>;
235
+ /** Any field made {@link Optional}, whatever it holds. */
236
+ type AnyOptional = {
237
+ readonly "~optionality": "optional";
238
+ readonly field: Value;
239
+ };
240
+ /** Whether a field was made {@link Optional}. */
241
+ type IsOptional<F> = F extends AnyOptional ? true : false;
242
+ /** What a field was made {@link Optional} of, or the field itself where it was not. */
243
+ type Unwrap<F> = F extends AnyOptional ? F["field"] : F;
244
+ /** The key and the value of a Record a field is, or `never` where it is none. */
245
+ type RecordOf<F> = RecordParts<Unwrap<F>>;
246
+ /** The key and the value a Record field carries, or `never` where it is none. */
247
+ type RecordParts<F> = F extends {
248
+ readonly [RecordTypeId]: {
249
+ readonly key: infer K extends Schema.Record.Key;
250
+ readonly value: infer V extends Value;
251
+ };
252
+ } ? {
253
+ readonly key: K;
254
+ readonly value: V;
255
+ } : never;
256
+ /** Whether `V` is something an update reaches into: a struct or a Record. */
257
+ type IsNode<V> = Unwrap<V> extends VariantSchema.Struct<any> | {
258
+ readonly [RecordTypeId]: any;
259
+ } | {
260
+ readonly [UnionTypeId]: any;
261
+ } ? true : false;
262
+ /** Whether an update writes anything into a Record of `V`, at any depth. */
263
+ type IsWritable<V extends Value> = [RecordOf<V>] extends [never] ? [UnionOf<V>] extends [never] ? IsNode<V> extends true ? true : [UpdateSchema<V>] extends [never] ? false : true : IsUnionWritable<UnionOf<V>, IsOptional<V>> : IsWritable<RecordOf<V>["value"]>;
264
+ /**
265
+ * The fields of a Record at the keys out of `Keys` known up front, as a struct
266
+ * holds them: decoded for its patch, encoded for its paths.
267
+ */
268
+ type KnownFields<Keys, V extends Value> = { readonly [_ in KnownKeys<Keys> & string]: V; };
269
+ /** What a key of a Record only the data names takes, which may be missing. */
270
+ type EntryUpdate<V extends Value, Mode extends UpdateMode> = Unwrap<V> extends VariantSchema.Struct<infer G> ? StructTakes<G, true, Mode> : [UnionOf<V>] extends [never] ? EntryValueUpdate<V, Mode> : UnionTakes<UnionOf<V>, true, Mode>;
271
+ /** What a key of a Record only the data names takes, where it is no struct or union. */
272
+ type EntryValueUpdate<V extends Value, Mode extends UpdateMode> = [RecordOf<V>] extends [never] ? DeleteFieldOr<WithoutOptionalKey<UpdateSchema<V>>> : RecordTakes<RecordOf<V>["key"], RecordOf<V>["value"], true, Mode>;
273
+ /** The patch of a Record: key by key. */
274
+ type RecordPatch<K extends Schema.Record.Key, V extends Value, Mode extends UpdateMode> = IsOpen<K> extends true ? Schema.$Record<Schema.toType<K>, EntryUpdate<V, Mode>> : Schema.Struct<UpdateFields<KnownFields<K["Type"], V>, Mode>>;
275
+ /**
276
+ * What a Record takes in `Mode`. One keyed by keys only the data names is
277
+ * patched even where it may be missing, since every key of it may be missing
278
+ * as well.
279
+ */
280
+ type RecordTakes<K extends Schema.Record.Key, V extends Value, Optional extends boolean, Mode extends UpdateMode> = Schema.Union<readonly [...(Optional extends true ? Mode extends "unchecked" ? [RecordPatch<K, V, Mode>] : IsOpen<K> extends true ? [RecordPatch<K, V, Mode>] : [] : [RecordPatch<K, V, Mode>]), ...(IsReplaceable<{
281
+ readonly _: V;
282
+ }> extends true ? [ReplaceSchema<RecordSchema<K, ValueSchema<V, "create">>>] : []), ...(Optional extends true ? [DeleteField] : [])]>;
283
+ /** The schemas written anywhere at or below a key of a Record only the data names. */
284
+ type EntryPaths<V extends Value, Mode extends UpdateMode> = WithoutOptionalKey<Extract<UpdatePaths<{
285
+ readonly _: AsEntry<V>;
286
+ }, Mode>[keyof UpdatePaths<{
287
+ readonly _: AsEntry<V>;
288
+ }, Mode>], Schema.Top>>;
289
+ /** `V` as a key of a Record only the data names, which may be missing. */
290
+ type AsEntry<V extends Value> = IsNode<V> extends true ? V extends AnyOptional ? V : Optional<V> : VariantSchema.Field<{
291
+ readonly update: DeleteFieldOr<WithoutOptionalKey<UpdateSchema<V>>>;
292
+ }>;
293
+ /** The paths a Record at `Path` is written at. */
294
+ type RecordPaths<K extends Schema.Record.Key, V extends Value, Optional extends boolean, Mode extends UpdateMode, Path extends string> = IsWritable<V> extends false ? {} : (Optional extends true ? { readonly [_ in Path]: Schema.optionalKey<IsReplaceable<{
295
+ readonly _: V;
296
+ }> extends true ? DeleteFieldOr<RecordSchema<K, ValueSchema<V, "create">>> : DeleteField>; } : IsReplaceable<{
297
+ readonly _: V;
298
+ }> extends true ? { readonly [_ in Path]: Schema.optionalKey<RecordSchema<K, ValueSchema<V, "create">>>; } : {}) & (IsOpen<K> extends true ? { readonly [_ in `${Path}.${string}`]: EntryPaths<V, Mode>; } : UpdatePaths<KnownFields<K["Encoded"], V>, Mode, `${Path}.`>);
299
+ /** The paths a struct at `Path` is written at. */
300
+ type StructPaths<Fields extends VariantSchema.Struct.Fields, Optional extends boolean, Mode extends UpdateMode, Path extends string> = (Optional extends true ? { readonly [_ in Path]: Schema.optionalKey<IsReplaceable<Fields> extends true ? DeleteFieldOr<WholeStruct<Fields>> : DeleteField>; } : IsReplaceable<Fields> extends true ? { readonly [_ in Path]: Schema.optionalKey<WholeStruct<Fields>>; } : {}) & UpdatePaths<Fields, Mode, `${Path}.`>;
301
+ /**
302
+ * Which patches an update takes: `"checked"` or `"unchecked"`.
303
+ *
304
+ * **When to use**
305
+ *
306
+ * Use `"checked"`, the default, unless the caller knows what the document
307
+ * holds. Use `"unchecked"` to patch an {@link Optional} struct or union, or a
308
+ * key only some members of a {@link Union} hold, after an earlier read, in a
309
+ * transaction, or with a query that only matches such documents.
310
+ *
311
+ * **Details**
312
+ *
313
+ * Firestore applies an update to whatever the document holds without checking
314
+ * it, and a patch does not say which member of a union the document holds.
315
+ *
316
+ * - `checked` takes only patches that leave any document readable. An
317
+ * {@link Optional} struct is written whole with {@link Patch.replace} or
318
+ * removed, never patched: a patch written into a missing struct would create
319
+ * it holding only the patch. A {@link Union} is patched only at its Shared
320
+ * Fields, the fields every member holds, with a value every member takes and
321
+ * stores the same way. An {@link Optional} union is not patched at all.
322
+ * - `unchecked` also patches an {@link Optional} struct or union, and a key
323
+ * only some members of a union hold. That key is checked by the same rule as
324
+ * a Shared Field, over just the members that hold it: each must take the
325
+ * value and store it the same way.
326
+ *
327
+ * A patch is checked against every member of a union rather than the first it
328
+ * matches, since a patch one member takes could leave a document holding
329
+ * another unreadable - by exceeding its maximum length, say, or storing a
330
+ * `Date` as a timestamp where it holds a string.
331
+ *
332
+ * The modes differ only in which patches they take. A patch both take is
333
+ * written the same way, at the same paths.
334
+ *
335
+ * @see {@link Class.update} for the checked update of a document
336
+ * @see {@link Class.updateUnchecked} for the unchecked one
337
+ * @see {@link Firestore.UpdateOptions} for choosing the mode of `updateDoc`
338
+ * @see {@link Firestore.With.updateDoc} for writing an update
339
+ *
340
+ * @stability unstable
341
+ * @category models
342
+ * @since 0.2.0
343
+ */
344
+ export type UpdateMode = "checked" | "unchecked";
345
+ /** The fields of the struct a field reaches into, or `never` if it is none. */
346
+ type StructOf<F> = Unwrap<F> extends VariantSchema.Struct<infer G> ? G : never;
347
+ /**
348
+ * Whether a struct may be written whole by an update: only where every field it
349
+ * holds, at any depth, is written both by `set`, whose shape a replacement
350
+ * takes, and by an update.
351
+ */
352
+ type IsReplaceable<Fields extends VariantSchema.Struct.Fields> = false extends { [K in keyof Fields]: [UnionOf<Fields[K]>] extends [never] ? FieldIsReplaceable<Fields[K]> : AreReplaceable<UnionOf<Fields[K]>>; }[keyof Fields] ? false : true;
353
+ /** Whether a field that is no union may be written whole by an update. */
354
+ type FieldIsReplaceable<F> = [RecordOf<F>] extends [never] ? [StructOf<F>] extends [never] ? [UpdateSchema<F>] extends [never] ? false : [VariantSchemaOf<F, "create">] extends [never] ? false : true : IsReplaceable<StructOf<F>> : IsWritable<RecordOf<F>["value"]> extends true ? IsReplaceable<{
355
+ readonly _: RecordOf<F>["value"];
356
+ }> : false;
357
+ /** The shape a struct is written whole in, as `set` would write it. */
358
+ type WholeStruct<Fields extends VariantSchema.Struct.Fields> = VariantSchema.Extract<"create", VariantSchema.Struct<Fields>>;
359
+ /**
360
+ * The schema of a {@link Patch.replace} of a struct written whole as `S`. It is
361
+ * made from what `S` is made from, so the constructor defaults of the struct
362
+ * are filled in.
363
+ */
364
+ interface ReplaceSchema<S extends Schema.Top> extends Schema.Bottom<Replace<S["Type"]>, Replace<S["Type"]>, never, never, SchemaAST.Declaration, ReplaceSchema<S>, Replace<S["~type.make.in"]>> {}
365
+ /** What a struct takes in `Mode`, as a field of the struct it sits in. */
366
+ type StructUpdate<Fields extends VariantSchema.Struct.Fields, Optional extends boolean, Mode extends UpdateMode> = Schema.optionalKey<StructTakes<Fields, Optional, Mode>>;
367
+ /** What a struct takes in `Mode`. */
368
+ type StructTakes<Fields extends VariantSchema.Struct.Fields, Optional extends boolean, Mode extends UpdateMode> = Schema.Union<readonly [...(Optional extends true ? Mode extends "unchecked" ? [Schema.Struct<UpdateFields<Fields, Mode>>] : [] : [Schema.Struct<UpdateFields<Fields, Mode>>]), ...(IsReplaceable<Fields> extends true ? [ReplaceSchema<WholeStruct<Fields>>] : []), ...(Optional extends true ? [DeleteField] : [])]>;
369
+ /**
370
+ * The fields of an update in `Mode`: every field that may change, each one
371
+ * optional.
372
+ *
373
+ * **Details**
374
+ *
375
+ * A struct every document holds takes a patch of its own. An {@link Optional}
376
+ * struct takes the removal, and a patch only under `unchecked` - see
377
+ * {@link UpdateMode}. Either takes {@link Patch.replace} where an update writes
378
+ * every field it holds.
379
+ *
380
+ * @see {@link UpdatePaths} for the paths these fields are written at
381
+ *
382
+ * @stability unstable
383
+ * @category models
384
+ * @since 0.2.0
385
+ */
386
+ export type UpdateFields<Fields extends VariantSchema.Struct.Fields, Mode extends UpdateMode = "checked"> = { readonly [K in keyof Fields as FieldUpdate<Fields[K], Mode> extends never ? never : K]: FieldUpdate<Fields[K], Mode>; };
387
+ /** What a field takes in an update in `Mode`, or `never` where it takes nothing. */
388
+ type FieldUpdate<F, Mode extends UpdateMode> = Unwrap<F> extends VariantSchema.Struct<infer G> ? StructUpdate<G, IsOptional<F>, Mode> : [UnionOf<F>] extends [never] ? ValueUpdate<F, Mode> : UnionFieldUpdate<UnionOf<F>, IsOptional<F>, Mode>;
389
+ /** What a field that is no struct or union takes in an update in `Mode`. */
390
+ type ValueUpdate<F, Mode extends UpdateMode> = [RecordOf<F>] extends [never] ? [UpdateSchema<F>] extends [never] ? never : Schema.optionalKey<UpdateSchema<F>> : RecordUpdate<RecordOf<F>, IsOptional<F>, Mode>;
391
+ /**
392
+ * The services the key of each Record an update writes into takes to encode,
393
+ * which an update encodes every key it writes at with.
394
+ */
395
+ type KeyServices<Fields extends VariantSchema.Struct.Fields> = { [K in keyof Fields]: FieldKeyServices<Fields[K]>; }[keyof Fields];
396
+ /** The services the keys of the Records a field holds take to encode. */
397
+ type FieldKeyServices<F> = Unwrap<F> extends VariantSchema.Struct<infer G> ? KeyServices<G> : [RecordOf<F>] extends [never] ? never : IsWritable<RecordOf<F>["value"]> extends true ? RecordOf<F>["key"]["EncodingServices"] | FieldKeyServices<RecordOf<F>["value"]> : never;
398
+ /** What a Record takes as a field of the struct it sits in. */
399
+ type RecordUpdate<P extends {
400
+ readonly key: Schema.Record.Key;
401
+ readonly value: Value;
402
+ }, Optional extends boolean, Mode extends UpdateMode> = IsWritable<P["value"]> extends true ? Schema.optionalKey<RecordTakes<P["key"], P["value"], Optional, Mode>> : never;
403
+ /**
404
+ * The fields an update is encoded as: one optional key per path it can write
405
+ * to, such as `"address.city"`.
406
+ *
407
+ * **Details**
408
+ *
409
+ * A struct's own key takes the struct written whole, where an update writes
410
+ * every field it holds, and the removal, where it is {@link Optional}. A
411
+ * struct that takes neither has no key of its own and is only written field by
412
+ * field.
413
+ *
414
+ * The paths are the same in either {@link UpdateMode}.
415
+ *
416
+ * @see {@link UpdateFields} for the nested patch these paths are encoded from
417
+ *
418
+ * @stability unstable
419
+ * @category models
420
+ * @since 0.2.0
421
+ */
422
+ export type UpdatePaths<Fields extends VariantSchema.Struct.Fields, Mode extends UpdateMode = "checked", Prefix extends string = ""> = Struct$1.Simplify<Types.UnionToIntersection<{ [K in keyof Fields & string]: Unwrap<Fields[K]> extends VariantSchema.Struct<infer G> ? StructPaths<G, IsOptional<Fields[K]>, Mode, `${Prefix}${K}`> : [UnionOf<Fields[K]>] extends [never] ? ValuePaths<Fields[K], Mode, `${Prefix}${K}`> : UnionPaths<UnionOf<Fields[K]>, IsOptional<Fields[K]>, `${Prefix}${K}`>; }[keyof Fields & string]> & {}>;
423
+ /** The paths a field that is no struct or union is written at. */
424
+ type ValuePaths<F, Mode extends UpdateMode, Path extends string> = [RecordOf<F>] extends [never] ? [UpdateSchema<F>] extends [never] ? {} : { readonly [_ in Path]: Schema.optionalKey<UpdateSchema<F>>; } : RecordPaths<RecordOf<F>["key"], RecordOf<F>["value"], IsOptional<F>, Mode, Path>;
425
+ /**
426
+ * The `update` variant of a set of fields, taking the patches `Mode` allows.
427
+ *
428
+ * **Details**
429
+ *
430
+ * It takes a nested partial - the fields that change, with a struct carrying
431
+ * only its own fields that change - and encodes each one at its path, so
432
+ * `{ address: { city } }` becomes `{ "address.city": city }`. That makes an
433
+ * update a merge: Firestore replaces a map it is handed as a value, but a path
434
+ * counts as the top level and leaves the rest of the map alone. It also lets a
435
+ * sentinel sit at any depth, which matters for removal: Firestore only takes
436
+ * `deleteField` at the top level of an update.
437
+ *
438
+ * - A {@link Struct} or class is reached into. Handed {@link Patch.replace},
439
+ * it is written whole at its path, as `setDoc` would write it, and one made
440
+ * {@link Optional} may also be removed.
441
+ * - Any other schema, a plain `Schema.Struct` included, is a value and is
442
+ * written whole. The patch decides which, not the key - see `Patch`.
443
+ * - A {@link Union} is replaced with one of its members, removed where it is
444
+ * {@link Optional}, and patched at its Shared Fields, each at its path.
445
+ * - A struct holding a field that `setDoc` or an update leaves out -
446
+ * {@link Immutable}, or a read-only field - is never replaced, since that
447
+ * would change or drop the field. It is patched where every document holds
448
+ * it, and a checked update only removes it where it is {@link Optional}.
449
+ *
450
+ * Under `checked`, a patch into an {@link Optional} struct or union is refused,
451
+ * by the type and by the encoding, since written into a missing struct it
452
+ * creates one holding only the patch. Under `unchecked` it is taken - see
453
+ * {@link UpdateMode}.
454
+ *
455
+ * A patch of a union's Shared Field is checked against every member: its type
456
+ * is what every member's update takes there, so the literal the members are
457
+ * told apart by is never shared, and its value is encoded through every member,
458
+ * each of which must store it as the same Firestore Value. Otherwise it fails
459
+ * with a schema issue. A sentinel is taken where every member takes it.
460
+ *
461
+ * The patch it takes is `Update.to`, and the paths it writes are `Update.from`.
462
+ * It is only ever written: decoding fails, since a document is never read in
463
+ * this shape.
464
+ *
465
+ * @see {@link UpdateFields} for the patch it takes
466
+ * @see {@link UpdatePaths} for the paths it writes
467
+ *
468
+ * @stability unstable
469
+ * @category models
470
+ * @since 0.2.0
471
+ */
472
+ export interface Update<in out Fields extends VariantSchema.Struct.Fields, in out Mode extends UpdateMode = "checked"> extends Schema.decodeTo<Schema.toType<Schema.Struct<UpdateFields<Fields, Mode>>>, Schema.Struct<UpdatePaths<Fields, Mode> extends (infer P extends Schema.Struct.Fields) ? P : never>, never, KeyServices<Fields>> {}
473
+ /**
474
+ * Type-level representation of {@link Class}: a document schema together with
475
+ * the shapes it is written in.
476
+ *
477
+ * @stability unstable
478
+ * @category models
479
+ * @since 0.2.0
480
+ */
481
+ export interface Class<Self, Fields extends VariantSchema.Struct.Fields> extends VariantSchema.Class<Self, Fields, Schema.Struct<VariantSchema.ExtractFields<"read", Fields, true>>> {
482
+ /** The shape a snapshot decodes into, which is the class itself. */
483
+ readonly read: VariantSchema.Extract<"read", VariantSchema.Struct<Fields>>;
484
+ /**
485
+ * The shape `setDoc` and `addDoc` write: a whole document, taking the
486
+ * sentinels and constructor defaults its fields declare.
487
+ */
488
+ readonly create: VariantSchema.Extract<"create", VariantSchema.Struct<Fields>>;
489
+ /**
490
+ * The shape `updateDoc` writes, taking only patches that leave any document
491
+ * readable.
492
+ *
493
+ * **When to use**
494
+ *
495
+ * Use for every update unless the caller knows what the document holds.
496
+ *
497
+ * **Details**
498
+ *
499
+ * An {@link Optional} struct is replaced with {@link Patch.replace} or
500
+ * removed, never patched, and a {@link Union} is only patched at its Shared
501
+ * Fields.
502
+ *
503
+ * @see {@link Class.updateUnchecked} for patching where the caller knows the
504
+ * document holds the target
505
+ */
506
+ readonly update: Update<Fields, "checked">;
507
+ /**
508
+ * The shape `updateDoc` writes with `mode: "unchecked"`, also taking a patch
509
+ * into an {@link Optional} struct, and into a key only some members of a
510
+ * {@link Union} hold.
511
+ *
512
+ * **When to use**
513
+ *
514
+ * Use when the caller knows the struct is there, or which member of the
515
+ * union the document holds - from an earlier read, a transaction, or a
516
+ * query that only matches such documents.
517
+ *
518
+ * **Details**
519
+ *
520
+ * It takes every patch {@link Class.update} takes, and writes it the same
521
+ * way. Where the caller is wrong, Firestore writes the patch anyway and the
522
+ * document no longer reads.
523
+ *
524
+ * @see {@link Class.update} for the checked update
525
+ * @see {@link UpdateMode} for exactly what each mode takes
526
+ */
527
+ readonly updateUnchecked: Update<Fields, "unchecked">;
528
+ }
529
+ type MissingSelfGeneric = `Missing \`Self\` generic - use \`class Self extends Class<Self>("Self")({ ... })\``;
530
+ /**
531
+ * Defines a document schema: one field declaration, with the shapes a document
532
+ * is read, created and updated in derived from it.
533
+ *
534
+ * **When to use**
535
+ *
536
+ * Use to define what the documents of a collection hold. Hand the class to
537
+ * {@link Collection.make}, and every read and write of that collection goes
538
+ * through it.
539
+ *
540
+ * **Details**
541
+ *
542
+ * The class is the `read` variant: what a snapshot decodes into, and what
543
+ * schema combinators take. The write shapes hang off it:
544
+ *
545
+ * - {@link Class.create} is what `setDoc` and `addDoc` write, a whole document,
546
+ * taking the sentinels and constructor defaults its fields declare.
547
+ * - {@link Class.update} is what `updateDoc` writes, a nested partial encoded at
548
+ * field paths, taking only patches that leave any document readable.
549
+ * - {@link Class.updateUnchecked} also takes patches that are only right where
550
+ * the caller knows what the document holds - see {@link UpdateMode}.
551
+ *
552
+ * The document's id is not a field: it lives in the path.
553
+ *
554
+ * @example Defining a document and its writes
555
+ * ```ts
556
+ * import { Schema } from "effect";
557
+ * import {
558
+ * FieldValue,
559
+ * FirestoreModel,
560
+ * FirestoreSchema,
561
+ * } from "@visiolab/effect-firebase/firestore";
562
+ *
563
+ * class User extends FirestoreModel.Class<User>("User")({
564
+ * displayName: Schema.String,
565
+ * signupSource: FirestoreModel.Immutable(Schema.String),
566
+ * createdAt: FirestoreModel.Timestamp(FirestoreSchema.Timestamp),
567
+ * visits: FirestoreModel.Number(Schema.Int),
568
+ * nickname: FirestoreModel.Optional(Schema.String),
569
+ * }) {}
570
+ *
571
+ * User.create.make({
572
+ * displayName: "Ada",
573
+ * signupSource: "web",
574
+ * createdAt: FieldValue.serverTimestamp,
575
+ * visits: 0,
576
+ * });
577
+ *
578
+ * User.update.make({ visits: FieldValue.increment(1), nickname: FieldValue.deleteField });
579
+ * ```
580
+ *
581
+ * @see {@link Union} for a document that holds one of several shapes
582
+ * @see {@link Struct} for a nested map, or fields shared between documents
583
+ * @see {@link Collection.make} for the collection a document lives in
584
+ *
585
+ * @stability unstable
586
+ * @category constructors
587
+ * @since 0.2.0
588
+ */
589
+ export declare const Class: <Self = never>(identifier: string) => <const Fields extends VariantSchema.Struct.Fields>(fields: Fields & VariantSchema.Struct.Validate<Fields, Variant>, annotations?: Schema.Annotations.Declaration<Self, readonly [Schema.Struct<VariantSchema.ExtractFields<"read", Fields, true>>]>) => [Self] extends [never] ? MissingSelfGeneric : Class<Self, Fields>;
590
+ /** What a union is replaced with: the `create` shape of each member it may be replaced with. */
591
+ type ReplaceableCreates<Members extends ReadonlyArray<VariantSchema.Struct<any>>> = Members extends readonly [infer Head extends VariantSchema.Struct<any>, ...infer Tail extends ReadonlyArray<VariantSchema.Struct<any>>] ? IsReplaceable<Head[typeof VariantSchema.TypeId]> extends true ? [VariantSchema.Extract<"create", Head>, ...ReplaceableCreates<Tail>] : ReplaceableCreates<Tail> : [];
592
+ /** Whether every member of a union may be written whole by an update. */
593
+ type AreReplaceable<Members extends ReadonlyArray<VariantSchema.Struct<any>>> = false extends { [K in keyof Members]: IsReplaceable<Members[K][typeof VariantSchema.TypeId]>; }[number] ? false : true;
594
+ /** The union of the `create` shapes of `Members`. */
595
+ type UnionCreate<Members extends ReadonlyArray<VariantSchema.Struct<any>>> = Schema.Union<{ readonly [K in keyof Members]: VariantSchema.Extract<"create", Members[K]>; }>;
596
+ /** The fields each of `Members` holds. */
597
+ type MemberFields<Members extends ReadonlyArray<VariantSchema.Struct<any>>> = { readonly [I in keyof Members]: Members[I][typeof VariantSchema.TypeId]; };
598
+ /** Whether every one of `Fs` holds a field at `K`. */
599
+ type HoldAll<Fs extends ReadonlyArray<VariantSchema.Struct.Fields>, K extends PropertyKey> = false extends { [I in keyof Fs]: K extends keyof Fs[I] ? true : false; }[number] ? false : true;
600
+ /** The keys any of `Fs` holds. */
601
+ type AllKeys<Fs extends ReadonlyArray<VariantSchema.Struct.Fields>> = { [I in keyof Fs]: keyof Fs[I]; }[number] & string;
602
+ /** Those of `Fs` that hold a field at `K`. */
603
+ type HoldingMembers<Fs extends ReadonlyArray<VariantSchema.Struct.Fields>, K extends PropertyKey> = Fs extends readonly [infer Head extends VariantSchema.Struct.Fields, ...infer Tail extends ReadonlyArray<VariantSchema.Struct.Fields>] ? K extends keyof Head ? [Head, ...HoldingMembers<Tail, K>] : HoldingMembers<Tail, K> : [];
604
+ /** The field each of `Fs` holds at `K`. */
605
+ type FieldsAt<Fs extends ReadonlyArray<VariantSchema.Struct.Fields>, K extends PropertyKey> = { readonly [I in keyof Fs]: Fs[I][K & keyof Fs[I]]; };
606
+ /** Whether every one of `Vs` is a struct, {@link Optional} or not. */
607
+ type AllStructs<Vs extends ReadonlyArray<unknown>> = false extends { [I in keyof Vs]: [StructOf<Vs[I]>] extends [never] ? false : true; }[number] ? false : true;
608
+ /** Whether every one of `Vs` is a value: no struct, Record or union. */
609
+ type AllValues<Vs extends ReadonlyArray<unknown>> = true extends { [I in keyof Vs]: IsNode<Vs[I]>; }[number] ? false : true;
610
+ /** Whether every one of `Vs` is {@link Optional}, or none, or some. */
611
+ type Optionality<Vs extends ReadonlyArray<unknown>> = { [I in keyof Vs]: IsOptional<Vs[I]>; }[number] extends (infer O) ? [O] extends [true] ? "all" : [O] extends [false] ? "none" : "some" : never;
612
+ /** The fields of the struct each of `Vs` is. */
613
+ type StructsOf<Vs extends ReadonlyArray<unknown>> = { readonly [I in keyof Vs]: StructOf<Vs[I]>; } extends (infer Fs extends ReadonlyArray<VariantSchema.Struct.Fields>) ? Fs : never;
614
+ /** The values out of `A` and `B` that the other takes too. */
615
+ type Meet<A, B> = (A extends B ? A : never) | (B extends A ? B : never);
616
+ /** The values every one of `Ts` takes. */
617
+ type MeetAll<Ts extends ReadonlyArray<unknown>> = Ts extends readonly [infer H, ...infer T] ? T extends readonly [] ? H : Meet<H, MeetAll<T>> : never;
618
+ /** What each of `Vs` takes in an update. */
619
+ type UpdateTypes<Vs extends ReadonlyArray<unknown>> = { readonly [I in keyof Vs]: UpdateSchema<Vs[I]>["Type"]; };
620
+ /**
621
+ * The schema a Shared Field that is a value is patched through: it takes what
622
+ * every member takes, and encodes as the first member does, which is how every
623
+ * member would.
624
+ */
625
+ interface SharedSchema<T, E> extends Schema.Bottom<T, E, never, never, SchemaAST.AST, SharedSchema<T, E>, T> {}
626
+ /** Whether every one of `Vs` is a {@link Union}, {@link Optional} or not. */
627
+ type AllUnions<Vs extends ReadonlyArray<unknown>> = false extends { [I in keyof Vs]: [UnionOf<Vs[I]>] extends [never] ? false : true; }[number] ? false : true;
628
+ /** The fields of every member of each of the unions `Vs`, in one list. */
629
+ type UnionsMemberFields<Vs extends ReadonlyArray<unknown>> = Vs extends readonly [infer Head, ...infer Tail] ? [...MemberFields<UnionOf<Head>>, ...UnionsMemberFields<Tail>] : [];
630
+ /** What each of the unions `Vs` is replaced with, or `never` where one is replaced with nothing. */
631
+ type UnionsCreates<Vs extends ReadonlyArray<unknown>> = true extends { [I in keyof Vs]: ReplaceableCreates<UnionOf<Vs[I]>> extends readonly [] ? true : false; }[number] ? never : { readonly [I in keyof Vs]: Schema.Union<ReplaceableCreates<UnionOf<Vs[I]>>>; };
632
+ /**
633
+ * The schema the unions the members of a union hold at one key are replaced
634
+ * through: it takes what every one of them takes, made by every one.
635
+ */
636
+ interface SharedReplaceSchema<T, MakeIn> extends Schema.Bottom<Replace<T>, Replace<T>, never, never, SchemaAST.Declaration, SharedReplaceSchema<T, MakeIn>, Replace<MakeIn>> {}
637
+ /** The value each of `Ss` holds, and what each is made from. */
638
+ type CreateTypes<Ss extends ReadonlyArray<Schema.Top>> = { readonly [I in keyof Ss]: Ss[I]["Type"]; };
639
+ type CreateMakeIns<Ss extends ReadonlyArray<Schema.Top>> = { readonly [I in keyof Ss]: Ss[I]["~type.make.in"]; };
640
+ /**
641
+ * The replacement of the unions `Vs` takes, or `never` where there is none:
642
+ * one every one of them is replaced with.
643
+ */
644
+ type SharedReplacement<Vs extends ReadonlyArray<unknown>> = UnionsCreates<Vs> extends (infer Ss extends ReadonlyArray<Schema.Top>) ? [MeetAll<CreateTypes<Ss>>] extends [never] ? never : SharedReplaceSchema<MeetAll<CreateTypes<Ss>>, MeetAll<CreateMakeIns<Ss>>> : never;
645
+ /** The schema the unions `Vs` are written whole at their path through, or `never`. */
646
+ type SharedWhole<Vs extends ReadonlyArray<unknown>> = UnionsCreates<Vs> extends (infer Ss extends ReadonlyArray<Schema.Top>) ? [MeetAll<CreateTypes<Ss>>] extends [never] ? never : SharedSchema<MeetAll<CreateTypes<Ss>>, Ss[0]["Encoded"]> : never;
647
+ /**
648
+ * What the unions `Vs` the members of a union hold at one key take, by the
649
+ * rule a union field is written by, held to every one of them: a replacement
650
+ * every one takes, the removal where every one is {@link Optional}, and a
651
+ * patch at the Shared Fields of all their members, unless one is
652
+ * {@link Optional} and the update checked. `never` where they take none.
653
+ */
654
+ type SharedUnionTakes<Vs extends ReadonlyArray<unknown>, Mode extends UpdateMode> = [...([SharedPatch<UnionsMemberFields<Vs>, Mode>] extends [never] ? [] : Optionality<Vs> extends "none" ? [SharedPatch<UnionsMemberFields<Vs>, Mode>] : Mode extends "unchecked" ? [SharedPatch<UnionsMemberFields<Vs>, Mode>] : []), ...([SharedReplacement<Vs>] extends [never] ? [] : [SharedReplacement<Vs>]), ...(Optionality<Vs> extends "all" ? [DeleteField] : [])] extends (infer Takes extends ReadonlyArray<Schema.Top>) ? Takes extends readonly [] ? never : Schema.Union<Takes> : never;
655
+ /** The path the unions `Vs` at `Path` are written whole or removed at. */
656
+ type SharedUnionPath<Vs extends ReadonlyArray<unknown>, Path extends string> = Optionality<Vs> extends "all" ? { readonly [_ in Path]: Schema.optionalKey<[SharedWhole<Vs>] extends [never] ? DeleteField : DeleteFieldOr<SharedWhole<Vs>>>; } : [SharedWhole<Vs>] extends [never] ? {} : { readonly [_ in Path]: Schema.optionalKey<SharedWhole<Vs>>; };
657
+ /**
658
+ * What the fields `Vs` the members of a union hold at one key take, where it
659
+ * is a Shared Field, or `never` where it is none: a value, at what every
660
+ * member takes there, or a struct, patched at its own Shared Fields, or removed
661
+ * where every member may go without it, or a union - see
662
+ * {@link SharedUnionTakes}.
663
+ */
664
+ type SharedTakes<Vs extends ReadonlyArray<unknown>, Mode extends UpdateMode> = AllStructs<Vs> extends true ? Optionality<Vs> extends "none" ? SharedPatch<StructsOf<Vs>, Mode> : Optionality<Vs> extends "all" ? DeleteField : never : AllUnions<Vs> extends true ? SharedUnionTakes<Vs, Mode> : AllValues<Vs> extends true ? [MeetAll<UpdateTypes<Vs>>] extends [never] ? never : SharedSchema<MeetAll<UpdateTypes<Vs>>, UpdateSchema<Vs[0]>["Encoded"]> : never;
665
+ /**
666
+ * The keys members holding the fields `Fs` are patched at in `Mode`, as a
667
+ * patch holds them: their Shared Fields, and under `unchecked` a key only some
668
+ * of them hold as well, by the same rule over just those.
669
+ */
670
+ type SharedUpdateFields<Fs extends ReadonlyArray<VariantSchema.Struct.Fields>, Mode extends UpdateMode> = { readonly [K in AllKeys<Fs> as Mode extends "unchecked" ? [SharedTakes<FieldsAt<HoldingMembers<Fs, K>, K>, Mode>] extends [never] ? never : K : HoldAll<Fs, K> extends true ? [SharedTakes<FieldsAt<Fs, K>, Mode>] extends [never] ? never : K : never]: Schema.optionalKey<SharedTakes<FieldsAt<HoldingMembers<Fs, K>, K>, Mode>>; };
671
+ /** The patch of members holding `Fs` in `Mode`, or `never` where it takes no key. */
672
+ type SharedPatch<Fs extends ReadonlyArray<VariantSchema.Struct.Fields>, Mode extends UpdateMode> = keyof SharedUpdateFields<Fs, Mode> extends never ? never : Schema.Struct<SharedUpdateFields<Fs, Mode>>;
673
+ /** Whether a union is patched at any key in `Mode`. */
674
+ type HasSharedFields<Members extends ReadonlyArray<VariantSchema.Struct<any>>, Mode extends UpdateMode> = [SharedPatch<MemberFields<Members>, Mode>] extends [never] ? false : true;
675
+ /**
676
+ * The paths the keys of members holding `Fs` are written at: every key an
677
+ * `unchecked` update patches, in either mode.
678
+ */
679
+ type SharedPaths<Fs extends ReadonlyArray<VariantSchema.Struct.Fields>, Prefix extends string> = Types.UnionToIntersection<{ [K in keyof SharedUpdateFields<Fs, "unchecked"> & string]: SharedFieldPaths<FieldsAt<HoldingMembers<Fs, K>, K>, `${Prefix}${K}`>; }[keyof SharedUpdateFields<Fs, "unchecked"> & string]> & {};
680
+ /** The paths a Shared Field at `Path`, held as `Vs`, is written at. */
681
+ type SharedFieldPaths<Vs extends ReadonlyArray<unknown>, Path extends string> = AllStructs<Vs> extends true ? Optionality<Vs> extends "none" ? SharedPaths<StructsOf<Vs>, `${Path}.`> : { readonly [_ in Path]: Schema.optionalKey<DeleteField>; } : AllUnions<Vs> extends true ? SharedUnionPath<Vs, Path> & SharedPaths<UnionsMemberFields<Vs>, `${Path}.`> : { readonly [_ in Path]: Schema.optionalKey<SharedTakes<Vs, "unchecked">>; };
682
+ /**
683
+ * What a union takes in an update in `Mode`: a replacement with any member it
684
+ * may be replaced with, the removal where it is {@link Optional}, and a patch
685
+ * of its Shared Fields, unless it is {@link Optional} and the update checked.
686
+ */
687
+ type UnionTakes<Members extends ReadonlyArray<VariantSchema.Struct<any>>, Optional extends boolean, Mode extends UpdateMode> = Schema.Union<readonly [...(HasSharedFields<Members, Mode> extends true ? Optional extends true ? Mode extends "unchecked" ? [SharedPatch<MemberFields<Members>, Mode>] : [] : [SharedPatch<MemberFields<Members>, Mode>] : []), ...(ReplaceableCreates<Members> extends readonly [] | readonly [never] ? [] : [ReplaceSchema<Schema.Union<ReplaceableCreates<Members>>>]), ...(Optional extends true ? [DeleteField] : [])]>;
688
+ /** Whether an update writes anything at all into a union. */
689
+ type IsUnionWritable<Members extends ReadonlyArray<VariantSchema.Struct<any>>, Optional extends boolean> = Optional extends true ? true : ReplaceableCreates<Members> extends readonly [] ? HasSharedFields<Members, "unchecked"> : true;
690
+ /** What a union takes as a field of the struct it sits in, or `never` where it takes nothing. */
691
+ type UnionFieldUpdate<Members extends ReadonlyArray<VariantSchema.Struct<any>>, Optional extends boolean, Mode extends UpdateMode> = IsUnionWritable<Members, Optional> extends true ? Schema.optionalKey<UnionTakes<Members, Optional, Mode>> : never;
692
+ /**
693
+ * The paths a union at `Path` is written at: its own, whole, and that of each
694
+ * of its Shared Fields.
695
+ */
696
+ type UnionPaths<Members extends ReadonlyArray<VariantSchema.Struct<any>>, Optional extends boolean, Path extends string> = (Optional extends true ? { readonly [_ in Path]: Schema.optionalKey<ReplaceableCreates<Members> extends readonly [] ? DeleteField : DeleteFieldOr<Schema.Union<ReplaceableCreates<Members>>>>; } : ReplaceableCreates<Members> extends readonly [] ? {} : { readonly [_ in Path]: Schema.optionalKey<Schema.Union<ReplaceableCreates<Members>>>; }) & SharedPaths<MemberFields<Members>, `${Path}.`>;
697
+ /** The members of the union a field is, or `never` where it is none. */
698
+ type UnionOf<F> = Unwrap<F> extends {
699
+ readonly [UnionTypeId]: infer Members extends ReadonlyArray<VariantSchema.Struct<any>>;
700
+ } ? Members : never;
701
+ /** The schemas a union field is, variant by variant. */
702
+ type UnionSchemas<Members extends ReadonlyArray<VariantSchema.Struct<any>>> = IsUnionWritable<Members, false> extends true ? {
703
+ readonly read: VariantSchema.Union<Members, "read">;
704
+ readonly create: UnionCreate<Members>;
705
+ readonly update: UnionFieldUpdate<Members, false, "unchecked">;
706
+ } : {
707
+ readonly read: VariantSchema.Union<Members, "read">;
708
+ readonly create: UnionCreate<Members>;
709
+ };
710
+ /**
711
+ * Type-level representation of {@link Union}.
712
+ *
713
+ * It is the union of its members as they are read, and carries the members it
714
+ * was made of, which a field holding it is written through.
715
+ *
716
+ * @stability unstable
717
+ * @category models
718
+ * @since 0.2.0
719
+ */
720
+ export interface Union<in out Members extends ReadonlyArray<VariantSchema.Struct<any>>> extends VariantSchema.Union<Members, "read">, VariantSchema.Field<UnionSchemas<Members>> {
721
+ /** The shape a snapshot decodes into: any member, as it is read. */
722
+ readonly read: Schema.Union<{ readonly [K in keyof Members]: VariantSchema.Extract<"read", Members[K]>; }>;
723
+ /** The shape `setDoc` writes: any member, in its `create` shape. */
724
+ readonly create: UnionCreate<Members>;
725
+ /**
726
+ * The shape `updateDoc` writes to a document that is the union: a patch of
727
+ * its Shared Fields alone.
728
+ *
729
+ * A document is never written whole by an update: it changes member through
730
+ * `setDoc`.
731
+ *
732
+ * @see {@link Union.updateUnchecked} for patching a key only some members
733
+ * hold
734
+ */
735
+ readonly update: UnionUpdate<Members, "checked">;
736
+ /**
737
+ * The shape `updateDoc` writes to a document that is the union with
738
+ * `mode: "unchecked"`, also taking a patch of a key only some members hold.
739
+ *
740
+ * **When to use**
741
+ *
742
+ * Use when the caller knows which member the document holds.
743
+ *
744
+ * @see {@link Union.update} for the checked update
745
+ * @see {@link Class.updateUnchecked} for the same rule on a class
746
+ */
747
+ readonly updateUnchecked: UnionUpdate<Members, "unchecked">;
748
+ readonly [UnionTypeId]: Members;
749
+ }
750
+ /** The patch of a document that is a union, or an empty one where it takes no key. */
751
+ type UnionDocumentPatch<Members extends ReadonlyArray<VariantSchema.Struct<any>>, Mode extends UpdateMode> = [SharedPatch<MemberFields<Members>, Mode>] extends [never] ? Schema.Struct<{}> : SharedPatch<MemberFields<Members>, Mode>;
752
+ /**
753
+ * The update of a document that is a {@link Union}, taking the patches `Mode`
754
+ * allows.
755
+ *
756
+ * **Details**
757
+ *
758
+ * It takes a patch of the Shared Fields, and under `unchecked` of a key only
759
+ * some members hold, by the rule a union field is patched by - see
760
+ * {@link Update}. Each is written at its path.
761
+ *
762
+ * It takes no replacement or removal of the document: a document changes
763
+ * member, such as to a new discriminator or version, through `setDoc`.
764
+ *
765
+ * @see {@link Union.update} and {@link Union.updateUnchecked}, which are this
766
+ * in each mode
767
+ *
768
+ * @stability unstable
769
+ * @category models
770
+ * @since 0.2.0
771
+ */
772
+ export interface UnionUpdate<in out Members extends ReadonlyArray<VariantSchema.Struct<any>>, in out Mode extends UpdateMode = "checked"> extends Schema.decodeTo<Schema.toType<UnionDocumentPatch<Members, Mode>>, Schema.Struct<Struct$1.Simplify<SharedPaths<MemberFields<Members>, "">> extends (infer P extends Schema.Struct.Fields) ? P : never>> {}
773
+ /**
774
+ * Declares a document or field that holds one of several structs or classes.
775
+ *
776
+ * **When to use**
777
+ *
778
+ * Use when documents of one collection, or one field, come in several shapes,
779
+ * such as the states of a job or the versions of a document, told apart by a
780
+ * literal field.
781
+ *
782
+ * **Details**
783
+ *
784
+ * It is Effect's own union, with no tag of this library's. A snapshot decodes
785
+ * into the first member that matches, so a literal field narrows it, and data
786
+ * matching no member fails with a schema issue. A `create` takes any member
787
+ * in the shape `setDoc` writes it. A value that fits several members, on
788
+ * `create` or in a replacement, is taken as the first in declaration order, as
789
+ * `Schema.Union` does.
790
+ *
791
+ * As a field, an update may:
792
+ *
793
+ * - Replace it with {@link Patch.replace} and any member, in its `create`
794
+ * shape. A member holding a field that `setDoc` or an update leaves out -
795
+ * {@link Immutable}, or a read-only field - is never replaced, as with a
796
+ * struct.
797
+ * - Remove it with {@link FieldValue.deleteField}, where it is
798
+ * {@link Optional}.
799
+ * - Patch its Shared Fields: keys every member holds, with a value every member
800
+ * takes and stores the same way, so the patch is right whichever member the
801
+ * document holds. A struct every member holds at a key is patched at its own
802
+ * Shared Fields. A union every member holds at a key is written by this same
803
+ * rule, across all of those unions. A Record is never shared.
804
+ * - Under `unchecked`, also patch a key only some members hold, such as
805
+ * `completedAt` on a job the caller knows is done. The value is checked
806
+ * against just those members and written at its path. An {@link Optional}
807
+ * union is only patched under `unchecked`.
808
+ *
809
+ * As a whole document, `setDoc` writes any member and changing member takes a
810
+ * whole `setDoc`. An update patches it by the same rule - see
811
+ * {@link UnionUpdate}.
812
+ *
813
+ * @example A field holding one of several states
814
+ * ```ts
815
+ * import { Schema } from "effect";
816
+ * import {
817
+ * FieldValue,
818
+ * FirestoreModel,
819
+ * FirestoreSchema,
820
+ * Patch,
821
+ * } from "@visiolab/effect-firebase/firestore";
822
+ *
823
+ * const Pending = FirestoreModel.Struct({ status: Schema.Literal("pending") });
824
+ * const Done = FirestoreModel.Struct({
825
+ * status: Schema.Literal("done"),
826
+ * completedAt: FirestoreModel.Timestamp(FirestoreSchema.Timestamp),
827
+ * });
828
+ *
829
+ * class Job extends FirestoreModel.Class<Job>("Job")({
830
+ * state: FirestoreModel.Union([Pending, Done]),
831
+ * }) {}
832
+ *
833
+ * Job.update.make({
834
+ * state: Patch.replace({ status: "done", completedAt: FieldValue.serverTimestamp }),
835
+ * });
836
+ * // Where the job is known to be done: written at "state.completedAt".
837
+ * Job.updateUnchecked.make({ state: { completedAt: FieldValue.serverTimestamp } });
838
+ * ```
839
+ *
840
+ * @see {@link Class} for a document with a single shape
841
+ * @see {@link UpdateMode} for what `checked` and `unchecked` patch
842
+ *
843
+ * @stability unstable
844
+ * @category constructors
845
+ * @since 0.2.0
846
+ */
847
+ export declare const Union: <const Members extends ReadonlyArray<VariantSchema.Struct<any>>>(members: Members) => Union<Members>;
848
+ /**
849
+ * Type-level representation of {@link Immutable}.
850
+ *
851
+ * @stability unstable
852
+ * @category models
853
+ * @since 0.2.0
854
+ */
855
+ export interface Immutable<S extends Schema.Top> extends VariantSchema.Field<{
856
+ readonly read: S;
857
+ readonly create: S;
858
+ }> {}
859
+ /**
860
+ * Declares a field written once, when the document is created.
861
+ *
862
+ * **When to use**
863
+ *
864
+ * Use for a field that must never change after creation, such as a sign-up
865
+ * source or an owner id.
866
+ *
867
+ * **Details**
868
+ *
869
+ * It is read, and written by `setDoc`, but left out of `update`, so no update
870
+ * can change it. A struct or union member holding it is never replaced by an
871
+ * update, since that would rewrite it.
872
+ *
873
+ * @see {@link FieldOnly} for keeping a field to other variants
874
+ * @see {@link Optional} for a field that may be missing
875
+ *
876
+ * @stability unstable
877
+ * @category schemas
878
+ * @since 0.2.0
879
+ */
880
+ export declare const Immutable: <S extends Schema.Top>(schema: S) => Immutable<S>;
881
+ /**
882
+ * Type-level representation of {@link Timestamp}.
883
+ *
884
+ * @stability unstable
885
+ * @category models
886
+ * @since 0.2.0
887
+ */
888
+ export interface Timestamp<S extends TimeSchema> extends VariantSchema.Field<{
889
+ readonly read: S;
890
+ readonly create: ServerTimestampOr<S>;
891
+ readonly update: ServerTimestampOr<S>;
892
+ }> {}
893
+ /**
894
+ * Declares a timestamp field that the client or the server may set.
895
+ *
896
+ * **When to use**
897
+ *
898
+ * Use for a timestamp a write may leave to the server, such as `createdAt` or
899
+ * `updatedAt`. Where the server must never set it, use the schema itself as
900
+ * the field.
901
+ *
902
+ * **Details**
903
+ *
904
+ * `setDoc` and `updateDoc` take either a value of `schema` or
905
+ * {@link FieldValue.serverTimestamp}. A read takes `schema` alone, since the
906
+ * sentinel is resolved by the time a document comes back.
907
+ *
908
+ * `schema` decides what the instant is held as:
909
+ * {@link FirestoreSchema.Timestamp} where precision finer than a millisecond
910
+ * must survive a round trip, or `Schema.DateTimeUtc` or `Schema.Date` where one
911
+ * of those is easier to work with. Firestore stores each as a timestamp.
912
+ *
913
+ * @example Timestamps held two ways
914
+ * ```ts
915
+ * import { Schema } from "effect";
916
+ * import { FieldValue, FirestoreModel, FirestoreSchema } from "@visiolab/effect-firebase/firestore";
917
+ *
918
+ * class Session extends FirestoreModel.Class<Session>("Session")({
919
+ * createdAt: FirestoreModel.Timestamp(FirestoreSchema.Timestamp),
920
+ * seenAt: FirestoreModel.Timestamp(Schema.DateTimeUtc),
921
+ * }) {}
922
+ *
923
+ * Session.update.make({ seenAt: FieldValue.serverTimestamp });
924
+ * ```
925
+ *
926
+ * @see {@link FirestoreSchema.Timestamp} for the schema that keeps full precision
927
+ * @see {@link FirestoreSchema.ServerTimestampOr} for the write schema this
928
+ * declares
929
+ * @see {@link FieldValue.serverTimestamp} for the sentinel a write hands it
930
+ *
931
+ * @stability unstable
932
+ * @category schemas
933
+ * @since 0.2.0
934
+ */
935
+ export declare const Timestamp: <S extends TimeSchema>(schema: S) => Timestamp<S>;
936
+ /**
937
+ * Type-level representation of {@link Number}.
938
+ *
939
+ * @stability unstable
940
+ * @category models
941
+ * @since 0.2.0
942
+ */
943
+ export interface Number<S extends Schema.Codec<unknown, number, unknown, unknown>> extends VariantSchema.Field<{
944
+ readonly read: S;
945
+ readonly create: IncrementOr<S>;
946
+ readonly update: IncrementOr<S>;
947
+ }> {}
948
+ /**
949
+ * Declares a number field that a write may set or have the server increment.
950
+ *
951
+ * **When to use**
952
+ *
953
+ * Use for counters and totals more than one client may change at once: an
954
+ * increment keeps the total right, where reading the number and writing the
955
+ * sum back loses concurrent writes. Where it must never be incremented, use
956
+ * the schema itself as the field.
957
+ *
958
+ * **Details**
959
+ *
960
+ * `setDoc` and `updateDoc` take either a value of `schema` or
961
+ * {@link FieldValue.increment} / {@link FieldValue.decrement}. A read takes
962
+ * `schema` alone, since the document holds the sum the server computed.
963
+ *
964
+ * `schema` decides what the number may be, on both reads and writes: hand it
965
+ * `Schema.Int` for whole steps, or `Schema.Finite` for fractions. An increment
966
+ * is not checked against it, since the server computes the sum and only the
967
+ * next read sees it.
968
+ *
969
+ * @example A counter and a balance
970
+ * ```ts
971
+ * import { Schema } from "effect";
972
+ * import { FieldValue, FirestoreModel } from "@visiolab/effect-firebase/firestore";
973
+ *
974
+ * class Account extends FirestoreModel.Class<Account>("Account")({
975
+ * visits: FirestoreModel.Number(Schema.Int),
976
+ * balance: FirestoreModel.Number(Schema.Finite),
977
+ * }) {}
978
+ *
979
+ * Account.update.make({ visits: FieldValue.increment(1) });
980
+ * ```
981
+ *
982
+ * @see {@link FieldValue.increment} for the sentinel a write hands it
983
+ * @see {@link FirestoreSchema.IncrementOr} for the write schema this declares
984
+ *
985
+ * @stability unstable
986
+ * @category schemas
987
+ * @since 0.2.0
988
+ */
989
+ export declare const Number: <S extends Schema.Codec<unknown, number, unknown, unknown>>(schema: S) => Number<S>;
990
+ /**
991
+ * Type-level representation of {@link Array}.
992
+ *
993
+ * @stability unstable
994
+ * @category models
995
+ * @since 0.2.0
996
+ */
997
+ export interface Array<S extends Schema.Top> extends VariantSchema.Field<{
998
+ readonly read: Schema.$Array<S>;
999
+ readonly create: Schema.$Array<S>;
1000
+ readonly update: ArrayOr<S>;
1001
+ }> {}
1002
+ /**
1003
+ * Declares an array field that an update may write whole, or have the server
1004
+ * add elements to or remove elements from.
1005
+ *
1006
+ * **When to use**
1007
+ *
1008
+ * Use for an array more than one client may change at once, such as a list of
1009
+ * tags: {@link FieldValue.arrayUnion} and {@link FieldValue.arrayRemove} keep
1010
+ * an element another client added at the same time, where reading the array
1011
+ * and writing it back does not.
1012
+ *
1013
+ * **Details**
1014
+ *
1015
+ * An update takes the array, `arrayUnion` or `arrayRemove`. A read takes the
1016
+ * array alone. `setDoc` takes the array alone too: adding to a missing array
1017
+ * writes the elements as they are, and removing from one writes it empty,
1018
+ * which is not what was meant.
1019
+ *
1020
+ * Elements are matched by value, all the way down, so removing a map from the
1021
+ * array means handing over every key it holds - see
1022
+ * {@link FieldValue.ArrayRemove}. `item` is what each element is held as. It
1023
+ * cannot be an array, which Firestore does not nest, or a field, since an
1024
+ * element is always written whole.
1025
+ *
1026
+ * @example Adding a tag
1027
+ * ```ts
1028
+ * import { Schema } from "effect";
1029
+ * import { FieldValue, FirestoreModel } from "@visiolab/effect-firebase/firestore";
1030
+ *
1031
+ * class Article extends FirestoreModel.Class<Article>("Article")({
1032
+ * tags: FirestoreModel.Array(Schema.String),
1033
+ * }) {}
1034
+ *
1035
+ * Article.update.make({ tags: FieldValue.arrayUnion("news") });
1036
+ * ```
1037
+ *
1038
+ * @see {@link FieldValue.arrayUnion} and {@link FieldValue.arrayRemove} for the
1039
+ * sentinels an update hands it
1040
+ * @see {@link FirestoreSchema.ArrayOr} for the update schema this declares
1041
+ *
1042
+ * @stability unstable
1043
+ * @category schemas
1044
+ * @since 0.2.0
1045
+ */
1046
+ export declare const Array: <S extends Schema.Top>(item: S) => Array<S>;
1047
+ /**
1048
+ * Type-level representation of {@link Record}.
1049
+ *
1050
+ * It carries the key and value it was made of, which an update reaches into.
1051
+ *
1052
+ * @stability unstable
1053
+ * @category models
1054
+ * @since 0.2.0
1055
+ */
1056
+ export interface Record<in out K extends Schema.Record.Key, in out V extends Value> extends VariantSchema.Field<IsWritable<V> extends true ? {
1057
+ readonly read: RecordSchema<K, ValueSchema<V, "read">>;
1058
+ readonly create: RecordSchema<K, ValueSchema<V, "create">>;
1059
+ readonly update: Schema.optionalKey<RecordTakes<K, V, false, "unchecked">>;
1060
+ } : {
1061
+ readonly read: RecordSchema<K, ValueSchema<V, "read">>;
1062
+ readonly create: RecordSchema<K, ValueSchema<V, "create">>;
1063
+ }> {
1064
+ readonly [RecordTypeId]: {
1065
+ readonly key: K;
1066
+ readonly value: V;
1067
+ };
1068
+ }
1069
+ /**
1070
+ * Declares a map field whose keys come from the data, which an update writes
1071
+ * key by key.
1072
+ *
1073
+ * **When to use**
1074
+ *
1075
+ * Use for a map keyed by data rather than by a fixed set of fields: a counter
1076
+ * per option, an entry per member, a lookup table. Writing key by key lets two
1077
+ * clients each change a key of the same map without reading it first.
1078
+ *
1079
+ * **Details**
1080
+ *
1081
+ * A read and `setDoc` hold it as `Schema.Record(key, value)`, with each value
1082
+ * in its read or create shape, so `setDoc` takes the sentinels `value` takes.
1083
+ * An update takes a patch, writing each key it carries at its own path, in the
1084
+ * update shape of `value`: a {@link Number} takes
1085
+ * {@link FieldValue.increment}, an {@link Array} {@link FieldValue.arrayUnion},
1086
+ * a {@link Timestamp} {@link FieldValue.serverTimestamp}.
1087
+ *
1088
+ * - Where `key` is a string, refined or not, any key may be missing, so each
1089
+ * takes {@link FieldValue.deleteField}. A value that is itself a struct or
1090
+ * Record is treated like an {@link Optional} struct: written whole with
1091
+ * {@link Patch.replace} or removed, and only patched by
1092
+ * {@link Class.updateUnchecked}.
1093
+ * - Where `key` is a union of literals, the Record holds every key, and an
1094
+ * update treats it as a struct with a field per key: no key is removed
1095
+ * unless `value` is {@link Optional}.
1096
+ *
1097
+ * Either way, it takes {@link Patch.replace} to be written whole, unless
1098
+ * `value` holds a field `setDoc` or an update leaves out.
1099
+ *
1100
+ * A key's path is the key as `key` encodes it, so the update requires any
1101
+ * service `key` needs to encode. A key no path can name - empty, or containing
1102
+ * a `.` - fails the update when it is encoded, or throws when the Record is
1103
+ * declared if it is a literal. A value no update writes, such as
1104
+ * {@link Immutable}, leaves the whole Record out of the update.
1105
+ *
1106
+ * @example Patching keys of a map
1107
+ * ```ts
1108
+ * import { Schema } from "effect";
1109
+ * import { FieldValue, FirestoreModel } from "@visiolab/effect-firebase/firestore";
1110
+ *
1111
+ * class Poll extends FirestoreModel.Class<Poll>("Poll")({
1112
+ * votes: FirestoreModel.Record(Schema.String, FirestoreModel.Number(Schema.Int)),
1113
+ * aliases: FirestoreModel.Record(Schema.String, Schema.String),
1114
+ * }) {}
1115
+ *
1116
+ * Poll.update.make({
1117
+ * votes: { pizza: FieldValue.increment(1) }, // "votes.pizza"
1118
+ * aliases: { old: FieldValue.deleteField }, // "aliases.old"
1119
+ * });
1120
+ * ```
1121
+ *
1122
+ * @see {@link Struct} for a map with a fixed set of fields
1123
+ *
1124
+ * @stability unstable
1125
+ * @category schemas
1126
+ * @since 0.2.0
1127
+ */
1128
+ export declare const Record: <K extends Schema.Record.Key, V extends Value>(key: K, value: V) => Record<K, V>;
1129
+ /** Any {@link Record}, whatever it holds. */
1130
+ type AnyRecord = VariantSchema.Field<any> & {
1131
+ readonly [RecordTypeId]: any;
1132
+ };
1133
+ /** The variants of `F` made {@link Optional}. */
1134
+ type OptionalSchemas<F extends Value> = F extends VariantSchema.Struct<any> ? {
1135
+ readonly read: Schema.optionalKey<VariantSchema.Extract<"read", F>>;
1136
+ readonly create: Schema.optionalKey<VariantSchema.Extract<"create", F>>;
1137
+ readonly update: StructUpdate<F[typeof VariantSchema.TypeId], true, "unchecked">;
1138
+ } : F extends Union<infer Members> ? {
1139
+ readonly read: Schema.optionalKey<VariantSchema.Union<Members, "read">>;
1140
+ readonly create: Schema.optionalKey<UnionCreate<Members>>;
1141
+ readonly update: UnionFieldUpdate<Members, true, "unchecked">;
1142
+ } : F extends AnyRecord ? IsWritable<RecordOf<F>["value"]> extends true ? {
1143
+ readonly read: Schema.optionalKey<F["schemas"]["read"]>;
1144
+ readonly create: Schema.optionalKey<F["schemas"]["create"]>;
1145
+ readonly update: Schema.optionalKey<RecordTakes<RecordOf<F>["key"], RecordOf<F>["value"], true, "unchecked">>;
1146
+ } : {
1147
+ readonly read: Schema.optionalKey<F["schemas"]["read"]>;
1148
+ readonly create: Schema.optionalKey<F["schemas"]["create"]>;
1149
+ } : F extends Schema.Top ? {
1150
+ readonly read: Schema.optionalKey<F>;
1151
+ readonly create: Schema.optionalKey<F>;
1152
+ readonly update: Schema.optionalKey<DeleteFieldOr<F>>;
1153
+ } : F extends VariantSchema.Field<infer S> ? { readonly [K in keyof S]: S[K] extends Schema.Top ? K extends "update" ? Schema.optionalKey<DeleteFieldOr<S[K]>> : Schema.optionalKey<S[K]> : never; } : never;
1154
+ /**
1155
+ * Type-level representation of {@link Optional}.
1156
+ *
1157
+ * It carries the field it was made of as `field`, which an update reaches into
1158
+ * where that is a struct or a {@link Record}.
1159
+ *
1160
+ * @stability unstable
1161
+ * @category models
1162
+ * @since 0.2.0
1163
+ */
1164
+ export interface Optional<in out F extends Value> extends VariantSchema.Field<OptionalSchemas<F>> {
1165
+ readonly "~optionality": "optional";
1166
+ readonly field: F;
1167
+ }
1168
+ /**
1169
+ * Declares a field a document may go without, and an update may remove.
1170
+ *
1171
+ * **When to use**
1172
+ *
1173
+ * Use for a field that may be missing from a document. Wrap any schema, field,
1174
+ * struct, union or {@link Record} in it.
1175
+ *
1176
+ * **Details**
1177
+ *
1178
+ * A read and `setDoc` hold it as an optional key: a missing field is left out
1179
+ * rather than stored as `null`. An update also takes
1180
+ * {@link FieldValue.deleteField}, since leaving a field out of an update leaves
1181
+ * it as it is. Inside a struct, an optional field is removed the same way, at
1182
+ * its path.
1183
+ *
1184
+ * A field with no `update` variant, such as {@link Immutable}, becomes optional
1185
+ * where it is read and created, and stays out of the update. Making a field
1186
+ * optional twice is the same as once.
1187
+ *
1188
+ * An optional struct is where the stored document decides what a patch does: a
1189
+ * patch written into a missing struct creates it holding only the patch, and
1190
+ * the document no longer reads. So {@link Class.update} writes it whole with
1191
+ * {@link Patch.replace} or removes it, and only {@link Class.updateUnchecked}
1192
+ * patches it, for a caller who knows it is there.
1193
+ *
1194
+ * @example Optional fields
1195
+ * ```ts
1196
+ * import { Schema } from "effect";
1197
+ * import { FirestoreModel, FirestoreSchema } from "@visiolab/effect-firebase/firestore";
1198
+ *
1199
+ * const Address = FirestoreModel.Struct({ city: Schema.String });
1200
+ *
1201
+ * class User extends FirestoreModel.Class<User>("User")({
1202
+ * nickname: FirestoreModel.Optional(Schema.String),
1203
+ * lastSeenAt: FirestoreModel.Optional(FirestoreModel.Timestamp(FirestoreSchema.Timestamp)),
1204
+ * address: FirestoreModel.Optional(Address),
1205
+ * }) {}
1206
+ * ```
1207
+ *
1208
+ * @example Updating an optional struct
1209
+ * ```ts
1210
+ * import { Schema } from "effect";
1211
+ * import { FieldValue, FirestoreModel, Patch } from "@visiolab/effect-firebase/firestore";
1212
+ *
1213
+ * const Address = FirestoreModel.Struct({ city: Schema.String, zip: Schema.String });
1214
+ *
1215
+ * class Customer extends FirestoreModel.Class<Customer>("Customer")({
1216
+ * address: FirestoreModel.Optional(Address),
1217
+ * }) {}
1218
+ *
1219
+ * Customer.update.make({ address: Patch.replace({ city: "Berlin", zip: "10115" }) }); // written whole
1220
+ * Customer.update.make({ address: FieldValue.deleteField }); // removed
1221
+ * Customer.updateUnchecked.make({ address: { city: "Berlin" } }); // the caller knows it is there
1222
+ * ```
1223
+ *
1224
+ * @see {@link FieldValue.deleteField} for removing it in an update
1225
+ * @see {@link UpdateMode} for when an optional struct may be patched
1226
+ *
1227
+ * @stability unstable
1228
+ * @category schemas
1229
+ * @since 0.2.0
1230
+ */
1231
+ export declare const Optional: <F extends Value>(self: F) => F extends AnyOptional ? F : Optional<F>;
1232
+ export { FirestoreModel_d_exports };