@visiolab/effect-firebase-client 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 (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +70 -2
  3. package/dist/_virtual/_rolldown/runtime.mjs +12 -0
  4. package/dist/app/App.d.mts +117 -0
  5. package/dist/app/App.mjs +149 -0
  6. package/dist/app/App.mjs.map +1 -0
  7. package/dist/app/index.d.mts +2 -0
  8. package/dist/app/index.mjs +1 -0
  9. package/dist/app/internal/app.mjs +20 -0
  10. package/dist/app/internal/app.mjs.map +1 -0
  11. package/dist/firestore/ClientDocumentSnapshot.d.mts +106 -0
  12. package/dist/firestore/ClientDocumentSnapshot.mjs +86 -0
  13. package/dist/firestore/ClientDocumentSnapshot.mjs.map +1 -0
  14. package/dist/firestore/ClientFirestore.d.mts +331 -0
  15. package/dist/firestore/ClientFirestore.mjs +146 -0
  16. package/dist/firestore/ClientFirestore.mjs.map +1 -0
  17. package/dist/firestore/ClientFirestoreValue.d.mts +61 -0
  18. package/dist/firestore/ClientFirestoreValue.mjs +62 -0
  19. package/dist/firestore/ClientFirestoreValue.mjs.map +1 -0
  20. package/dist/firestore/ClientQuerySnapshot.d.mts +52 -0
  21. package/dist/firestore/ClientQuerySnapshot.mjs +58 -0
  22. package/dist/firestore/ClientQuerySnapshot.mjs.map +1 -0
  23. package/dist/firestore/index.d.mts +5 -0
  24. package/dist/firestore/index.mjs +5 -0
  25. package/dist/firestore/internal/firestore.mjs +158 -0
  26. package/dist/firestore/internal/firestore.mjs.map +1 -0
  27. package/dist/firestore/internal/firestoreValue.mjs +43 -0
  28. package/dist/firestore/internal/firestoreValue.mjs.map +1 -0
  29. package/dist/firestore/internal/snapshotMetadata.mjs +15 -0
  30. package/dist/firestore/internal/snapshotMetadata.mjs.map +1 -0
  31. package/dist/functions/CallableClient.d.mts +139 -0
  32. package/dist/functions/CallableClient.mjs +215 -0
  33. package/dist/functions/CallableClient.mjs.map +1 -0
  34. package/dist/functions/ClientFunctions.d.mts +112 -0
  35. package/dist/functions/ClientFunctions.mjs +105 -0
  36. package/dist/functions/ClientFunctions.mjs.map +1 -0
  37. package/dist/functions/index.d.mts +3 -0
  38. package/dist/functions/index.mjs +3 -0
  39. package/package.json +63 -3
  40. package/src/app/App.ts +163 -0
  41. package/src/app/index.ts +7 -0
  42. package/src/app/internal/app.ts +35 -0
  43. package/src/firestore/ClientDocumentSnapshot.ts +156 -0
  44. package/src/firestore/ClientFirestore.ts +410 -0
  45. package/src/firestore/ClientFirestoreValue.ts +94 -0
  46. package/src/firestore/ClientQuerySnapshot.ts +93 -0
  47. package/src/firestore/index.ts +30 -0
  48. package/src/firestore/internal/firestore.ts +264 -0
  49. package/src/firestore/internal/firestoreValue.ts +58 -0
  50. package/src/firestore/internal/snapshotMetadata.ts +14 -0
  51. package/src/functions/CallableClient.ts +296 -0
  52. package/src/functions/ClientFunctions.ts +149 -0
  53. package/src/functions/index.ts +15 -0
@@ -0,0 +1,331 @@
1
+ import { App } from "../app/App.mjs";
2
+ import { SnapshotMetadata } from "./ClientDocumentSnapshot.mjs";
3
+ import { Context, Effect, Layer } from "effect";
4
+ import { Firestore, With } from "@visiolab/effect-firebase/firestore/Firestore";
5
+ import { Firestore as Firestore$1, FirestoreLocalCache } from "firebase/firestore";
6
+ declare namespace ClientFirestore_d_exports {
7
+ export { ClientFirestore, Emulator, ListenOptions, Options, ReadOptions, ReadSource, layer, make };
8
+ }
9
+ declare const TypeId = "~@visiolab/effect-firebase-client/firestore/ClientFirestore";
10
+ /**
11
+ * The portable {@link Firestore}, plus what only the client SDK can do.
12
+ *
13
+ * **When to use**
14
+ *
15
+ * Ask for it where code needs the client SDK: a read from the server or the
16
+ * cache alone, metadata changes on a listen, a snapshot's
17
+ * {@link ClientDocumentSnapshot.SnapshotMetadata}, or the SDK itself through
18
+ * {@link ClientFirestore.instance}. Everywhere else ask for {@link Firestore},
19
+ * so the code also runs on the Admin SDK.
20
+ *
21
+ * **Details**
22
+ *
23
+ * Its reads take {@link ReadOptions} and its listens {@link ListenOptions}.
24
+ * Every document snapshot, each document of a query snapshot, and each query
25
+ * snapshot as a whole carries the `metadata` of its read, as a
26
+ * {@link ClientDocumentSnapshot.ClientDocumentSnapshot} or
27
+ * {@link ClientQuerySnapshot.ClientQuerySnapshot} does.
28
+ *
29
+ * The service its key holds is also a {@link Firestore}, so it can be handed
30
+ * to code that expects one as it is. The type itself only extends
31
+ * {@link Firestore.With}, so providing a {@link Firestore} alone, such as an
32
+ * in-memory fake, does not satisfy code that asks for it. Its
33
+ * transactions are the portable {@link Firestore.Transaction}: the client SDK's
34
+ * transactions read one document at a time.
35
+ *
36
+ * The client SDK cannot abort a request in flight, so interrupting a call does
37
+ * not stop it: the request still runs to completion.
38
+ *
39
+ * @see {@link Firestore.With} for each read and write it offers
40
+ *
41
+ * @stability unstable
42
+ * @category models
43
+ * @since 0.1.0
44
+ */
45
+ export interface ClientFirestore extends With<ReadOptions, ListenOptions, {
46
+ readonly metadata: SnapshotMetadata;
47
+ }> {
48
+ readonly [TypeId]: typeof TypeId;
49
+ /**
50
+ * The client SDK's own `Firestore`, for the database the service was opened
51
+ * on.
52
+ *
53
+ * **When to use**
54
+ *
55
+ * Use for what this service does not wrap, such as queries or
56
+ * `disableNetwork` and `enableNetwork`. Prefer the service's own methods
57
+ * where one exists.
58
+ *
59
+ * **Details**
60
+ *
61
+ * Calls through it skip the collection's model, take and return the SDK's
62
+ * own values, and throw the SDK's own errors. To write a model through it,
63
+ * encode with {@link FirestoreValue.toCodecFirestore} and map with
64
+ * {@link ClientFirestoreValue.toClient}.
65
+ *
66
+ * @see {@link ClientFirestoreValue} for mapping between the SDK's values and Firestore Values
67
+ */
68
+ readonly instance: Firestore$1;
69
+ }
70
+ /**
71
+ * How `streamDoc` and `streamDocs` on {@link ClientFirestore} listen, named as
72
+ * in the client SDK's own listen options.
73
+ *
74
+ * **When to use**
75
+ *
76
+ * Use to also hear metadata changes, such as a pending write being
77
+ * acknowledged, or to listen to the local cache alone. Left out, a listen
78
+ * behaves as the SDK's does by default: it emits only when the data changes.
79
+ *
80
+ * **Details**
81
+ *
82
+ * Every snapshot a listen emits carries the
83
+ * {@link ClientDocumentSnapshot.SnapshotMetadata} it arrived with. The portable
84
+ * {@link Firestore.With.streamDoc} takes no options, because the Admin SDK's
85
+ * listeners take none.
86
+ *
87
+ * @example Waiting for the server to acknowledge a write
88
+ * ```ts
89
+ * import { Effect, Schema, Stream } from "effect";
90
+ * import { Collection, FirestoreModel } from "@visiolab/effect-firebase/firestore";
91
+ * import { ClientFirestore } from "@visiolab/effect-firebase-client/firestore";
92
+ *
93
+ * class Post extends FirestoreModel.Class<Post>("Post")({
94
+ * title: Schema.String,
95
+ * }) {}
96
+ *
97
+ * const Posts = Collection.make("posts", Post);
98
+ * const hello = Posts.doc(Posts.id.make("hello"));
99
+ *
100
+ * const acknowledged = Effect.gen(function* () {
101
+ * const firestore = yield* ClientFirestore.ClientFirestore;
102
+ * yield* firestore.streamDoc(hello, { includeMetadataChanges: true }).pipe(
103
+ * Stream.filter((snapshot) => !snapshot.metadata.hasPendingWrites),
104
+ * Stream.runHead,
105
+ * );
106
+ * });
107
+ * ```
108
+ *
109
+ * @see {@link ReadOptions} for the options of a one-off read
110
+ *
111
+ * @stability unstable
112
+ * @category models
113
+ * @since 0.1.0
114
+ */
115
+ export interface ListenOptions {
116
+ /**
117
+ * Whether to also emit when only the
118
+ * {@link ClientDocumentSnapshot.SnapshotMetadata} changes, such as when the
119
+ * server acknowledges a pending write or the cache catches up with the
120
+ * server. Without it, a listen only emits when the data changes.
121
+ */
122
+ readonly includeMetadataChanges?: boolean | undefined;
123
+ /**
124
+ * Where to listen. `"default"` listens to the server and the local cache.
125
+ * `"cache"` listens to the local cache alone and never reaches the server, so
126
+ * it only sees what this client has written or already read.
127
+ */
128
+ readonly source?: "default" | "cache" | undefined;
129
+ }
130
+ /**
131
+ * Service key for {@link ClientFirestore}.
132
+ *
133
+ * @see {@link Firestore} for the portable key, which {@link layer} provides the same service under
134
+ *
135
+ * @stability unstable
136
+ * @category services
137
+ * @since 0.1.0
138
+ */
139
+ export declare const ClientFirestore: Context.Service<ClientFirestore, ClientFirestore & Firestore>;
140
+ /**
141
+ * Where a one-off read is served from.
142
+ *
143
+ * - `"default"`: the server when it can be reached, otherwise the local cache.
144
+ * What a read does when no source is given.
145
+ * - `"server"`: the server alone. Fails with the SDK's code when the server
146
+ * cannot be reached, instead of falling back to the cache.
147
+ * - `"cache"`: the local cache alone, without asking the server.
148
+ *
149
+ * The two reads report what the cache lacks differently, as the SDK does. A
150
+ * cached `getDoc` of a document the cache has never seen fails with a
151
+ * {@link Firestore.FirestoreError} whose code is `unavailable`, and one the
152
+ * cache knows was deleted reads as `Missing`. A cached `getDocs` never fails
153
+ * for what the cache lacks: it returns whatever the cache holds, which may be
154
+ * nothing, with `fromCache: true`.
155
+ *
156
+ * @see {@link ReadOptions} for passing it to a read
157
+ *
158
+ * @stability unstable
159
+ * @category models
160
+ * @since 0.1.0
161
+ */
162
+ export type ReadSource = "default" | "server" | "cache";
163
+ /**
164
+ * How `getDoc` and `getDocs` on {@link ClientFirestore} read a document, a
165
+ * collection, or a Collection Group.
166
+ *
167
+ * **When to use**
168
+ *
169
+ * Use to read from the server alone, such as to confirm a value before acting
170
+ * on it, or from the local cache alone, such as to render at once while
171
+ * offline. Left out, a read behaves as the SDK's does by default.
172
+ *
173
+ * **Details**
174
+ *
175
+ * With `source: "cache"`, a `getDoc` of a document the cache has never seen
176
+ * fails with a {@link Firestore.FirestoreError} whose code is `unavailable`:
177
+ * not being cached is not the same as not existing. One the cache knows was
178
+ * deleted reads as `Missing`. A `getDocs` never fails for what the cache lacks:
179
+ * it returns whatever the cache holds, which may be nothing, with `fromCache:
180
+ * true`. So, unlike `getDoc`, an empty result cannot tell "nothing cached" from
181
+ * "nothing there".
182
+ *
183
+ * The portable {@link Firestore.With.getDoc} takes no options, because the
184
+ * Admin SDK's reads take none.
185
+ *
186
+ * @example Reading from the server alone
187
+ * ```ts
188
+ * import { Effect, Schema } from "effect";
189
+ * import { Collection, FirestoreModel } from "@visiolab/effect-firebase/firestore";
190
+ * import { ClientFirestore } from "@visiolab/effect-firebase-client/firestore";
191
+ *
192
+ * class Post extends FirestoreModel.Class<Post>("Post")({
193
+ * title: Schema.String,
194
+ * }) {}
195
+ *
196
+ * const Posts = Collection.make("posts", Post);
197
+ *
198
+ * const fresh = Effect.gen(function* () {
199
+ * const firestore = yield* ClientFirestore.ClientFirestore;
200
+ * return yield* firestore.getDoc(Posts.doc(Posts.id.make("hello")), { source: "server" });
201
+ * });
202
+ * ```
203
+ *
204
+ * @see {@link ReadSource} for where a read can be served from
205
+ * @see {@link ListenOptions} for the options of a listen
206
+ *
207
+ * @stability unstable
208
+ * @category models
209
+ * @since 0.1.0
210
+ */
211
+ export interface ReadOptions {
212
+ /**
213
+ * Where the read is served from. Left out, it is `"default"`.
214
+ *
215
+ * @see {@link ReadSource} for each source, and what a cached read does with what the cache lacks
216
+ */
217
+ readonly source?: ReadSource | undefined;
218
+ }
219
+ /**
220
+ * Where the Firestore emulator listens, such as `{ host: "127.0.0.1", port:
221
+ * 8080 }`.
222
+ *
223
+ * @see {@link Options.emulator} for connecting to it
224
+ *
225
+ * @stability unstable
226
+ * @category models
227
+ * @since 0.1.0
228
+ */
229
+ export interface Emulator {
230
+ readonly host: string;
231
+ readonly port: number;
232
+ }
233
+ /**
234
+ * How {@link layer} opens a database. All of them are fixed once the database
235
+ * is open.
236
+ *
237
+ * @see {@link AdminFirestore.Options} for the Admin SDK's, which read the emulator from the environment
238
+ *
239
+ * @stability unstable
240
+ * @category models
241
+ * @since 0.1.0
242
+ */
243
+ export interface Options {
244
+ /**
245
+ * The database to open, where the project has more than its default one.
246
+ * Leave it out for the default database.
247
+ */
248
+ readonly databaseId?: string | undefined;
249
+ /**
250
+ * The emulator to talk to instead of the project's database.
251
+ *
252
+ * Unlike the Admin SDK, the client SDK takes the emulator per database, not
253
+ * from the environment, and only before the database is first used.
254
+ */
255
+ readonly emulator?: Emulator | undefined;
256
+ /**
257
+ * Where the SDK keeps the documents it has seen and the writes it has yet to
258
+ * send: `memoryLocalCache()`, the SDK's default, or `persistentLocalCache()`,
259
+ * which keeps them in IndexedDB across reloads.
260
+ */
261
+ readonly localCache?: FirestoreLocalCache | undefined;
262
+ }
263
+ /**
264
+ * Builds {@link ClientFirestore} on the {@link App.App} in context.
265
+ *
266
+ * **When to use**
267
+ *
268
+ * Use to build the service inside an effect of your own. Most programs provide
269
+ * it with {@link layer} instead, which also provides it as {@link Firestore}.
270
+ *
271
+ * **Details**
272
+ *
273
+ * Building the service cannot fail. Opening a database only throws for an app
274
+ * that was already deleted, or a database already opened or used with other
275
+ * settings. Both are wiring mistakes, so they are defects, and a
276
+ * {@link Firestore.FirestoreError} only ever means that a call failed.
277
+ *
278
+ * A write only succeeds once the server acknowledges it, so a write made
279
+ * offline waits for the connection. It is applied to the local cache at once
280
+ * and sent when it can be: interrupting the write, or timing it out, does not
281
+ * take it back.
282
+ *
283
+ * A server timestamp the server has not settled yet reads as the local clock's
284
+ * estimate, so the field decodes as a timestamp.
285
+ *
286
+ * @see {@link layer} for the same as a layer
287
+ *
288
+ * @stability unstable
289
+ * @category constructors
290
+ * @since 0.1.0
291
+ */
292
+ export declare const make: (options?: Options) => Effect.Effect<ClientFirestore & Firestore, never, App>;
293
+ /**
294
+ * A layer that provides {@link ClientFirestore} for the {@link App.App} in
295
+ * context, and the same service as the portable {@link Firestore}.
296
+ *
297
+ * **When to use**
298
+ *
299
+ * Use in a browser, or anywhere the client SDK runs. On a server, use
300
+ * {@link AdminFirestore.layer} instead.
301
+ *
302
+ * **Details**
303
+ *
304
+ * With no options it opens the project's default database with the SDK's
305
+ * defaults.
306
+ *
307
+ * @example Providing Firestore with a persistent cache
308
+ * ```ts
309
+ * import { Layer } from "effect";
310
+ * import { persistentLocalCache } from "firebase/firestore";
311
+ * import { App } from "@visiolab/effect-firebase-client/app";
312
+ * import { ClientFirestore } from "@visiolab/effect-firebase-client/firestore";
313
+ *
314
+ * const FirestoreLive = ClientFirestore.layer({
315
+ * localCache: persistentLocalCache(),
316
+ * emulator: import.meta.env.DEV ? { host: "127.0.0.1", port: 8080 } : undefined,
317
+ * }).pipe(
318
+ * Layer.provide(App.layer({ apiKey: "<api key>", projectId: "my-project", appId: "<app id>" })),
319
+ * );
320
+ * ```
321
+ *
322
+ * @see {@link make} for why building the service cannot fail
323
+ * @see {@link AdminFirestore.layer} for the Admin SDK's layer, for servers
324
+ *
325
+ * @stability unstable
326
+ * @category layers
327
+ * @since 0.1.0
328
+ */
329
+ export declare const layer: (options?: Options) => Layer.Layer<ClientFirestore | Firestore, never, App>;
330
+ export { ClientFirestore_d_exports };
331
+ //# sourceMappingURL=ClientFirestore.d.mts.map
@@ -0,0 +1,146 @@
1
+ import { __exportAll } from "../_virtual/_rolldown/runtime.mjs";
2
+ import { fromDatabase, openDatabase } from "./internal/firestore.mjs";
3
+ import { Context, Effect, Layer } from "effect";
4
+ import { Firestore } from "@visiolab/effect-firebase/firestore/Firestore";
5
+ // src/firestore/ClientFirestore.ts
6
+ /**
7
+ * Firestore on the Firebase client SDK, for browsers.
8
+ *
9
+ * {@link layer} provides one service under two keys: the portable
10
+ * {@link Firestore}, which code that runs on either SDK asks for, and
11
+ * {@link ClientFirestore}, which adds what only the client SDK can do: read
12
+ * sources, listen options, and the
13
+ * {@link ClientDocumentSnapshot.SnapshotMetadata} of every read. Both reach the
14
+ * same database.
15
+ *
16
+ * Where it behaves differently from the Admin SDK:
17
+ *
18
+ * - The emulator is a layer option, not an environment variable.
19
+ * - A write only succeeds once the server acknowledges it, so a write made
20
+ * offline waits for the connection. It is applied to the local cache at once
21
+ * and sent when it can be; interrupting the write does not take it back.
22
+ * - A pending server timestamp reads as the local clock's estimate, not `null`,
23
+ * so it decodes as a timestamp before the server has settled it.
24
+ * - Error codes are always named, such as `permission-denied`.
25
+ *
26
+ * @example Reading a document, and where the read came from
27
+ * ```ts
28
+ * import { Effect, Layer, Schema } from "effect";
29
+ * import { Collection, FirestoreModel } from "@visiolab/effect-firebase/firestore";
30
+ * import { App } from "@visiolab/effect-firebase-client/app";
31
+ * import { ClientFirestore } from "@visiolab/effect-firebase-client/firestore";
32
+ *
33
+ * class Post extends FirestoreModel.Class<Post>("Post")({
34
+ * title: Schema.String,
35
+ * }) {}
36
+ *
37
+ * const Posts = Collection.make("posts", Post);
38
+ *
39
+ * const program = Effect.gen(function* () {
40
+ * const firestore = yield* ClientFirestore.ClientFirestore;
41
+ * const snapshot = yield* firestore.getDoc(Posts.doc(Posts.id.make("hello")));
42
+ * yield* Effect.log(snapshot.metadata.fromCache ? "from the cache" : "from the server");
43
+ * });
44
+ *
45
+ * const FirestoreLive = ClientFirestore.layer().pipe(
46
+ * Layer.provide(App.layer({ apiKey: "<api key>", projectId: "my-project", appId: "<app id>" })),
47
+ * );
48
+ *
49
+ * program.pipe(Effect.provide(FirestoreLive));
50
+ * ```
51
+ *
52
+ * @see {@link AdminFirestore} for the same service on the Admin SDK, for servers
53
+ *
54
+ * @stability unstable
55
+ * @since 0.1.0
56
+ */
57
+ var ClientFirestore_exports = /* @__PURE__ */ __exportAll({
58
+ ClientFirestore: () => ClientFirestore,
59
+ layer: () => layer,
60
+ make: () => make
61
+ });
62
+ /**
63
+ * Service key for {@link ClientFirestore}.
64
+ *
65
+ * @see {@link Firestore} for the portable key, which {@link layer} provides the same service under
66
+ *
67
+ * @stability unstable
68
+ * @category services
69
+ * @since 0.1.0
70
+ */
71
+ const ClientFirestore = Context.Service("@visiolab/effect-firebase-client/firestore/ClientFirestore");
72
+ /**
73
+ * Builds {@link ClientFirestore} on the {@link App.App} in context.
74
+ *
75
+ * **When to use**
76
+ *
77
+ * Use to build the service inside an effect of your own. Most programs provide
78
+ * it with {@link layer} instead, which also provides it as {@link Firestore}.
79
+ *
80
+ * **Details**
81
+ *
82
+ * Building the service cannot fail. Opening a database only throws for an app
83
+ * that was already deleted, or a database already opened or used with other
84
+ * settings. Both are wiring mistakes, so they are defects, and a
85
+ * {@link Firestore.FirestoreError} only ever means that a call failed.
86
+ *
87
+ * A write only succeeds once the server acknowledges it, so a write made
88
+ * offline waits for the connection. It is applied to the local cache at once
89
+ * and sent when it can be: interrupting the write, or timing it out, does not
90
+ * take it back.
91
+ *
92
+ * A server timestamp the server has not settled yet reads as the local clock's
93
+ * estimate, so the field decodes as a timestamp.
94
+ *
95
+ * @see {@link layer} for the same as a layer
96
+ *
97
+ * @stability unstable
98
+ * @category constructors
99
+ * @since 0.1.0
100
+ */
101
+ const make = Effect.fn("ClientFirestore.make")(function* (options) {
102
+ const firestore = yield* openDatabase(options);
103
+ return fromDatabase(firestore);
104
+ });
105
+ /** The one service, under both its own tag and the portable one. */
106
+ const both = (service) => Context.make(ClientFirestore, service).pipe(Context.add(Firestore, service));
107
+ /**
108
+ * A layer that provides {@link ClientFirestore} for the {@link App.App} in
109
+ * context, and the same service as the portable {@link Firestore}.
110
+ *
111
+ * **When to use**
112
+ *
113
+ * Use in a browser, or anywhere the client SDK runs. On a server, use
114
+ * {@link AdminFirestore.layer} instead.
115
+ *
116
+ * **Details**
117
+ *
118
+ * With no options it opens the project's default database with the SDK's
119
+ * defaults.
120
+ *
121
+ * @example Providing Firestore with a persistent cache
122
+ * ```ts
123
+ * import { Layer } from "effect";
124
+ * import { persistentLocalCache } from "firebase/firestore";
125
+ * import { App } from "@visiolab/effect-firebase-client/app";
126
+ * import { ClientFirestore } from "@visiolab/effect-firebase-client/firestore";
127
+ *
128
+ * const FirestoreLive = ClientFirestore.layer({
129
+ * localCache: persistentLocalCache(),
130
+ * emulator: import.meta.env.DEV ? { host: "127.0.0.1", port: 8080 } : undefined,
131
+ * }).pipe(
132
+ * Layer.provide(App.layer({ apiKey: "<api key>", projectId: "my-project", appId: "<app id>" })),
133
+ * );
134
+ * ```
135
+ *
136
+ * @see {@link make} for why building the service cannot fail
137
+ * @see {@link AdminFirestore.layer} for the Admin SDK's layer, for servers
138
+ *
139
+ * @stability unstable
140
+ * @category layers
141
+ * @since 0.1.0
142
+ */
143
+ const layer = (options) => Layer.effectContext(Effect.map(make(options), both));
144
+ export { ClientFirestore, ClientFirestore_exports, layer, make };
145
+
146
+ //# sourceMappingURL=ClientFirestore.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClientFirestore.mjs","names":["internalFirestore.openDatabase","internalFirestore.fromDatabase"],"sources":["../../src/firestore/ClientFirestore.ts"],"sourcesContent":["/**\n * Firestore on the Firebase client SDK, for browsers.\n *\n * {@link layer} provides one service under two keys: the portable\n * {@link Firestore}, which code that runs on either SDK asks for, and\n * {@link ClientFirestore}, which adds what only the client SDK can do: read\n * sources, listen options, and the\n * {@link ClientDocumentSnapshot.SnapshotMetadata} of every read. Both reach the\n * same database.\n *\n * Where it behaves differently from the Admin SDK:\n *\n * - The emulator is a layer option, not an environment variable.\n * - A write only succeeds once the server acknowledges it, so a write made\n * offline waits for the connection. It is applied to the local cache at once\n * and sent when it can be; interrupting the write does not take it back.\n * - A pending server timestamp reads as the local clock's estimate, not `null`,\n * so it decodes as a timestamp before the server has settled it.\n * - Error codes are always named, such as `permission-denied`.\n *\n * @example Reading a document, and where the read came from\n * ```ts\n * import { Effect, Layer, Schema } from \"effect\";\n * import { Collection, FirestoreModel } from \"@visiolab/effect-firebase/firestore\";\n * import { App } from \"@visiolab/effect-firebase-client/app\";\n * import { ClientFirestore } from \"@visiolab/effect-firebase-client/firestore\";\n *\n * class Post extends FirestoreModel.Class<Post>(\"Post\")({\n * title: Schema.String,\n * }) {}\n *\n * const Posts = Collection.make(\"posts\", Post);\n *\n * const program = Effect.gen(function* () {\n * const firestore = yield* ClientFirestore.ClientFirestore;\n * const snapshot = yield* firestore.getDoc(Posts.doc(Posts.id.make(\"hello\")));\n * yield* Effect.log(snapshot.metadata.fromCache ? \"from the cache\" : \"from the server\");\n * });\n *\n * const FirestoreLive = ClientFirestore.layer().pipe(\n * Layer.provide(App.layer({ apiKey: \"<api key>\", projectId: \"my-project\", appId: \"<app id>\" })),\n * );\n *\n * program.pipe(Effect.provide(FirestoreLive));\n * ```\n *\n * @see {@link AdminFirestore} for the same service on the Admin SDK, for servers\n *\n * @stability unstable\n * @since 0.1.0\n */\nimport { Context, Effect, Layer } from \"effect\";\nimport { Firestore, type With } from \"@visiolab/effect-firebase/firestore/Firestore\";\nimport type { Firestore as SdkFirestore, FirestoreLocalCache } from \"firebase/firestore\";\nimport type * as App from \"../app/App.ts\";\nimport type * as ClientDocumentSnapshot from \"./ClientDocumentSnapshot.ts\";\n// Only {@link ClientFirestore}'s documentation links to it.\n// oxlint-disable-next-line no-unused-vars\nimport type * as ClientQuerySnapshot from \"./ClientQuerySnapshot.ts\";\nimport * as internalFirestore from \"./internal/firestore.ts\";\n\nconst TypeId = internalFirestore.TypeId;\n\n/**\n * The portable {@link Firestore}, plus what only the client SDK can do.\n *\n * **When to use**\n *\n * Ask for it where code needs the client SDK: a read from the server or the\n * cache alone, metadata changes on a listen, a snapshot's\n * {@link ClientDocumentSnapshot.SnapshotMetadata}, or the SDK itself through\n * {@link ClientFirestore.instance}. Everywhere else ask for {@link Firestore},\n * so the code also runs on the Admin SDK.\n *\n * **Details**\n *\n * Its reads take {@link ReadOptions} and its listens {@link ListenOptions}.\n * Every document snapshot, each document of a query snapshot, and each query\n * snapshot as a whole carries the `metadata` of its read, as a\n * {@link ClientDocumentSnapshot.ClientDocumentSnapshot} or\n * {@link ClientQuerySnapshot.ClientQuerySnapshot} does.\n *\n * The service its key holds is also a {@link Firestore}, so it can be handed\n * to code that expects one as it is. The type itself only extends\n * {@link Firestore.With}, so providing a {@link Firestore} alone, such as an\n * in-memory fake, does not satisfy code that asks for it. Its\n * transactions are the portable {@link Firestore.Transaction}: the client SDK's\n * transactions read one document at a time.\n *\n * The client SDK cannot abort a request in flight, so interrupting a call does\n * not stop it: the request still runs to completion.\n *\n * @see {@link Firestore.With} for each read and write it offers\n *\n * @stability unstable\n * @category models\n * @since 0.1.0\n */\nexport interface ClientFirestore extends With<\n ReadOptions,\n ListenOptions,\n { readonly metadata: ClientDocumentSnapshot.SnapshotMetadata }\n> {\n readonly [TypeId]: typeof TypeId;\n\n /**\n * The client SDK's own `Firestore`, for the database the service was opened\n * on.\n *\n * **When to use**\n *\n * Use for what this service does not wrap, such as queries or\n * `disableNetwork` and `enableNetwork`. Prefer the service's own methods\n * where one exists.\n *\n * **Details**\n *\n * Calls through it skip the collection's model, take and return the SDK's\n * own values, and throw the SDK's own errors. To write a model through it,\n * encode with {@link FirestoreValue.toCodecFirestore} and map with\n * {@link ClientFirestoreValue.toClient}.\n *\n * @see {@link ClientFirestoreValue} for mapping between the SDK's values and Firestore Values\n */\n readonly instance: SdkFirestore;\n}\n\n/**\n * How `streamDoc` and `streamDocs` on {@link ClientFirestore} listen, named as\n * in the client SDK's own listen options.\n *\n * **When to use**\n *\n * Use to also hear metadata changes, such as a pending write being\n * acknowledged, or to listen to the local cache alone. Left out, a listen\n * behaves as the SDK's does by default: it emits only when the data changes.\n *\n * **Details**\n *\n * Every snapshot a listen emits carries the\n * {@link ClientDocumentSnapshot.SnapshotMetadata} it arrived with. The portable\n * {@link Firestore.With.streamDoc} takes no options, because the Admin SDK's\n * listeners take none.\n *\n * @example Waiting for the server to acknowledge a write\n * ```ts\n * import { Effect, Schema, Stream } from \"effect\";\n * import { Collection, FirestoreModel } from \"@visiolab/effect-firebase/firestore\";\n * import { ClientFirestore } from \"@visiolab/effect-firebase-client/firestore\";\n *\n * class Post extends FirestoreModel.Class<Post>(\"Post\")({\n * title: Schema.String,\n * }) {}\n *\n * const Posts = Collection.make(\"posts\", Post);\n * const hello = Posts.doc(Posts.id.make(\"hello\"));\n *\n * const acknowledged = Effect.gen(function* () {\n * const firestore = yield* ClientFirestore.ClientFirestore;\n * yield* firestore.streamDoc(hello, { includeMetadataChanges: true }).pipe(\n * Stream.filter((snapshot) => !snapshot.metadata.hasPendingWrites),\n * Stream.runHead,\n * );\n * });\n * ```\n *\n * @see {@link ReadOptions} for the options of a one-off read\n *\n * @stability unstable\n * @category models\n * @since 0.1.0\n */\nexport interface ListenOptions {\n /**\n * Whether to also emit when only the\n * {@link ClientDocumentSnapshot.SnapshotMetadata} changes, such as when the\n * server acknowledges a pending write or the cache catches up with the\n * server. Without it, a listen only emits when the data changes.\n */\n readonly includeMetadataChanges?: boolean | undefined;\n /**\n * Where to listen. `\"default\"` listens to the server and the local cache.\n * `\"cache\"` listens to the local cache alone and never reaches the server, so\n * it only sees what this client has written or already read.\n */\n readonly source?: \"default\" | \"cache\" | undefined;\n}\n\n/**\n * Service key for {@link ClientFirestore}.\n *\n * @see {@link Firestore} for the portable key, which {@link layer} provides the same service under\n *\n * @stability unstable\n * @category services\n * @since 0.1.0\n */\nexport const ClientFirestore = Context.Service<ClientFirestore, ClientFirestore & Firestore>(\n \"@visiolab/effect-firebase-client/firestore/ClientFirestore\",\n);\n\n/**\n * Where a one-off read is served from.\n *\n * - `\"default\"`: the server when it can be reached, otherwise the local cache.\n * What a read does when no source is given.\n * - `\"server\"`: the server alone. Fails with the SDK's code when the server\n * cannot be reached, instead of falling back to the cache.\n * - `\"cache\"`: the local cache alone, without asking the server.\n *\n * The two reads report what the cache lacks differently, as the SDK does. A\n * cached `getDoc` of a document the cache has never seen fails with a\n * {@link Firestore.FirestoreError} whose code is `unavailable`, and one the\n * cache knows was deleted reads as `Missing`. A cached `getDocs` never fails\n * for what the cache lacks: it returns whatever the cache holds, which may be\n * nothing, with `fromCache: true`.\n *\n * @see {@link ReadOptions} for passing it to a read\n *\n * @stability unstable\n * @category models\n * @since 0.1.0\n */\nexport type ReadSource = \"default\" | \"server\" | \"cache\";\n\n/**\n * How `getDoc` and `getDocs` on {@link ClientFirestore} read a document, a\n * collection, or a Collection Group.\n *\n * **When to use**\n *\n * Use to read from the server alone, such as to confirm a value before acting\n * on it, or from the local cache alone, such as to render at once while\n * offline. Left out, a read behaves as the SDK's does by default.\n *\n * **Details**\n *\n * With `source: \"cache\"`, a `getDoc` of a document the cache has never seen\n * fails with a {@link Firestore.FirestoreError} whose code is `unavailable`:\n * not being cached is not the same as not existing. One the cache knows was\n * deleted reads as `Missing`. A `getDocs` never fails for what the cache lacks:\n * it returns whatever the cache holds, which may be nothing, with `fromCache:\n * true`. So, unlike `getDoc`, an empty result cannot tell \"nothing cached\" from\n * \"nothing there\".\n *\n * The portable {@link Firestore.With.getDoc} takes no options, because the\n * Admin SDK's reads take none.\n *\n * @example Reading from the server alone\n * ```ts\n * import { Effect, Schema } from \"effect\";\n * import { Collection, FirestoreModel } from \"@visiolab/effect-firebase/firestore\";\n * import { ClientFirestore } from \"@visiolab/effect-firebase-client/firestore\";\n *\n * class Post extends FirestoreModel.Class<Post>(\"Post\")({\n * title: Schema.String,\n * }) {}\n *\n * const Posts = Collection.make(\"posts\", Post);\n *\n * const fresh = Effect.gen(function* () {\n * const firestore = yield* ClientFirestore.ClientFirestore;\n * return yield* firestore.getDoc(Posts.doc(Posts.id.make(\"hello\")), { source: \"server\" });\n * });\n * ```\n *\n * @see {@link ReadSource} for where a read can be served from\n * @see {@link ListenOptions} for the options of a listen\n *\n * @stability unstable\n * @category models\n * @since 0.1.0\n */\nexport interface ReadOptions {\n /**\n * Where the read is served from. Left out, it is `\"default\"`.\n *\n * @see {@link ReadSource} for each source, and what a cached read does with what the cache lacks\n */\n readonly source?: ReadSource | undefined;\n}\n\n/**\n * Where the Firestore emulator listens, such as `{ host: \"127.0.0.1\", port:\n * 8080 }`.\n *\n * @see {@link Options.emulator} for connecting to it\n *\n * @stability unstable\n * @category models\n * @since 0.1.0\n */\nexport interface Emulator {\n readonly host: string;\n readonly port: number;\n}\n\n/**\n * How {@link layer} opens a database. All of them are fixed once the database\n * is open.\n *\n * @see {@link AdminFirestore.Options} for the Admin SDK's, which read the emulator from the environment\n *\n * @stability unstable\n * @category models\n * @since 0.1.0\n */\nexport interface Options {\n /**\n * The database to open, where the project has more than its default one.\n * Leave it out for the default database.\n */\n readonly databaseId?: string | undefined;\n /**\n * The emulator to talk to instead of the project's database.\n *\n * Unlike the Admin SDK, the client SDK takes the emulator per database, not\n * from the environment, and only before the database is first used.\n */\n readonly emulator?: Emulator | undefined;\n /**\n * Where the SDK keeps the documents it has seen and the writes it has yet to\n * send: `memoryLocalCache()`, the SDK's default, or `persistentLocalCache()`,\n * which keeps them in IndexedDB across reloads.\n */\n readonly localCache?: FirestoreLocalCache | undefined;\n}\n\n/**\n * Builds {@link ClientFirestore} on the {@link App.App} in context.\n *\n * **When to use**\n *\n * Use to build the service inside an effect of your own. Most programs provide\n * it with {@link layer} instead, which also provides it as {@link Firestore}.\n *\n * **Details**\n *\n * Building the service cannot fail. Opening a database only throws for an app\n * that was already deleted, or a database already opened or used with other\n * settings. Both are wiring mistakes, so they are defects, and a\n * {@link Firestore.FirestoreError} only ever means that a call failed.\n *\n * A write only succeeds once the server acknowledges it, so a write made\n * offline waits for the connection. It is applied to the local cache at once\n * and sent when it can be: interrupting the write, or timing it out, does not\n * take it back.\n *\n * A server timestamp the server has not settled yet reads as the local clock's\n * estimate, so the field decodes as a timestamp.\n *\n * @see {@link layer} for the same as a layer\n *\n * @stability unstable\n * @category constructors\n * @since 0.1.0\n */\nexport const make: (\n options?: Options,\n) => Effect.Effect<ClientFirestore & Firestore, never, App.App> = Effect.fn(\"ClientFirestore.make\")(\n function* (options?: Options) {\n const firestore = yield* internalFirestore.openDatabase(options);\n return internalFirestore.fromDatabase(firestore);\n },\n);\n\n/** The one service, under both its own tag and the portable one. */\nconst both = (service: ClientFirestore & Firestore) =>\n Context.make(ClientFirestore, service).pipe(Context.add(Firestore, service));\n\n/**\n * A layer that provides {@link ClientFirestore} for the {@link App.App} in\n * context, and the same service as the portable {@link Firestore}.\n *\n * **When to use**\n *\n * Use in a browser, or anywhere the client SDK runs. On a server, use\n * {@link AdminFirestore.layer} instead.\n *\n * **Details**\n *\n * With no options it opens the project's default database with the SDK's\n * defaults.\n *\n * @example Providing Firestore with a persistent cache\n * ```ts\n * import { Layer } from \"effect\";\n * import { persistentLocalCache } from \"firebase/firestore\";\n * import { App } from \"@visiolab/effect-firebase-client/app\";\n * import { ClientFirestore } from \"@visiolab/effect-firebase-client/firestore\";\n *\n * const FirestoreLive = ClientFirestore.layer({\n * localCache: persistentLocalCache(),\n * emulator: import.meta.env.DEV ? { host: \"127.0.0.1\", port: 8080 } : undefined,\n * }).pipe(\n * Layer.provide(App.layer({ apiKey: \"<api key>\", projectId: \"my-project\", appId: \"<app id>\" })),\n * );\n * ```\n *\n * @see {@link make} for why building the service cannot fail\n * @see {@link AdminFirestore.layer} for the Admin SDK's layer, for servers\n *\n * @stability unstable\n * @category layers\n * @since 0.1.0\n */\nexport const layer = (\n options?: Options,\n): Layer.Layer<ClientFirestore | Firestore, never, App.App> =>\n Layer.effectContext(Effect.map(make(options), both));\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqMA,MAAa,kBAAkB,QAAQ,QACrC,4DACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8JA,MAAa,OAEqD,OAAO,GAAG,sBAAsB,CAAC,CACjG,WAAW,SAAmB;CAC5B,MAAM,YAAY,OAAOA,aAA+B,OAAO;CAC/D,OAAOC,aAA+B,SAAS;AACjD,CACF;;AAGA,MAAM,QAAQ,YACZ,QAAQ,KAAK,iBAAiB,OAAO,CAAC,CAAC,KAAK,QAAQ,IAAI,WAAW,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsC7E,MAAa,SACX,YAEA,MAAM,cAAc,OAAO,IAAI,KAAK,OAAO,GAAG,IAAI,CAAC"}
@@ -0,0 +1,61 @@
1
+ import { Result } from "effect";
2
+ import { FirestoreError } from "@visiolab/effect-firebase/firestore/Firestore";
3
+ import { Firestore as Firestore$1 } from "firebase/firestore";
4
+ import { FirestoreValue } from "@visiolab/effect-firebase/firestore/FirestoreValue";
5
+ declare namespace ClientFirestoreValue_d_exports {
6
+ export { fromClient, toClient };
7
+ }
8
+ /**
9
+ * Turns a Firestore Value into the value the client SDK writes into
10
+ * `firestore`.
11
+ *
12
+ * **When to use**
13
+ *
14
+ * Use to write what a model encodes to through the client SDK itself.
15
+ *
16
+ * **Details**
17
+ *
18
+ * The portable `Timestamp`, `GeoPoint` and bytes become the SDK's `Timestamp`,
19
+ * `GeoPoint` and `Bytes`, and the sentinels its `FieldValue`s. A `DocumentPath`
20
+ * becomes `doc(firestore, path)`, so it points into that database. Map keys are
21
+ * kept as they are, so the dotted field paths of an update stay field paths.
22
+ *
23
+ * It throws for anything that is not a Firestore Value, such as one of the
24
+ * client SDK's own values or a class instance cast past the type. What
25
+ * {@link FirestoreValue.toCodecFirestore} encodes is always a Firestore Value.
26
+ *
27
+ * @see {@link fromClient} for the other direction
28
+ *
29
+ * @stability unstable
30
+ * @category conversions
31
+ * @since 0.3.0
32
+ */
33
+ export declare const toClient: (value: FirestoreValue, firestore: Firestore$1) => unknown;
34
+ /**
35
+ * Turns a value the client SDK read into a Firestore Value.
36
+ *
37
+ * **When to use**
38
+ *
39
+ * Use to decode what the client SDK itself read through a model, with
40
+ * {@link FirestoreValue.toCodecFirestore}.
41
+ *
42
+ * **Details**
43
+ *
44
+ * The SDK's `Timestamp`, `GeoPoint` and `Bytes` become the portable
45
+ * `Timestamp`, `GeoPoint` and `Uint8Array`. A `DocumentReference` becomes the
46
+ * `DocumentPath` it points at, since Firestore stores nothing else of it;
47
+ * {@link FirestoreSchema.DocumentReference} reads that back into the
48
+ * collection it names.
49
+ *
50
+ * Fails with a {@link Firestore.FirestoreError} naming the field for a value
51
+ * that is not a Firestore Value, such as a vector.
52
+ *
53
+ * @see {@link toClient} for the other direction
54
+ *
55
+ * @stability unstable
56
+ * @category conversions
57
+ * @since 0.3.0
58
+ */
59
+ export declare const fromClient: (value: unknown) => Result.Result<FirestoreValue, FirestoreError>;
60
+ export { ClientFirestoreValue_d_exports };
61
+ //# sourceMappingURL=ClientFirestoreValue.d.mts.map
@@ -0,0 +1,62 @@
1
+ import { __exportAll } from "../_virtual/_rolldown/runtime.mjs";
2
+ import { fromClient as fromClient$1, toClient as toClient$1 } from "./internal/firestoreValue.mjs";
3
+ // src/firestore/ClientFirestoreValue.ts
4
+ var ClientFirestoreValue_exports = /* @__PURE__ */ __exportAll({
5
+ fromClient: () => fromClient,
6
+ toClient: () => toClient
7
+ });
8
+ /**
9
+ * Turns a Firestore Value into the value the client SDK writes into
10
+ * `firestore`.
11
+ *
12
+ * **When to use**
13
+ *
14
+ * Use to write what a model encodes to through the client SDK itself.
15
+ *
16
+ * **Details**
17
+ *
18
+ * The portable `Timestamp`, `GeoPoint` and bytes become the SDK's `Timestamp`,
19
+ * `GeoPoint` and `Bytes`, and the sentinels its `FieldValue`s. A `DocumentPath`
20
+ * becomes `doc(firestore, path)`, so it points into that database. Map keys are
21
+ * kept as they are, so the dotted field paths of an update stay field paths.
22
+ *
23
+ * It throws for anything that is not a Firestore Value, such as one of the
24
+ * client SDK's own values or a class instance cast past the type. What
25
+ * {@link FirestoreValue.toCodecFirestore} encodes is always a Firestore Value.
26
+ *
27
+ * @see {@link fromClient} for the other direction
28
+ *
29
+ * @stability unstable
30
+ * @category conversions
31
+ * @since 0.3.0
32
+ */
33
+ const toClient = toClient$1;
34
+ /**
35
+ * Turns a value the client SDK read into a Firestore Value.
36
+ *
37
+ * **When to use**
38
+ *
39
+ * Use to decode what the client SDK itself read through a model, with
40
+ * {@link FirestoreValue.toCodecFirestore}.
41
+ *
42
+ * **Details**
43
+ *
44
+ * The SDK's `Timestamp`, `GeoPoint` and `Bytes` become the portable
45
+ * `Timestamp`, `GeoPoint` and `Uint8Array`. A `DocumentReference` becomes the
46
+ * `DocumentPath` it points at, since Firestore stores nothing else of it;
47
+ * {@link FirestoreSchema.DocumentReference} reads that back into the
48
+ * collection it names.
49
+ *
50
+ * Fails with a {@link Firestore.FirestoreError} naming the field for a value
51
+ * that is not a Firestore Value, such as a vector.
52
+ *
53
+ * @see {@link toClient} for the other direction
54
+ *
55
+ * @stability unstable
56
+ * @category conversions
57
+ * @since 0.3.0
58
+ */
59
+ const fromClient = fromClient$1;
60
+ export { ClientFirestoreValue_exports, fromClient, toClient };
61
+
62
+ //# sourceMappingURL=ClientFirestoreValue.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClientFirestoreValue.mjs","names":["internal.toClient","internal.fromClient"],"sources":["../../src/firestore/ClientFirestoreValue.ts"],"sourcesContent":["/**\n * Maps between Firestore Values, the portable values a model encodes to, and\n * the values the client SDK reads and writes.\n *\n * {@link ClientFirestore} applies it on every read and write. Use it directly\n * to read or write a model through the client SDK itself, such as through\n * {@link ClientFirestore.instance}.\n *\n * @example Writing a model through the client SDK\n * ```ts\n * import { Schema } from \"effect\";\n * import { FirestoreModel, FirestoreValue } from \"@visiolab/effect-firebase/firestore\";\n * import { ClientFirestoreValue } from \"@visiolab/effect-firebase-client/firestore\";\n * import { type DocumentData, doc, getFirestore, setDoc } from \"firebase/firestore\";\n *\n * class Post extends FirestoreModel.Class<Post>(\"Post\")({\n * title: Schema.String,\n * }) {}\n *\n * const firestore = getFirestore();\n * const encoded = Schema.encodeSync(FirestoreValue.toCodecFirestore(Post.create))({\n * title: \"Hello\",\n * });\n * await setDoc(\n * doc(firestore, \"posts/hello\"),\n * ClientFirestoreValue.toClient(encoded, firestore) as DocumentData,\n * );\n * ```\n *\n * @see {@link AdminFirestoreValue} for the Admin SDK's mapping\n *\n * @stability unstable\n * @since 0.3.0\n */\nimport type { Result } from \"effect\";\nimport type { FirestoreError } from \"@visiolab/effect-firebase/firestore/Firestore\";\nimport type { FirestoreValue } from \"@visiolab/effect-firebase/firestore/FirestoreValue\";\nimport type { Firestore } from \"firebase/firestore\";\nimport * as internal from \"./internal/firestoreValue.ts\";\n\n/**\n * Turns a Firestore Value into the value the client SDK writes into\n * `firestore`.\n *\n * **When to use**\n *\n * Use to write what a model encodes to through the client SDK itself.\n *\n * **Details**\n *\n * The portable `Timestamp`, `GeoPoint` and bytes become the SDK's `Timestamp`,\n * `GeoPoint` and `Bytes`, and the sentinels its `FieldValue`s. A `DocumentPath`\n * becomes `doc(firestore, path)`, so it points into that database. Map keys are\n * kept as they are, so the dotted field paths of an update stay field paths.\n *\n * It throws for anything that is not a Firestore Value, such as one of the\n * client SDK's own values or a class instance cast past the type. What\n * {@link FirestoreValue.toCodecFirestore} encodes is always a Firestore Value.\n *\n * @see {@link fromClient} for the other direction\n *\n * @stability unstable\n * @category conversions\n * @since 0.3.0\n */\nexport const toClient: (value: FirestoreValue, firestore: Firestore) => unknown = internal.toClient;\n\n/**\n * Turns a value the client SDK read into a Firestore Value.\n *\n * **When to use**\n *\n * Use to decode what the client SDK itself read through a model, with\n * {@link FirestoreValue.toCodecFirestore}.\n *\n * **Details**\n *\n * The SDK's `Timestamp`, `GeoPoint` and `Bytes` become the portable\n * `Timestamp`, `GeoPoint` and `Uint8Array`. A `DocumentReference` becomes the\n * `DocumentPath` it points at, since Firestore stores nothing else of it;\n * {@link FirestoreSchema.DocumentReference} reads that back into the\n * collection it names.\n *\n * Fails with a {@link Firestore.FirestoreError} naming the field for a value\n * that is not a Firestore Value, such as a vector.\n *\n * @see {@link toClient} for the other direction\n *\n * @stability unstable\n * @category conversions\n * @since 0.3.0\n */\nexport const fromClient: (value: unknown) => Result.Result<FirestoreValue, FirestoreError> =\n internal.fromClient;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiEA,MAAa,WAAqEA;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BlF,MAAa,aACXC"}