@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,213 @@
1
+ import { CallableRequest } from "./CallableRequest.mjs";
2
+ import { Any } from "./Callable.mjs";
3
+ import { Context, Effect, Schema } from "effect";
4
+ import { unhandled } from "effect/Types";
5
+ declare namespace CallableMiddleware_d_exports {
6
+ export { AnyId, AnyKey, ApplyServices, CallableMiddleware, Error, ErrorConstraint, ErrorSchema, Options, Provides, Requires, Service, ServiceClass };
7
+ }
8
+ declare const TypeId = "~@visiolab/effect-firebase/functions/CallableMiddleware";
9
+ /**
10
+ * The errors a middleware can fail with: one schema or an array.
11
+ *
12
+ * @stability unstable
13
+ * @category models
14
+ * @since 0.3.0
15
+ */
16
+ export type ErrorConstraint = Schema.Top | ReadonlyArray<Schema.Top>;
17
+ type ErrorSchemaFromConstraint<E> = E extends ReadonlyArray<Schema.Top> ? E[number] : E extends Schema.Top ? E : never;
18
+ /**
19
+ * What a middleware's implementation is told about the call it wraps.
20
+ *
21
+ * @stability unstable
22
+ * @category models
23
+ * @since 0.3.0
24
+ */
25
+ export interface Options {
26
+ /** The Callable being called. */
27
+ readonly callable: Any;
28
+ }
29
+ /**
30
+ * The implementation of a middleware: a function that wraps the rest of the
31
+ * call.
32
+ *
33
+ * **Details**
34
+ *
35
+ * `effect` is the rest of the call: the middleware inside this one, the
36
+ * Payload's decoding and the handler. It needs what this middleware
37
+ * `Provides`. The implementation may run it, fail instead, or catch what it
38
+ * fails with. It may require what middleware outside it provides, and always
39
+ * the {@link CallableRequest.CallableRequest}.
40
+ *
41
+ * A Payload that doesn't decode fails `effect` too. An implementation that
42
+ * catches every failure catches that one as well, and the caller then no
43
+ * longer gets `invalid-argument`. Catch only the errors you mean to.
44
+ *
45
+ * @stability unstable
46
+ * @category models
47
+ * @since 0.3.0
48
+ */
49
+ export type CallableMiddleware<Provides, E extends ErrorConstraint, Requires> = (effect: Effect.Effect<unknown, unhandled, Provides>, options: Options) => Effect.Effect<unknown, unhandled | ErrorSchemaFromConstraint<E>["Type"], Requires | CallableRequest>;
50
+ /**
51
+ * Any middleware, as the type of its service class's instances: what it
52
+ * provides, requires and fails with.
53
+ *
54
+ * @stability unstable
55
+ * @category models
56
+ * @since 0.3.0
57
+ */
58
+ export interface AnyId {
59
+ readonly [TypeId]: {
60
+ readonly provides: any;
61
+ readonly requires: any;
62
+ readonly error: ErrorConstraint;
63
+ };
64
+ }
65
+ /**
66
+ * Any middleware's service key, as `.middleware` takes it.
67
+ *
68
+ * @stability unstable
69
+ * @category models
70
+ * @since 0.3.0
71
+ */
72
+ export interface AnyKey extends Context.Key<any, any> {
73
+ readonly [TypeId]: typeof TypeId;
74
+ /** The schemas of the errors the middleware can fail with. */
75
+ readonly error: ReadonlySet<Schema.Top>;
76
+ }
77
+ /**
78
+ * The services a middleware provides to what it wraps.
79
+ *
80
+ * @stability unstable
81
+ * @category type-level
82
+ * @since 0.3.0
83
+ */
84
+ export type Provides<A> = A extends {
85
+ readonly [TypeId]: {
86
+ readonly provides: infer P;
87
+ };
88
+ } ? P : never;
89
+ /**
90
+ * The services a middleware requires from the middleware outside it.
91
+ *
92
+ * @stability unstable
93
+ * @category type-level
94
+ * @since 0.3.0
95
+ */
96
+ export type Requires<A> = A extends {
97
+ readonly [TypeId]: {
98
+ readonly requires: infer R;
99
+ };
100
+ } ? R : never;
101
+ /**
102
+ * The services still required after wrapping `R` in the middleware `A`: `A`'s
103
+ * `provides` are removed and its `requires` added.
104
+ *
105
+ * @stability unstable
106
+ * @category type-level
107
+ * @since 0.3.0
108
+ */
109
+ export type ApplyServices<A extends AnyId, R> = Exclude<R, Provides<A>> | Requires<A>;
110
+ /**
111
+ * The union of the error schemas of a middleware.
112
+ *
113
+ * @stability unstable
114
+ * @category type-level
115
+ * @since 0.3.0
116
+ */
117
+ export type ErrorSchema<A> = A extends {
118
+ readonly [TypeId]: {
119
+ readonly error: infer E;
120
+ };
121
+ } ? ErrorSchemaFromConstraint<E> : never;
122
+ /**
123
+ * The errors a middleware can fail with.
124
+ *
125
+ * @stability unstable
126
+ * @category type-level
127
+ * @since 0.3.0
128
+ */
129
+ export type Error<A> = ErrorSchema<A>["Type"];
130
+ /**
131
+ * The class {@link Service} returns: a service key whose instances carry the
132
+ * middleware's types.
133
+ *
134
+ * @stability unstable
135
+ * @category models
136
+ * @since 0.3.0
137
+ */
138
+ export type ServiceClass<Self, Id extends string, Config extends {
139
+ requires: any;
140
+ provides: any;
141
+ error: ErrorConstraint;
142
+ }> = Context.Service<Self, CallableMiddleware<Config["provides"], Config["error"], Config["requires"]>> & {
143
+ new (_: never): Context.ServiceClass.Shape<Id, CallableMiddleware<Config["provides"], Config["error"], Config["requires"]>> & {
144
+ readonly [TypeId]: {
145
+ readonly error: Config["error"];
146
+ readonly requires: Config["requires"];
147
+ readonly provides: Config["provides"];
148
+ };
149
+ };
150
+ readonly [TypeId]: typeof TypeId;
151
+ /** The schemas of the errors the middleware can fail with. */
152
+ readonly error: ReadonlySet<Schema.Top>;
153
+ };
154
+ /**
155
+ * Declares a Callable Middleware as a class.
156
+ *
157
+ * **When to use**
158
+ *
159
+ * Use to state a requirement of a Callable, such as "the caller is a member of
160
+ * a tenant", as part of its contract. For "the caller is signed in", use the
161
+ * built-in `Caller.Authenticated`.
162
+ *
163
+ * **Details**
164
+ *
165
+ * `provides` is what the middleware gives the handler: the handler's Layer no
166
+ * longer needs it. `requires` is what it needs from middleware outside it; a
167
+ * `requires` that nothing outside provides is left for the Layers where the
168
+ * chain runs. The {@link CallableRequest.CallableRequest} is always there and
169
+ * is never listed.
170
+ *
171
+ * `error` is one schema or an array. A middleware's errors join the error
172
+ * union of every Callable it is attached to. They are sent like the
173
+ * Callable's declared errors, and the client decodes them back.
174
+ *
175
+ * The middleware runs before the Payload is decoded, so a call it rejects
176
+ * learns nothing from the Payload's decoding. The decoding runs inside the
177
+ * chain, so an implementation that catches every failure also catches a
178
+ * Payload that doesn't decode.
179
+ *
180
+ * @example Declaring a middleware
181
+ * ```ts
182
+ * import { Context } from "effect";
183
+ * import { CallableError, CallableMiddleware } from "@visiolab/effect-firebase/functions";
184
+ *
185
+ * class Tenant extends Context.Service<Tenant, { readonly id: string }>()("Tenant") {}
186
+ *
187
+ * class WithTenant extends CallableMiddleware.Service<WithTenant, { provides: Tenant }>()(
188
+ * "WithTenant",
189
+ * { error: CallableError.PermissionDenied },
190
+ * ) {}
191
+ * ```
192
+ *
193
+ * @see {@link Callable.Callable.middleware} for attaching it to a Callable
194
+ * @see {@link Caller.Authenticated} for the built-in middleware
195
+ *
196
+ * @stability unstable
197
+ * @category constructors
198
+ * @since 0.3.0
199
+ */
200
+ export declare const Service: <Self, Config extends {
201
+ requires?: any;
202
+ provides?: any;
203
+ } = {
204
+ requires: never;
205
+ provides: never;
206
+ }>() => <const Id extends string, const Error extends ErrorConstraint = never>(id: Id, options?: {
207
+ readonly error?: Error | undefined;
208
+ }) => ServiceClass<Self, Id, {
209
+ requires: "requires" extends keyof Config ? Config["requires"] : never;
210
+ provides: "provides" extends keyof Config ? Config["provides"] : never;
211
+ error: Error;
212
+ }>;
213
+ export { CallableMiddleware_d_exports };
@@ -0,0 +1,52 @@
1
+ import { __exportAll } from "../_virtual/_rolldown/runtime.mjs";
2
+ import { Service as Service$1 } from "./internal/callableMiddleware.mjs";
3
+ // src/functions/CallableMiddleware.ts
4
+ var CallableMiddleware_exports = /* @__PURE__ */ __exportAll({ Service: () => Service });
5
+ /**
6
+ * Declares a Callable Middleware as a class.
7
+ *
8
+ * **When to use**
9
+ *
10
+ * Use to state a requirement of a Callable, such as "the caller is a member of
11
+ * a tenant", as part of its contract. For "the caller is signed in", use the
12
+ * built-in `Caller.Authenticated`.
13
+ *
14
+ * **Details**
15
+ *
16
+ * `provides` is what the middleware gives the handler: the handler's Layer no
17
+ * longer needs it. `requires` is what it needs from middleware outside it; a
18
+ * `requires` that nothing outside provides is left for the Layers where the
19
+ * chain runs. The {@link CallableRequest.CallableRequest} is always there and
20
+ * is never listed.
21
+ *
22
+ * `error` is one schema or an array. A middleware's errors join the error
23
+ * union of every Callable it is attached to. They are sent like the
24
+ * Callable's declared errors, and the client decodes them back.
25
+ *
26
+ * The middleware runs before the Payload is decoded, so a call it rejects
27
+ * learns nothing from the Payload's decoding. The decoding runs inside the
28
+ * chain, so an implementation that catches every failure also catches a
29
+ * Payload that doesn't decode.
30
+ *
31
+ * @example Declaring a middleware
32
+ * ```ts
33
+ * import { Context } from "effect";
34
+ * import { CallableError, CallableMiddleware } from "@visiolab/effect-firebase/functions";
35
+ *
36
+ * class Tenant extends Context.Service<Tenant, { readonly id: string }>()("Tenant") {}
37
+ *
38
+ * class WithTenant extends CallableMiddleware.Service<WithTenant, { provides: Tenant }>()(
39
+ * "WithTenant",
40
+ * { error: CallableError.PermissionDenied },
41
+ * ) {}
42
+ * ```
43
+ *
44
+ * @see {@link Callable.Callable.middleware} for attaching it to a Callable
45
+ * @see {@link Caller.Authenticated} for the built-in middleware
46
+ *
47
+ * @stability unstable
48
+ * @category constructors
49
+ * @since 0.3.0
50
+ */
51
+ const Service = () => (id, options) => Service$1(id, options);
52
+ export { CallableMiddleware_exports, Service };
@@ -0,0 +1,166 @@
1
+ import { Context } from "effect";
2
+ import * as HttpServerRequest from "effect/http/HttpServerRequest";
3
+ declare namespace CallableRequest_d_exports {
4
+ export { App, Auth, CallableRequest, Input };
5
+ }
6
+ /**
7
+ * Who made a call: the signed-in user's uid, the claims of their ID token and
8
+ * the raw ID token.
9
+ *
10
+ * @stability unstable
11
+ * @category models
12
+ * @since 0.3.0
13
+ */
14
+ export interface Auth {
15
+ /** The signed-in user's uid. */
16
+ readonly uid: string;
17
+ /** The decoded claims of the user's ID token. */
18
+ readonly token: Readonly<Record<string, unknown>>;
19
+ /** The ID token as the client sent it. */
20
+ readonly rawToken: string;
21
+ }
22
+ /**
23
+ * The app a call came from, as App Check attested it.
24
+ *
25
+ * @stability unstable
26
+ * @category models
27
+ * @since 0.3.0
28
+ */
29
+ export interface App {
30
+ /** The app ID of the attested Firebase app. */
31
+ readonly appId: string;
32
+ /** The decoded claims of the App Check token. */
33
+ readonly token: Readonly<Record<string, unknown>>;
34
+ /** Whether the App Check token was already used, when replay protection is on. */
35
+ readonly alreadyConsumed?: boolean | undefined;
36
+ }
37
+ /**
38
+ * The call a Callable is answering.
39
+ *
40
+ * **Details**
41
+ *
42
+ * `data` is the raw Payload, the `Schema.toCodecJson` output the client sent.
43
+ * Callable Middleware runs before the Payload is decoded, so it sees only
44
+ * `data`.
45
+ *
46
+ * `rawRequest` is the HTTP request the call came in, as Effect's
47
+ * `HttpServerRequest`. `Functions` builds it from Firebase's request,
48
+ * streaming its body without copying the bytes, and `Callable.handler` takes
49
+ * it from {@link Input.rawRequest}.
50
+ *
51
+ * @stability unstable
52
+ * @category models
53
+ * @since 0.3.0
54
+ */
55
+ export interface CallableRequest {
56
+ /** The signed-in caller, absent for a signed-out call. */
57
+ readonly auth?: Auth | undefined;
58
+ /** The app the call came from, absent without App Check. */
59
+ readonly app?: App | undefined;
60
+ /** An unverified Firebase Instance ID token, if the client sent one. */
61
+ readonly instanceIdToken?: string | undefined;
62
+ /** The raw Payload, before it is decoded. */
63
+ readonly data: unknown;
64
+ /**
65
+ * The HTTP request the call came in: its headers, method, URL, body and the
66
+ * caller's `remoteAddress`.
67
+ *
68
+ * **Details**
69
+ *
70
+ * The Firebase web SDK's `httpsCallable` can't send custom headers, so a
71
+ * header of your own comes only from callers that don't use it, such as
72
+ * another server. Headers the browser or the SDK sets, such as `user-agent`
73
+ * and `accept-language`, are there for every caller.
74
+ *
75
+ * `remoteAddress` is the caller's IP address as the platform reports it,
76
+ * `Option.none()` when it is unknown.
77
+ */
78
+ readonly rawRequest: HttpServerRequest.HttpServerRequest;
79
+ }
80
+ /**
81
+ * The service key of the {@link CallableRequest}.
82
+ *
83
+ * **Details**
84
+ *
85
+ * Every call provides it, so Callable Middleware may read it without listing
86
+ * it in `requires`.
87
+ *
88
+ * @stability unstable
89
+ * @category services
90
+ * @since 0.3.0
91
+ */
92
+ export declare const CallableRequest: Context.Service<CallableRequest, CallableRequest>;
93
+ /**
94
+ * What `Callable.handler` takes about a call: who makes it, from which app and
95
+ * over which HTTP request. `Callable.handler` fills `data` by encoding the
96
+ * Payload.
97
+ *
98
+ * **Details**
99
+ *
100
+ * Pass `{}` for a signed-out call and `{ auth: { uid, token } }` for a
101
+ * signed-in one. `rawToken` defaults to an empty string, since a call made in
102
+ * process has no real ID token.
103
+ *
104
+ * @stability unstable
105
+ * @category models
106
+ * @since 0.3.0
107
+ */
108
+ export interface Input {
109
+ /** The signed-in caller, absent for a signed-out call. */
110
+ readonly auth?: {
111
+ readonly uid: string;
112
+ readonly token: Readonly<Record<string, unknown>>;
113
+ readonly rawToken?: string | undefined;
114
+ } | undefined;
115
+ /** The app the call came from. */
116
+ readonly app?: App | undefined;
117
+ /** A Firebase Instance ID token. */
118
+ readonly instanceIdToken?: string | undefined;
119
+ /**
120
+ * The HTTP request the call comes in, for middleware that reads headers or
121
+ * the caller's address.
122
+ *
123
+ * **Details**
124
+ *
125
+ * Left out, it is a `POST` of the encoded Payload as JSON to
126
+ * `http://localhost/<deployed name>`, with `content-type:
127
+ * application/json`, no other headers and no `remoteAddress`. Build one with
128
+ * `HttpServerRequest.fromWeb` from `effect/http/HttpServerRequest`, and set
129
+ * `remoteAddress` with its `modify`.
130
+ *
131
+ * @example Calling with a request of your own
132
+ * ```ts
133
+ * import { Effect, Layer, Option } from "effect";
134
+ * import * as HttpServerRequest from "effect/http/HttpServerRequest";
135
+ * import { Callable, CallableMiddleware, CallableRequest } from "@visiolab/effect-firebase/functions";
136
+ *
137
+ * class LogLocale extends CallableMiddleware.Service<LogLocale>()("LogLocale") {}
138
+ *
139
+ * const Ping = Callable.make("ping").middleware(LogLocale);
140
+ *
141
+ * const program = Effect.gen(function* () {
142
+ * const ping = yield* Callable.handler(Ping);
143
+ * const rawRequest = HttpServerRequest.fromWeb(
144
+ * new Request("https://example.com/ping", {
145
+ * method: "POST",
146
+ * headers: { "accept-language": "de-CH" },
147
+ * }),
148
+ * ).modify({ remoteAddress: Option.some("203.0.113.7") });
149
+ * yield* ping(undefined, { rawRequest });
150
+ * }).pipe(
151
+ * Effect.provide(
152
+ * Layer.mergeAll(
153
+ * Callable.toLayer(Ping, () => Effect.void),
154
+ * Layer.succeed(LogLocale, (effect) =>
155
+ * Effect.flatMap(Effect.service(CallableRequest.CallableRequest), ({ rawRequest }) =>
156
+ * Effect.andThen(Effect.logInfo("Locale", rawRequest.headers["accept-language"]), effect),
157
+ * ),
158
+ * ),
159
+ * ),
160
+ * ),
161
+ * );
162
+ * ```
163
+ */
164
+ readonly rawRequest?: HttpServerRequest.HttpServerRequest | undefined;
165
+ }
166
+ export { CallableRequest_d_exports };
@@ -0,0 +1,18 @@
1
+ import { __exportAll } from "../_virtual/_rolldown/runtime.mjs";
2
+ import { CallableRequest as CallableRequest$1 } from "./internal/callableRequest.mjs";
3
+ // src/functions/CallableRequest.ts
4
+ var CallableRequest_exports = /* @__PURE__ */ __exportAll({ CallableRequest: () => CallableRequest });
5
+ /**
6
+ * The service key of the {@link CallableRequest}.
7
+ *
8
+ * **Details**
9
+ *
10
+ * Every call provides it, so Callable Middleware may read it without listing
11
+ * it in `requires`.
12
+ *
13
+ * @stability unstable
14
+ * @category services
15
+ * @since 0.3.0
16
+ */
17
+ const CallableRequest = CallableRequest$1;
18
+ export { CallableRequest, CallableRequest_exports };
@@ -0,0 +1,103 @@
1
+ import { Unauthenticated } from "./CallableError.mjs";
2
+ import { ServiceClass } from "./CallableMiddleware.mjs";
3
+ import { Context, Layer } from "effect";
4
+ declare namespace Caller_d_exports {
5
+ export { Authenticated, Caller };
6
+ }
7
+ /**
8
+ * The signed-in user making a call.
9
+ *
10
+ * **Details**
11
+ *
12
+ * A portable shape, not `firebase-admin`'s `DecodedIdToken`. There is no
13
+ * constructor: {@link Authenticated} provides it from the request, and a test
14
+ * provides a fake one from a stub middleware Layer.
15
+ *
16
+ * @stability unstable
17
+ * @category models
18
+ * @since 0.3.0
19
+ */
20
+ export interface Caller {
21
+ /** The user's uid. */
22
+ readonly uid: string;
23
+ /** The decoded claims of the user's ID token. */
24
+ readonly token: Readonly<Record<string, unknown>>;
25
+ /** The ID token as the client sent it. */
26
+ readonly rawToken: string;
27
+ }
28
+ /**
29
+ * The service key of the {@link Caller}.
30
+ *
31
+ * @stability unstable
32
+ * @category services
33
+ * @since 0.3.0
34
+ */
35
+ export declare const Caller: Context.Service<Caller, Caller>;
36
+ declare const Authenticated_base: ServiceClass<Authenticated, "@visiolab/effect-firebase/functions/Caller/Authenticated", {
37
+ requires: never;
38
+ provides: Caller;
39
+ error: typeof Unauthenticated;
40
+ }>;
41
+ /**
42
+ * The built-in middleware that requires a signed-in caller and provides the
43
+ * {@link Caller}.
44
+ *
45
+ * **When to use**
46
+ *
47
+ * Use on every Callable that only a signed-in user may call. Write a
48
+ * middleware of your own with {@link CallableMiddleware.Service} for other
49
+ * requirements, such as a custom claim.
50
+ *
51
+ * **Details**
52
+ *
53
+ * A call without auth fails with `CallableError.Unauthenticated`, before its
54
+ * Payload is decoded. Provide {@link Authenticated.layer} where the chain
55
+ * runs, or a stub Layer that provides a fake Caller in tests.
56
+ *
57
+ * @example Stubbing the Caller in process
58
+ * ```ts
59
+ * import { Effect, Layer, Schema } from "effect";
60
+ * import { Callable, Caller } from "@visiolab/effect-firebase/functions";
61
+ *
62
+ * const WhoAmI = Callable.make("whoAmI", { success: Schema.String }).middleware(
63
+ * Caller.Authenticated,
64
+ * );
65
+ *
66
+ * const WhoAmILive = Callable.toLayer(WhoAmI, () =>
67
+ * Effect.map(Effect.service(Caller.Caller), ({ uid }) => uid),
68
+ * );
69
+ *
70
+ * const AsAda = Layer.succeed(Caller.Authenticated, (effect) =>
71
+ * Effect.provideService(effect, Caller.Caller, { uid: "ada", token: {}, rawToken: "" }),
72
+ * );
73
+ *
74
+ * const program = Effect.gen(function* () {
75
+ * const whoAmI = yield* Callable.handler(WhoAmI);
76
+ * return yield* whoAmI(undefined, {});
77
+ * }).pipe(Effect.provide(Layer.merge(WhoAmILive, AsAda)));
78
+ * ```
79
+ *
80
+ * @see {@link Caller} for what it provides
81
+ * @see {@link CallableMiddleware.Service} for declaring a middleware of your own
82
+ *
83
+ * @stability unstable
84
+ * @category middleware
85
+ * @since 0.3.0
86
+ */
87
+ export declare class Authenticated extends Authenticated_base {
88
+ /**
89
+ * The implementation of {@link Authenticated}: provides the {@link Caller}
90
+ * from the request's auth, and fails with `CallableError.Unauthenticated`
91
+ * when there is none.
92
+ *
93
+ * **When to use**
94
+ *
95
+ * Use where the chain runs, in production and in process alike.
96
+ *
97
+ * @stability unstable
98
+ * @category layers
99
+ * @since 0.3.0
100
+ */
101
+ static readonly layer: Layer.Layer<Authenticated>;
102
+ }
103
+ export { Caller_d_exports };
@@ -0,0 +1,115 @@
1
+ import { __exportAll } from "../_virtual/_rolldown/runtime.mjs";
2
+ import { Unauthenticated } from "./CallableError.mjs";
3
+ import { Service } from "./CallableMiddleware.mjs";
4
+ import { CallableRequest } from "./CallableRequest.mjs";
5
+ import { Context, Effect, Layer } from "effect";
6
+ // src/functions/Caller.ts
7
+ /**
8
+ * The Caller: the signed-in user making a call, and the built-in
9
+ * `Authenticated` middleware that provides it.
10
+ *
11
+ * A Callable that requires a signed-in caller attaches {@link Authenticated}.
12
+ * Its handler then reads the {@link Caller} instead of the raw request, and a
13
+ * signed-out call fails with `CallableError.Unauthenticated` before its
14
+ * Payload is decoded.
15
+ *
16
+ * @example Reading the Caller in a handler
17
+ * ```ts
18
+ * import { Effect, Schema } from "effect";
19
+ * import { Callable, Caller } from "@visiolab/effect-firebase/functions";
20
+ *
21
+ * const WhoAmI = Callable.make("whoAmI", { success: Schema.String }).middleware(
22
+ * Caller.Authenticated,
23
+ * );
24
+ *
25
+ * const WhoAmILive = Callable.toLayer(WhoAmI, () =>
26
+ * Effect.map(Effect.service(Caller.Caller), ({ uid }) => uid),
27
+ * );
28
+ * ```
29
+ *
30
+ * @stability unstable
31
+ * @since 0.3.0
32
+ */
33
+ var Caller_exports = /* @__PURE__ */ __exportAll({
34
+ Authenticated: () => Authenticated,
35
+ Caller: () => Caller
36
+ });
37
+ /**
38
+ * The service key of the {@link Caller}.
39
+ *
40
+ * @stability unstable
41
+ * @category services
42
+ * @since 0.3.0
43
+ */
44
+ const Caller = Context.Service("@visiolab/effect-firebase/functions/Caller");
45
+ /**
46
+ * The built-in middleware that requires a signed-in caller and provides the
47
+ * {@link Caller}.
48
+ *
49
+ * **When to use**
50
+ *
51
+ * Use on every Callable that only a signed-in user may call. Write a
52
+ * middleware of your own with {@link CallableMiddleware.Service} for other
53
+ * requirements, such as a custom claim.
54
+ *
55
+ * **Details**
56
+ *
57
+ * A call without auth fails with `CallableError.Unauthenticated`, before its
58
+ * Payload is decoded. Provide {@link Authenticated.layer} where the chain
59
+ * runs, or a stub Layer that provides a fake Caller in tests.
60
+ *
61
+ * @example Stubbing the Caller in process
62
+ * ```ts
63
+ * import { Effect, Layer, Schema } from "effect";
64
+ * import { Callable, Caller } from "@visiolab/effect-firebase/functions";
65
+ *
66
+ * const WhoAmI = Callable.make("whoAmI", { success: Schema.String }).middleware(
67
+ * Caller.Authenticated,
68
+ * );
69
+ *
70
+ * const WhoAmILive = Callable.toLayer(WhoAmI, () =>
71
+ * Effect.map(Effect.service(Caller.Caller), ({ uid }) => uid),
72
+ * );
73
+ *
74
+ * const AsAda = Layer.succeed(Caller.Authenticated, (effect) =>
75
+ * Effect.provideService(effect, Caller.Caller, { uid: "ada", token: {}, rawToken: "" }),
76
+ * );
77
+ *
78
+ * const program = Effect.gen(function* () {
79
+ * const whoAmI = yield* Callable.handler(WhoAmI);
80
+ * return yield* whoAmI(undefined, {});
81
+ * }).pipe(Effect.provide(Layer.merge(WhoAmILive, AsAda)));
82
+ * ```
83
+ *
84
+ * @see {@link Caller} for what it provides
85
+ * @see {@link CallableMiddleware.Service} for declaring a middleware of your own
86
+ *
87
+ * @stability unstable
88
+ * @category middleware
89
+ * @since 0.3.0
90
+ */
91
+ var Authenticated = class extends Service()("@visiolab/effect-firebase/functions/Caller/Authenticated", { error: Unauthenticated }) {
92
+ /**
93
+ * The implementation of {@link Authenticated}: provides the {@link Caller}
94
+ * from the request's auth, and fails with `CallableError.Unauthenticated`
95
+ * when there is none.
96
+ *
97
+ * **When to use**
98
+ *
99
+ * Use where the chain runs, in production and in process alike.
100
+ *
101
+ * @stability unstable
102
+ * @category layers
103
+ * @since 0.3.0
104
+ */
105
+ static layer = Layer.succeed(this, (effect) => Effect.gen(function* () {
106
+ const { auth } = yield* Effect.service(CallableRequest);
107
+ if (auth === void 0) return yield* new Unauthenticated();
108
+ return yield* Effect.provideService(effect, Caller, {
109
+ uid: auth.uid,
110
+ token: auth.token,
111
+ rawToken: auth.rawToken
112
+ });
113
+ }));
114
+ };
115
+ export { Authenticated, Caller, Caller_exports };