@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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 VisioLab GmbH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,82 @@
1
- # Temporary Holding Version
1
+ # @visiolab/effect-firebase
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Typed Firestore collections and Firebase services for [Effect](https://effect.website), independent of any Firebase SDK.
4
+
5
+ This package defines the services and the document models. Two packages implement them:
6
+
7
+ | Package | Runs on | SDK |
8
+ | ----------------------------------------------------------------------------------------------------------- | --------------------- | ---------------- |
9
+ | [`@visiolab/effect-firebase-admin`](https://github.com/VisioLab/effect-firebase/tree/main/packages/admin) | servers and functions | `firebase-admin` |
10
+ | [`@visiolab/effect-firebase-client`](https://github.com/VisioLab/effect-firebase/tree/main/packages/client) | browsers and apps | `firebase` |
11
+
12
+ Code written against this package, such as models, collections and the portable `Firestore` service, runs unchanged on either.
13
+
14
+ ## Install
15
+
16
+ ```sh
17
+ pnpm add effect @visiolab/effect-firebase @visiolab/effect-firebase-admin firebase-admin
18
+ # or, in a browser or app
19
+ pnpm add effect @visiolab/effect-firebase @visiolab/effect-firebase-client firebase
20
+ ```
21
+
22
+ ## Example
23
+
24
+ Define a document with `FirestoreModel.Class`, where it lives with `Collection.make`, and read and write it through the `Firestore` service:
25
+
26
+ ```ts
27
+ import { Effect, Layer, Schema } from "effect";
28
+ import {
29
+ Collection,
30
+ DocumentSnapshot,
31
+ Firestore,
32
+ FirestoreModel,
33
+ } from "@visiolab/effect-firebase/firestore";
34
+ import { App } from "@visiolab/effect-firebase-admin/app";
35
+ import { AdminFirestore } from "@visiolab/effect-firebase-admin/firestore";
36
+
37
+ class User extends FirestoreModel.Class<User>("User")({
38
+ name: Schema.String,
39
+ visits: FirestoreModel.Number(Schema.Int),
40
+ }) {}
41
+
42
+ const Users = Collection.make("users", User);
43
+
44
+ const program = Effect.gen(function* () {
45
+ const firestore = yield* Firestore.Firestore;
46
+ const alice = Users.doc(Users.id.make("alice"));
47
+
48
+ yield* firestore.setDoc(alice, { name: "Alice", visits: 0 });
49
+
50
+ const snapshot = yield* firestore.getDoc(alice);
51
+ if (DocumentSnapshot.isExisting(snapshot)) {
52
+ const user = yield* snapshot.data;
53
+ yield* Effect.log(`${user.name} has visited ${user.visits} times`);
54
+ }
55
+ });
56
+
57
+ const FirestoreLive = AdminFirestore.layer().pipe(Layer.provide(App.layer()));
58
+
59
+ Effect.runPromise(program.pipe(Effect.provide(FirestoreLive)));
60
+ ```
61
+
62
+ `program` only asks for the portable `Firestore`, so providing `ClientFirestore.layer` from `@visiolab/effect-firebase-client` runs it on the client SDK instead.
63
+
64
+ ## Modules
65
+
66
+ Everything is exported from `@visiolab/effect-firebase/firestore`, and each module from its own path, such as `@visiolab/effect-firebase/firestore/Collection`.
67
+
68
+ | Module | What it is for |
69
+ | ------------------ | --------------------------------------------------------------------------------- |
70
+ | `Firestore` | The service: read, listen to, write and update documents, and run transactions. |
71
+ | `FirestoreModel` | Document models, with the shapes a document is created, updated and read in. |
72
+ | `FirestoreSchema` | Schemas for Firestore's own values, such as timestamps and server-side sentinels. |
73
+ | `Collection` | Where documents live, and typed references to them. |
74
+ | `CollectionGroup` | Every collection with the same id, read together. |
75
+ | `DocumentSnapshot` | A document as a read found it: there or missing. |
76
+ | `QuerySnapshot` | The documents a read of a collection or group found. |
77
+ | `FieldValue` | Server-side writes: `serverTimestamp`, `increment`, `arrayUnion` and the others. |
78
+ | `Patch` | `Patch.replace`, to write a nested struct whole in an update. |
79
+ | `Timestamp` | Firestore's timestamp, to the nanosecond. |
80
+ | `GeoPoint` | Firestore's geographic point. |
81
+ | `DocumentPath` | An untyped document reference, as Firestore stores it in a field. |
82
+ | `FirestoreValue` | Values as Firestore stores them, and the codec models encode through. |
@@ -0,0 +1,12 @@
1
+ // \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __exportAll = (all, no_symbols) => {
4
+ let target = {};
5
+ for (var name in all) __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true
8
+ });
9
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
10
+ return target;
11
+ };
12
+ export { __exportAll };
@@ -0,0 +1,27 @@
1
+ declare namespace App_d_exports {
2
+ export { defaultAppName };
3
+ }
4
+ /**
5
+ * What the SDK packages' `App` modules share.
6
+ *
7
+ * The app service itself belongs to each SDK package: see the `App` modules
8
+ * of [`@visiolab/effect-firebase-admin`](/api/admin/app/App/) and
9
+ * [`@visiolab/effect-firebase-client`](/api/client/app/App/).
10
+ *
11
+ * @stability unstable
12
+ * @since 0.1.0
13
+ */
14
+ /**
15
+ * The name Firebase gives an app that was initialized without one.
16
+ *
17
+ * **When to use**
18
+ *
19
+ * Use to compare against an app's `name`, or to name the default app
20
+ * explicitly.
21
+ *
22
+ * @stability unstable
23
+ * @category constants
24
+ * @since 0.1.0
25
+ */
26
+ export declare const defaultAppName = "[DEFAULT]";
27
+ export { App_d_exports };
@@ -0,0 +1,27 @@
1
+ import { __exportAll } from "../_virtual/_rolldown/runtime.mjs";
2
+ // src/app/App.ts
3
+ var App_exports = /* @__PURE__ */ __exportAll({ defaultAppName: () => defaultAppName });
4
+ /**
5
+ * What the SDK packages' `App` modules share.
6
+ *
7
+ * The app service itself belongs to each SDK package: see the `App` modules
8
+ * of [`@visiolab/effect-firebase-admin`](/api/admin/app/App/) and
9
+ * [`@visiolab/effect-firebase-client`](/api/client/app/App/).
10
+ *
11
+ * @stability unstable
12
+ * @since 0.1.0
13
+ */
14
+ /**
15
+ * The name Firebase gives an app that was initialized without one.
16
+ *
17
+ * **When to use**
18
+ *
19
+ * Use to compare against an app's `name`, or to name the default app
20
+ * explicitly.
21
+ *
22
+ * @stability unstable
23
+ * @category constants
24
+ * @since 0.1.0
25
+ */
26
+ const defaultAppName = "[DEFAULT]";
27
+ export { App_exports, defaultAppName };
@@ -0,0 +1,2 @@
1
+ import { App_d_exports } from "./App.mjs";
2
+ export { App_d_exports as App };
@@ -0,0 +1 @@
1
+ export { App_exports as App } from "./App.mjs";
@@ -0,0 +1,423 @@
1
+ import { DocumentSnapshot, Existing, Missing } from "./DocumentSnapshot.mjs";
2
+ import { Any as Any$1 } from "./FirestoreModel.mjs";
3
+ import { Brand, Equal, Inspectable, Option, Schema } from "effect";
4
+ declare namespace Collection_d_exports {
5
+ export { Ancestors, Any, Collection, CollectionReference, DocumentReference, DocumentSchema, Id, IdSchema, Level, Levels, fromPath, isCollection, isCollectionReference, isDocumentReference, make };
6
+ }
7
+ declare const CollectionTypeId = "~@visiolab/effect-firebase/firestore/Collection";
8
+ declare const CollectionReferenceTypeId = "~@visiolab/effect-firebase/firestore/CollectionReference";
9
+ declare const DocumentReferenceTypeId = "~@visiolab/effect-firebase/firestore/DocumentReference";
10
+ /**
11
+ * One link of a collection's path: a segment and the model of the documents
12
+ * stored under it.
13
+ *
14
+ * @stability unstable
15
+ * @category models
16
+ * @since 0.1.0
17
+ */
18
+ export type Level = readonly [segment: string, schema: Any$1];
19
+ /**
20
+ * The {@link Level}s from a root collection down to a collection itself.
21
+ *
22
+ * **Details**
23
+ *
24
+ * A {@link Collection} carries the whole chain rather than only its own
25
+ * segment, so the id of every ancestor stays typed.
26
+ *
27
+ * @stability unstable
28
+ * @category models
29
+ * @since 0.1.0
30
+ */
31
+ export type Levels = readonly [Level, ...ReadonlyArray<Level>];
32
+ type Join<S extends ReadonlyArray<string>> = S extends readonly [infer Head extends string, ...infer Tail extends ReadonlyArray<string>] ? Tail extends readonly [] ? Head : `${Head}/${Join<Tail>}` : never;
33
+ /** The last link of the chain. */
34
+ type Leaf<L extends Levels> = L extends readonly [...ReadonlyArray<Level>, infer T extends Level] ? T : never;
35
+ /** The segments of a chain, as a tuple. */
36
+ type SegmentsOf<L extends Levels> = { readonly [K in keyof L]: L[K][0]; };
37
+ /**
38
+ * Document ids are branded with the collection's path, so an id only ever fits
39
+ * the collection it came from. Two collections that share a segment - `posts`
40
+ * under `users` and `posts` under `orgs` - still get distinct ids, because the
41
+ * brand is the whole path rather than the last segment.
42
+ */
43
+ type IdOf<L extends Levels> = string & Brand.Brand<Join<SegmentsOf<L>>>;
44
+ /**
45
+ * One id per ancestor, ordered from the root down. A root collection needs
46
+ * none, which is why the recursion bottoms out at the empty tuple.
47
+ *
48
+ * The parent chain is matched inline rather than looked up through an alias, so
49
+ * that the recursion stays deferred until `L` is a concrete chain. Going
50
+ * through an alias makes it eager, and the compiler gives up on the depth.
51
+ */
52
+ type AncestorsOf<L extends Levels> = L extends readonly [...infer I, Level] ? I extends Levels ? [...AncestorsOf<I>, IdOf<I>] : [] : [];
53
+ /**
54
+ * What {@link Collection.contains} narrows each member of `V` to: the members
55
+ * already in `C` are kept, the ones in another collection are dropped, and one
56
+ * whose collection is left open is narrowed to `C`.
57
+ *
58
+ * Every branch is `V` or an intersection with it, which is what lets the
59
+ * compiler see the result is assignable to `V`, as a type predicate must be.
60
+ */
61
+ type Contained<V, C extends Any> = V extends DocumentReference<Any> ? NarrowTo<V, DocumentReference<C>> : V extends Existing<Any> ? NarrowTo<V, Existing<C>> : V extends Missing<Any> ? NarrowTo<V, Missing<C>> : never;
62
+ /**
63
+ * `V` when it is `T`, and `never` when it is not. A `V` whose collection is
64
+ * `any` passes the check without saying anything about it, so it is narrowed
65
+ * by intersecting it with `T` instead.
66
+ */
67
+ type NarrowTo<V, T> = V extends T ? (0 extends 1 & LevelsOf<V> ? V & T : V) : never;
68
+ /** The chain of the collection a reference or snapshot is in. */
69
+ type LevelsOf<V> = V extends DocumentReference<Collection<infer L>> ? L : V extends {
70
+ readonly ref: DocumentReference<Collection<infer L>>;
71
+ } ? L : never;
72
+ /**
73
+ * The schema of a document id in one collection. It decodes a string and
74
+ * brands it with the collection's full path, so the id only fits that
75
+ * collection.
76
+ *
77
+ * **When to use**
78
+ *
79
+ * Use `collection.id.make(raw)` to turn a string you trust into an id, and
80
+ * `Schema.decodeUnknownEffect(collection.id)` to check one from outside.
81
+ *
82
+ * **Details**
83
+ *
84
+ * The brand is the whole path, so `posts` under `users` and `posts` under
85
+ * `orgs` have different id types. Its constructor takes a `string`, which
86
+ * makes passing anything else a type error rather than a runtime throw.
87
+ *
88
+ * @stability unstable
89
+ * @category models
90
+ * @since 0.1.0
91
+ */
92
+ export interface IdSchema<T extends string> extends Schema.Codec<T, string> {
93
+ readonly "~type.make.in": string;
94
+ }
95
+ /**
96
+ * The definition of a collection: where it sits, how its documents are
97
+ * addressed, and the model they hold.
98
+ *
99
+ * **Details**
100
+ *
101
+ * A definition does not point at any data. It describes a collection, and
102
+ * {@link Collection.collection} and {@link Collection.doc} turn it into a
103
+ * reference once you have the ids that address it. Build one with
104
+ * {@link make}, and nest one with {@link Collection.subcollection}.
105
+ *
106
+ * @see {@link CollectionReference} for a reference to one collection, with its ancestor ids filled in
107
+ * @see {@link CollectionGroup.CollectionGroup} for every collection with one collection id, read together
108
+ *
109
+ * @stability unstable
110
+ * @category models
111
+ * @since 0.1.0
112
+ */
113
+ export interface Collection<L extends Levels> extends Inspectable.Inspectable {
114
+ readonly [CollectionTypeId]: typeof CollectionTypeId;
115
+ /** The chain this collection was built from. Only read at the type level. */
116
+ readonly "~levels": L;
117
+ /** The path segments, from the root collection down, such as `["users", "posts"]`. */
118
+ readonly path: SegmentsOf<L>;
119
+ /** The last segment: the collection id Firestore knows the collection by. */
120
+ readonly segment: Leaf<L>[0];
121
+ /**
122
+ * The schema of the ids of documents in this collection.
123
+ *
124
+ * @see {@link IdSchema} for how to make and decode one
125
+ */
126
+ readonly id: IdSchema<IdOf<L>>;
127
+ /**
128
+ * The model of the documents in this collection. Reads decode through it,
129
+ * and writes encode through its {@link FirestoreModel.Class.create} and
130
+ * {@link FirestoreModel.Class.update} variants.
131
+ */
132
+ readonly schema: Leaf<L>[1];
133
+ /**
134
+ * Checks whether a Document Reference or Document Snapshot belongs to this
135
+ * collection, and narrows it to this collection's types when it does.
136
+ *
137
+ * **When to use**
138
+ *
139
+ * Use to pick out the documents of one collection from a mixed result, such
140
+ * as a read of a {@link CollectionGroup.CollectionGroup} with several
141
+ * members: `snapshot.docs.filter(UserPosts.contains)`.
142
+ *
143
+ * **Details**
144
+ *
145
+ * Two definitions are the same collection only when they are the same
146
+ * object, so a definition built separately at the same path does not
147
+ * contain this one's documents. It does not use `this`, so it can be passed
148
+ * on unbound.
149
+ *
150
+ * @see {@link isDocumentReference} for checking that a value is a reference to any collection
151
+ */
152
+ readonly contains: <V extends DocumentReference<Any> | DocumentSnapshot<Any>>(value: V) => value is Contained<V, Collection<L>>;
153
+ /**
154
+ * Defines a subcollection under the documents of this collection.
155
+ *
156
+ * **When to use**
157
+ *
158
+ * Use for a nested collection, such as `posts` under each user. Use
159
+ * {@link make} for a root collection.
160
+ *
161
+ * **Details**
162
+ *
163
+ * Throws when `segment` is not a collection id Firestore accepts: empty,
164
+ * containing `/`, `.` or `..`, matching `__.*__`, or longer than 1500
165
+ * bytes. An invalid definition is a programming error, not a failure to
166
+ * recover from.
167
+ */
168
+ subcollection<const Segment extends string, S extends Any$1>(segment: Segment, schema: S): Collection<readonly [...L, readonly [Segment, S]]>;
169
+ /**
170
+ * References this collection, given one id per ancestor, from the root down.
171
+ * A root collection takes none.
172
+ *
173
+ * **When to use**
174
+ *
175
+ * Use to address the collection itself, as {@link Firestore.With.getDocs},
176
+ * {@link Firestore.With.streamDocs} and {@link Firestore.With.addDoc} take
177
+ * it.
178
+ *
179
+ * @see {@link Collection.doc} for referencing one document in it
180
+ */
181
+ collection(...ids: AncestorsOf<L>): CollectionReference<Collection<L>>;
182
+ /**
183
+ * References a document in this collection, given one id per ancestor
184
+ * followed by the document's own.
185
+ *
186
+ * **When to use**
187
+ *
188
+ * Use to address one document, as {@link Firestore.With.getDoc},
189
+ * {@link Firestore.With.setDoc} and {@link Firestore.With.updateDoc} take it.
190
+ *
191
+ * @see {@link Collection.collection} for referencing the collection itself
192
+ * @see {@link fromPath} for a reference from a path string
193
+ */
194
+ doc(...ids: [...AncestorsOf<L>, IdOf<L>]): DocumentReference<Collection<L>>;
195
+ }
196
+ /**
197
+ * Any collection, whatever it is nested under and whatever it holds. Use it as
198
+ * a type bound.
199
+ *
200
+ * **Details**
201
+ *
202
+ * It is `Collection<any>` rather than `Collection<Levels>` because `L` sits in
203
+ * an argument position in {@link Collection.doc}, which makes it invariant.
204
+ *
205
+ * @stability unstable
206
+ * @category models
207
+ * @since 0.1.0
208
+ */
209
+ export type Any = Collection<any>;
210
+ /**
211
+ * The id of a document in `C`, branded with `C`'s path.
212
+ *
213
+ * @see {@link IdSchema} for how to make one
214
+ *
215
+ * @stability unstable
216
+ * @category models
217
+ * @since 0.1.0
218
+ */
219
+ export type Id<C extends Any> = IdOf<C["~levels"]>;
220
+ /**
221
+ * The ids that address `C`: one per ancestor, from the root down. Empty for a
222
+ * root collection.
223
+ *
224
+ * @stability unstable
225
+ * @category models
226
+ * @since 0.1.0
227
+ */
228
+ export type Ancestors<C extends Any> = AncestorsOf<C["~levels"]>;
229
+ /**
230
+ * The model of the documents in `C`, as {@link make} or
231
+ * {@link Collection.subcollection} was given it.
232
+ *
233
+ * @stability unstable
234
+ * @category models
235
+ * @since 0.1.0
236
+ */
237
+ export type DocumentSchema<C extends Any> = Leaf<C["~levels"]>[1];
238
+ /**
239
+ * A reference to one collection, with the ids of its ancestors filled in.
240
+ *
241
+ * **Details**
242
+ *
243
+ * Build one with {@link Collection.collection}. Two references are
244
+ * `Equal` when they have the same path and come from the same definition.
245
+ *
246
+ * @see {@link Collection} for the definition it is built from
247
+ * @see {@link DocumentReference} for a reference to one document
248
+ *
249
+ * @stability unstable
250
+ * @category models
251
+ * @since 0.1.0
252
+ */
253
+ export interface CollectionReference<C extends Any> extends Inspectable.Inspectable, Equal.Equal {
254
+ readonly [CollectionReferenceTypeId]: typeof CollectionReferenceTypeId;
255
+ /** The definition this reference was built from. */
256
+ readonly collection: C;
257
+ /** The ids that address it, from the root down. */
258
+ readonly ancestors: Readonly<Ancestors<C>>;
259
+ /** The collection id Firestore knows it by: the last segment of its path. */
260
+ readonly id: Leaf<C["~levels"]>[0];
261
+ /** The full path, such as `users/alice/posts`. */
262
+ readonly path: string;
263
+ /**
264
+ * References a document in this collection, by its own id.
265
+ *
266
+ * @see {@link Collection.doc} for referencing it from the definition with every id
267
+ */
268
+ doc(id: Id<C>): DocumentReference<C>;
269
+ }
270
+ /**
271
+ * A typed reference to one document in a collection.
272
+ *
273
+ * **Details**
274
+ *
275
+ * It knows the {@link Collection} it was built from, so reads through it
276
+ * decode with that collection's model and writes encode with it. Build one
277
+ * with {@link Collection.doc}, {@link CollectionReference.doc} or
278
+ * {@link fromPath}. Two references are `Equal` when they have the same path and
279
+ * come from the same definition.
280
+ *
281
+ * @see {@link CollectionGroup.DocumentReference} for a reference into any collection of a group
282
+ * @see {@link DocumentPath.DocumentPath} for the untyped path a reference is stored as in a field
283
+ *
284
+ * @stability unstable
285
+ * @category models
286
+ * @since 0.1.0
287
+ */
288
+ export interface DocumentReference<C extends Any> extends Inspectable.Inspectable, Equal.Equal {
289
+ readonly [DocumentReferenceTypeId]: typeof DocumentReferenceTypeId;
290
+ /** The definition of the collection holding it. */
291
+ readonly collection: C;
292
+ /** The ids that address its collection, from the root down. */
293
+ readonly ancestors: Readonly<Ancestors<C>>;
294
+ /** The document's own id. */
295
+ readonly id: Id<C>;
296
+ /** The full path, such as `users/alice/posts/hello`. */
297
+ readonly path: string;
298
+ /** A reference to the collection holding it. */
299
+ readonly parent: CollectionReference<C>;
300
+ }
301
+ /**
302
+ * Checks whether a value is a collection definition.
303
+ *
304
+ * @see {@link isCollectionReference} for a reference to a collection
305
+ * @see {@link CollectionGroup.isCollectionGroup} for a Collection Group
306
+ *
307
+ * @stability unstable
308
+ * @category guards
309
+ * @since 0.1.0
310
+ */
311
+ export declare const isCollection: (u: unknown) => u is Any;
312
+ /**
313
+ * Checks whether a value is a {@link CollectionReference}.
314
+ *
315
+ * @see {@link isCollection} for a collection definition
316
+ * @see {@link isDocumentReference} for a reference to a document
317
+ *
318
+ * @stability unstable
319
+ * @category guards
320
+ * @since 0.1.0
321
+ */
322
+ export declare const isCollectionReference: (u: unknown) => u is CollectionReference<Any>;
323
+ /**
324
+ * Checks whether a value is a {@link DocumentReference} into any collection.
325
+ *
326
+ * @see {@link Collection.contains} for checking that a reference belongs to one collection, with narrowing
327
+ * @see {@link isCollectionReference} for a reference to a collection
328
+ * @see {@link DocumentPath.isDocumentPath} for the untyped path stored in a field
329
+ *
330
+ * @stability unstable
331
+ * @category guards
332
+ * @since 0.1.0
333
+ */
334
+ export declare const isDocumentReference: (u: unknown) => u is DocumentReference<Any>;
335
+ /**
336
+ * Defines a root collection and the model of its documents.
337
+ *
338
+ * **When to use**
339
+ *
340
+ * Use once per root collection, at module level, and build every reference to
341
+ * it from the result. Use {@link Collection.subcollection} on the result for a
342
+ * collection nested under its documents.
343
+ *
344
+ * **Details**
345
+ *
346
+ * The documents are described by a {@link FirestoreModel.Class} rather than a
347
+ * plain schema, since a document is written in other shapes than it is read
348
+ * in, and the model carries each of them. Pass a {@link FirestoreModel.Union}
349
+ * of classes for a collection that holds several document shapes.
350
+ *
351
+ * Throws when `segment` is not a collection id Firestore accepts: empty,
352
+ * containing `/`, `.` or `..`, matching `__.*__`, or longer than 1500 bytes. An
353
+ * invalid definition is a programming error, not a failure to recover from.
354
+ *
355
+ * @example Defining a collection with a subcollection
356
+ * ```ts
357
+ * import { Collection, Firestore, FirestoreModel } from "@visiolab/effect-firebase/firestore";
358
+ * import { Effect, Schema } from "effect";
359
+ *
360
+ * class User extends FirestoreModel.Class<User>("User")({ name: Schema.String }) {}
361
+ * class Post extends FirestoreModel.Class<Post>("Post")({ title: Schema.String }) {}
362
+ *
363
+ * const Users = Collection.make("users", User);
364
+ * const UserPosts = Users.subcollection("posts", Post);
365
+ *
366
+ * const program = Effect.gen(function* () {
367
+ * const firestore = yield* Firestore.Firestore;
368
+ * const alice = Users.id.make("alice");
369
+ *
370
+ * yield* firestore.setDoc(Users.doc(alice), { name: "Alice" });
371
+ * const post = yield* firestore.addDoc(UserPosts.collection(alice), { title: "Hello" });
372
+ * return post.path; // "users/alice/posts/<generated id>"
373
+ * });
374
+ * ```
375
+ *
376
+ * @see {@link fromPath} for a reference to a document of an existing collection from a path string
377
+ * @see {@link CollectionGroup.make} for reading several collections with one collection id together
378
+ *
379
+ * @stability unstable
380
+ * @category constructors
381
+ * @since 0.1.0
382
+ */
383
+ export declare const make: <const Segment extends string, S extends Any$1>(segment: Segment, schema: S) => Collection<readonly [readonly [Segment, S]]>;
384
+ /**
385
+ * References the document of `collection` at a path string, such as
386
+ * `users/alice/posts/hello`, or returns `None` when the path is not in that
387
+ * collection.
388
+ *
389
+ * **When to use**
390
+ *
391
+ * Use when a path arrives as a string, such as from a URL, a message or a
392
+ * stored {@link DocumentPath.DocumentPath}, and you know which collection it
393
+ * should be in.
394
+ *
395
+ * **Details**
396
+ *
397
+ * The path is checked against every segment the collection was defined with,
398
+ * so a path into another collection returns `None`, even one with the same
399
+ * last segment. Every id in the path must be non-empty.
400
+ *
401
+ * @example Parsing a path
402
+ * ```ts
403
+ * import { Collection, FirestoreModel } from "@visiolab/effect-firebase/firestore";
404
+ * import { Option, Schema } from "effect";
405
+ *
406
+ * class User extends FirestoreModel.Class<User>("User")({ name: Schema.String }) {}
407
+ * class Post extends FirestoreModel.Class<Post>("Post")({ title: Schema.String }) {}
408
+ *
409
+ * const Users = Collection.make("users", User);
410
+ * const UserPosts = Users.subcollection("posts", Post);
411
+ *
412
+ * Option.isSome(Collection.fromPath(UserPosts, "users/alice/posts/hello")); // true
413
+ * Option.isSome(Collection.fromPath(UserPosts, "orgs/acme/posts/hello")); // false
414
+ * ```
415
+ *
416
+ * @see {@link Collection.doc} for a reference built from typed ids
417
+ *
418
+ * @stability unstable
419
+ * @category constructors
420
+ * @since 0.2.0
421
+ */
422
+ export declare const fromPath: <C extends Any>(collection: C, path: string) => Option.Option<DocumentReference<C>>;
423
+ export { Collection_d_exports };