@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.
- package/LICENSE +21 -0
- package/README.md +81 -2
- package/dist/_virtual/_rolldown/runtime.mjs +12 -0
- package/dist/app/App.d.mts +27 -0
- package/dist/app/App.mjs +27 -0
- package/dist/app/index.d.mts +2 -0
- package/dist/app/index.mjs +1 -0
- package/dist/firestore/Collection.d.mts +423 -0
- package/dist/firestore/Collection.mjs +133 -0
- package/dist/firestore/CollectionGroup.d.mts +164 -0
- package/dist/firestore/CollectionGroup.mjs +84 -0
- package/dist/firestore/DocumentPath.d.mts +95 -0
- package/dist/firestore/DocumentPath.mjs +71 -0
- package/dist/firestore/DocumentSnapshot.d.mts +239 -0
- package/dist/firestore/DocumentSnapshot.mjs +134 -0
- package/dist/firestore/FieldValue.d.mts +332 -0
- package/dist/firestore/FieldValue.mjs +256 -0
- package/dist/firestore/Firestore.d.mts +1165 -0
- package/dist/firestore/Firestore.mjs +274 -0
- package/dist/firestore/FirestoreModel.d.mts +1232 -0
- package/dist/firestore/FirestoreModel.mjs +586 -0
- package/dist/firestore/FirestoreSchema.d.mts +567 -0
- package/dist/firestore/FirestoreSchema.mjs +419 -0
- package/dist/firestore/FirestoreValue.d.mts +145 -0
- package/dist/firestore/FirestoreValue.mjs +87 -0
- package/dist/firestore/GeoPoint.d.mts +90 -0
- package/dist/firestore/GeoPoint.mjs +75 -0
- package/dist/firestore/Patch.d.mts +73 -0
- package/dist/firestore/Patch.mjs +57 -0
- package/dist/firestore/QuerySnapshot.d.mts +107 -0
- package/dist/firestore/QuerySnapshot.mjs +43 -0
- package/dist/firestore/Timestamp.d.mts +273 -0
- package/dist/firestore/Timestamp.mjs +255 -0
- package/dist/firestore/index.d.mts +14 -0
- package/dist/firestore/index.mjs +14 -0
- package/dist/firestore/internal/collection.mjs +156 -0
- package/dist/firestore/internal/collectionGroup.mjs +64 -0
- package/dist/firestore/internal/documentPath.d.mts +4 -0
- package/dist/firestore/internal/documentPath.mjs +42 -0
- package/dist/firestore/internal/documentSnapshot.mjs +63 -0
- package/dist/firestore/internal/fieldValue.d.mts +11 -0
- package/dist/firestore/internal/fieldValue.mjs +88 -0
- package/dist/firestore/internal/firestore.mjs +145 -0
- package/dist/firestore/internal/firestoreError.d.mts +29 -0
- package/dist/firestore/internal/firestoreError.mjs +30 -0
- package/dist/firestore/internal/firestoreModel.mjs +719 -0
- package/dist/firestore/internal/firestoreSchema.mjs +123 -0
- package/dist/firestore/internal/firestoreValue.mjs +108 -0
- package/dist/firestore/internal/firestoreValueWalk.d.mts +58 -0
- package/dist/firestore/internal/firestoreValueWalk.mjs +223 -0
- package/dist/firestore/internal/geoPoint.d.mts +4 -0
- package/dist/firestore/internal/geoPoint.mjs +39 -0
- package/dist/firestore/internal/patch.mjs +19 -0
- package/dist/firestore/internal/querySnapshot.mjs +24 -0
- package/dist/firestore/internal/schemaAST.mjs +35 -0
- package/dist/firestore/internal/snapshotExtra.mjs +35 -0
- package/dist/firestore/internal/streamFromListener.mjs +12 -0
- package/dist/firestore/internal/timestamp.d.mts +4 -0
- package/dist/firestore/internal/timestamp.mjs +66 -0
- package/dist/firestore/internal/timestampSchema.mjs +31 -0
- package/dist/firestore/internal/transactionFromCallback.mjs +66 -0
- package/dist/functions/Callable.d.mts +654 -0
- package/dist/functions/Callable.mjs +450 -0
- package/dist/functions/CallableError.d.mts +297 -0
- package/dist/functions/CallableError.mjs +256 -0
- package/dist/functions/CallableMiddleware.d.mts +213 -0
- package/dist/functions/CallableMiddleware.mjs +52 -0
- package/dist/functions/CallableRequest.d.mts +166 -0
- package/dist/functions/CallableRequest.mjs +18 -0
- package/dist/functions/Caller.d.mts +103 -0
- package/dist/functions/Caller.mjs +115 -0
- package/dist/functions/DocumentTrigger.d.mts +795 -0
- package/dist/functions/DocumentTrigger.mjs +566 -0
- package/dist/functions/FirebaseFunction.d.mts +79 -0
- package/dist/functions/FirebaseFunction.mjs +4 -0
- package/dist/functions/FunctionGroup.d.mts +175 -0
- package/dist/functions/FunctionGroup.mjs +64 -0
- package/dist/functions/index.d.mts +9 -0
- package/dist/functions/index.mjs +9 -0
- package/dist/functions/internal/callable.mjs +167 -0
- package/dist/functions/internal/callableMiddleware.d.mts +19 -0
- package/dist/functions/internal/callableMiddleware.mjs +15 -0
- package/dist/functions/internal/callableRequest.mjs +6 -0
- package/dist/functions/internal/documentTrigger.d.mts +10 -0
- package/dist/functions/internal/documentTrigger.mjs +73 -0
- package/dist/functions/internal/firebaseFunction.d.mts +5 -0
- package/dist/functions/internal/firebaseFunction.mjs +24 -0
- package/dist/functions/internal/functionGroup.mjs +36 -0
- package/package.json +66 -3
- package/src/app/App.ts +24 -0
- package/src/app/index.ts +7 -0
- package/src/firestore/Collection.ts +520 -0
- package/src/firestore/CollectionGroup.ts +245 -0
- package/src/firestore/DocumentPath.ts +114 -0
- package/src/firestore/DocumentSnapshot.ts +308 -0
- package/src/firestore/FieldValue.ts +375 -0
- package/src/firestore/Firestore.ts +1432 -0
- package/src/firestore/FirestoreModel.ts +1884 -0
- package/src/firestore/FirestoreSchema.ts +643 -0
- package/src/firestore/FirestoreValue.ts +207 -0
- package/src/firestore/GeoPoint.ts +105 -0
- package/src/firestore/Patch.ts +117 -0
- package/src/firestore/QuerySnapshot.ts +150 -0
- package/src/firestore/Timestamp.ts +302 -0
- package/src/firestore/index.ts +67 -0
- package/src/firestore/internal/collection.ts +246 -0
- package/src/firestore/internal/collectionGroup.ts +81 -0
- package/src/firestore/internal/documentPath.ts +53 -0
- package/src/firestore/internal/documentSnapshot.ts +117 -0
- package/src/firestore/internal/fieldValue.ts +119 -0
- package/src/firestore/internal/firestore.ts +322 -0
- package/src/firestore/internal/firestoreError.ts +36 -0
- package/src/firestore/internal/firestoreModel.ts +1242 -0
- package/src/firestore/internal/firestoreSchema.ts +218 -0
- package/src/firestore/internal/firestoreValue.ts +202 -0
- package/src/firestore/internal/firestoreValueWalk.ts +349 -0
- package/src/firestore/internal/geoPoint.ts +59 -0
- package/src/firestore/internal/patch.ts +21 -0
- package/src/firestore/internal/querySnapshot.ts +39 -0
- package/src/firestore/internal/schemaAST.ts +83 -0
- package/src/firestore/internal/snapshotExtra.ts +47 -0
- package/src/firestore/internal/streamFromListener.ts +27 -0
- package/src/firestore/internal/timestamp.ts +119 -0
- package/src/firestore/internal/timestampSchema.ts +42 -0
- package/src/firestore/internal/transactionFromCallback.ts +106 -0
- package/src/functions/Callable.ts +855 -0
- package/src/functions/CallableError.ts +348 -0
- package/src/functions/CallableMiddleware.ts +279 -0
- package/src/functions/CallableRequest.ts +207 -0
- package/src/functions/Caller.ts +141 -0
- package/src/functions/DocumentTrigger.ts +927 -0
- package/src/functions/FirebaseFunction.ts +96 -0
- package/src/functions/FunctionGroup.ts +225 -0
- package/src/functions/index.ts +62 -0
- package/src/functions/internal/callable.ts +272 -0
- package/src/functions/internal/callableMiddleware.ts +54 -0
- package/src/functions/internal/callableRequest.ts +8 -0
- package/src/functions/internal/documentTrigger.ts +143 -0
- package/src/functions/internal/firebaseFunction.ts +58 -0
- package/src/functions/internal/functionGroup.ts +47 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** @internal */
|
|
2
|
+
import { Context, type Effect, type Schema } from "effect";
|
|
3
|
+
|
|
4
|
+
/** @internal */
|
|
5
|
+
export const TypeId = "~@visiolab/effect-firebase/functions/CallableMiddleware";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A middleware's key as the chain reads it, with its types erased.
|
|
9
|
+
*
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
export interface Key extends Context.Key<never, Implementation> {
|
|
13
|
+
readonly [TypeId]: typeof TypeId;
|
|
14
|
+
readonly error: ReadonlySet<Schema.Top>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A middleware's implementation as the chain runs it.
|
|
19
|
+
*
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
export type Implementation = (
|
|
23
|
+
effect: Effect.Effect<unknown, unknown>,
|
|
24
|
+
options: { readonly callable: unknown },
|
|
25
|
+
) => Effect.Effect<unknown, unknown>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The middleware attached to a Callable, as a union, from its phantom
|
|
29
|
+
* `~Middleware` field.
|
|
30
|
+
*
|
|
31
|
+
* @internal
|
|
32
|
+
*/
|
|
33
|
+
export type Attached<X> = X extends { readonly "~Middleware": infer M } ? M : never;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* What the middleware attached to a Callable still requires, from its phantom
|
|
37
|
+
* `~MiddlewareServices` field.
|
|
38
|
+
*
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
export type AttachedServices<X> = X extends { readonly "~MiddlewareServices": infer R } ? R : never;
|
|
42
|
+
|
|
43
|
+
/** @internal */
|
|
44
|
+
export const Service = (
|
|
45
|
+
id: string,
|
|
46
|
+
options?: { readonly error?: Schema.Top | ReadonlyArray<Schema.Top> | undefined },
|
|
47
|
+
) => {
|
|
48
|
+
class Service extends Context.Service<Service, any>()(id) {}
|
|
49
|
+
const self = Service as any;
|
|
50
|
+
self[TypeId] = TypeId;
|
|
51
|
+
const error = options?.error;
|
|
52
|
+
self.error = new Set(error === undefined ? [] : Array.isArray(error) ? error : [error]);
|
|
53
|
+
return self;
|
|
54
|
+
};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/** @internal */
|
|
2
|
+
import { Context, Effect, Layer, Pipeable } from "effect";
|
|
3
|
+
import type * as Collection from "../../firestore/Collection.ts";
|
|
4
|
+
import type * as DocumentSnapshot from "../../firestore/DocumentSnapshot.ts";
|
|
5
|
+
import * as FirebaseFunction from "./firebaseFunction.ts";
|
|
6
|
+
|
|
7
|
+
/** @internal */
|
|
8
|
+
export const TypeId = "~@visiolab/effect-firebase/functions/DocumentTrigger";
|
|
9
|
+
|
|
10
|
+
/** @internal */
|
|
11
|
+
export const kind = "DocumentTrigger";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The changes to a document a trigger can listen to.
|
|
15
|
+
*
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export type EventKind = "created" | "deleted" | "updated" | "written";
|
|
19
|
+
|
|
20
|
+
/** @internal */
|
|
21
|
+
export interface Fields extends FirebaseFunction.Fields {
|
|
22
|
+
readonly kind: typeof kind;
|
|
23
|
+
readonly name: string;
|
|
24
|
+
readonly event: EventKind;
|
|
25
|
+
readonly collection: Collection.Any;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const Proto = {
|
|
29
|
+
[TypeId]: TypeId,
|
|
30
|
+
pipe() {
|
|
31
|
+
return Pipeable.pipeArguments(this, arguments);
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/** @internal */
|
|
36
|
+
export const make = (fields: Fields): Fields => Object.assign(Object.create(Proto), fields);
|
|
37
|
+
|
|
38
|
+
/** @internal */
|
|
39
|
+
export const isDocumentTrigger = (u: unknown): u is Fields =>
|
|
40
|
+
typeof u === "object" && u !== null && TypeId in u;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* A handler as it sits in the context: the services it was built with are
|
|
44
|
+
* already provided, so it needs only those of the event.
|
|
45
|
+
*
|
|
46
|
+
* @internal
|
|
47
|
+
*/
|
|
48
|
+
export type HandlerService = (event: unknown) => Effect.Effect<void, unknown>;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* What `toLayer` takes, with the types its signature has already checked
|
|
52
|
+
* erased.
|
|
53
|
+
*
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
export type HandlerInput = HandlerService | Effect.Effect<HandlerService>;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The key of the handler of the Document Trigger `name` in `group`, or in no
|
|
60
|
+
* group.
|
|
61
|
+
*
|
|
62
|
+
* @internal
|
|
63
|
+
*/
|
|
64
|
+
export const handlerKey = (group: string | undefined, name: string) =>
|
|
65
|
+
FirebaseFunction.handlerKey<HandlerService>(group, name);
|
|
66
|
+
|
|
67
|
+
/** @internal */
|
|
68
|
+
export const toLayer = (group: string | undefined, name: string, handler: HandlerInput) =>
|
|
69
|
+
Layer.effect(
|
|
70
|
+
handlerKey(group, name),
|
|
71
|
+
Effect.gen(function* () {
|
|
72
|
+
const run = Effect.isEffect(handler) ? yield* handler : handler;
|
|
73
|
+
// The services the Layer was built with, under those of the event.
|
|
74
|
+
const built = yield* Effect.context<never>();
|
|
75
|
+
return (event: unknown) =>
|
|
76
|
+
Effect.updateContext(run(event), (call: Context.Context<never>) =>
|
|
77
|
+
Context.merge(built, call),
|
|
78
|
+
);
|
|
79
|
+
}),
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
/** @internal */
|
|
83
|
+
export const serve = (group: FirebaseFunction.Group | undefined, trigger: Fields) =>
|
|
84
|
+
Effect.service(handlerKey(group?.identifier, trigger.name));
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* The path pattern of the documents of `collection`, with a wildcard of its
|
|
88
|
+
* own for each ancestor id and for the document id:
|
|
89
|
+
* `users/{id0}/posts/{id1}`. The wildcards are only ever read back through
|
|
90
|
+
* the event's document path, so their names are free.
|
|
91
|
+
*
|
|
92
|
+
* @internal
|
|
93
|
+
*/
|
|
94
|
+
export const documentPattern = (collection: Collection.Any): string =>
|
|
95
|
+
collection.path.map((segment, i) => `${segment}/{id${i}}`).join("/");
|
|
96
|
+
|
|
97
|
+
/** @internal */
|
|
98
|
+
export const deployment = (group: FirebaseFunction.Group | undefined, trigger: Fields) => ({
|
|
99
|
+
name: FirebaseFunction.deployedName(group, trigger),
|
|
100
|
+
document: documentPattern(trigger.collection),
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
/** @internal */
|
|
104
|
+
export const createdEvent = <C extends Collection.Any>(input: {
|
|
105
|
+
readonly id: string;
|
|
106
|
+
readonly time: string;
|
|
107
|
+
readonly snapshot: DocumentSnapshot.Existing<C>;
|
|
108
|
+
}) => ({
|
|
109
|
+
id: input.id,
|
|
110
|
+
time: input.time,
|
|
111
|
+
ref: input.snapshot.ref,
|
|
112
|
+
snapshot: input.snapshot,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* A `deleted` event has the shape of a `created` one, with the document as it
|
|
117
|
+
* was just before it was deleted.
|
|
118
|
+
*
|
|
119
|
+
* @internal
|
|
120
|
+
*/
|
|
121
|
+
export const deletedEvent = createdEvent;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* The event of a change with a document on each side. Both sides are at the
|
|
125
|
+
* same reference; `ref` is taken from `after`.
|
|
126
|
+
*
|
|
127
|
+
* @internal
|
|
128
|
+
*/
|
|
129
|
+
export const changeEvent = <
|
|
130
|
+
C extends Collection.Any,
|
|
131
|
+
S extends DocumentSnapshot.DocumentSnapshot<C>,
|
|
132
|
+
>(input: {
|
|
133
|
+
readonly id: string;
|
|
134
|
+
readonly time: string;
|
|
135
|
+
readonly before: S;
|
|
136
|
+
readonly after: S;
|
|
137
|
+
}) => ({
|
|
138
|
+
id: input.id,
|
|
139
|
+
time: input.time,
|
|
140
|
+
ref: input.after.ref,
|
|
141
|
+
before: input.before,
|
|
142
|
+
after: input.after,
|
|
143
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** @internal */
|
|
2
|
+
import { Context } from "effect";
|
|
3
|
+
|
|
4
|
+
/** @internal */
|
|
5
|
+
export const TypeId = "~@visiolab/effect-firebase/functions/FirebaseFunction";
|
|
6
|
+
|
|
7
|
+
/** @internal */
|
|
8
|
+
export const NoGroupTypeId = "~@visiolab/effect-firebase/functions/FirebaseFunction/NoGroup";
|
|
9
|
+
|
|
10
|
+
/** @internal */
|
|
11
|
+
export const HandlerTypeId = "~@visiolab/effect-firebase/functions/FirebaseFunction/Handler";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* What every kind of Function holds: its kind and its name.
|
|
15
|
+
*
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export interface Fields {
|
|
19
|
+
readonly kind: string;
|
|
20
|
+
readonly name: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The fields of a Function Group that a Function in it is served by.
|
|
25
|
+
*
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
export interface Group {
|
|
29
|
+
readonly identifier: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The key of the handler of the Function `name` in `group`, or in no group,
|
|
34
|
+
* whatever its kind. A kind decides what it holds.
|
|
35
|
+
*
|
|
36
|
+
* Context keys are compared by their string, so every call with the same group
|
|
37
|
+
* and name reaches the same service. Deployed names can't contain `/`, so the
|
|
38
|
+
* two forms can't collide. Names are unique within a group, and a Function in
|
|
39
|
+
* no group is deployed under its name, so two kinds never share a key they
|
|
40
|
+
* could both be served under.
|
|
41
|
+
*
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
export const handlerKey = <S>(group: string | undefined, name: string) =>
|
|
45
|
+
Context.Service<never, S>(
|
|
46
|
+
group === undefined
|
|
47
|
+
? `@visiolab/effect-firebase/functions/Handler/${name}`
|
|
48
|
+
: `@visiolab/effect-firebase/functions/Handler/${group}/${name}`,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The name `fn` is deployed under: its own in no group, or `<group>-<name>`
|
|
53
|
+
* in `group`.
|
|
54
|
+
*
|
|
55
|
+
* @internal
|
|
56
|
+
*/
|
|
57
|
+
export const deployedName = (group: Group | undefined, fn: Fields): string =>
|
|
58
|
+
group === undefined ? fn.name : `${group.identifier}-${fn.name}`;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** @internal */
|
|
2
|
+
import { Pipeable } from "effect";
|
|
3
|
+
import type * as FirebaseFunction from "./firebaseFunction.ts";
|
|
4
|
+
|
|
5
|
+
/** @internal */
|
|
6
|
+
export const TypeId = "~@visiolab/effect-firebase/functions/FunctionGroup";
|
|
7
|
+
|
|
8
|
+
/** @internal */
|
|
9
|
+
export interface Fields {
|
|
10
|
+
readonly identifier: string;
|
|
11
|
+
readonly functions: Readonly<Record<string, FirebaseFunction.Fields>>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** @internal */
|
|
15
|
+
export const isFunctionGroup = (u: unknown): u is Fields =>
|
|
16
|
+
(typeof u === "function" || (typeof u === "object" && u !== null)) && TypeId in u;
|
|
17
|
+
|
|
18
|
+
const Proto = {
|
|
19
|
+
[TypeId]: TypeId,
|
|
20
|
+
add(this: Fields, ...toAdd: ReadonlyArray<FirebaseFunction.Fields>) {
|
|
21
|
+
const functions = { ...this.functions };
|
|
22
|
+
for (const fn of toAdd) {
|
|
23
|
+
if (Object.hasOwn(functions, fn.name)) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
`The Function Group "${this.identifier}" already has a Function named "${fn.name}"`,
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
functions[fn.name] = fn;
|
|
29
|
+
}
|
|
30
|
+
return make({ identifier: this.identifier, functions });
|
|
31
|
+
},
|
|
32
|
+
pipe() {
|
|
33
|
+
return Pipeable.pipeArguments(this, arguments);
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* A function, so that a group can be the base of a class. Its `name` is the
|
|
39
|
+
* function's own, so the group's name is its `identifier`.
|
|
40
|
+
*
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
export const make = (fields: Fields) => {
|
|
44
|
+
function FunctionGroup() {}
|
|
45
|
+
Object.setPrototypeOf(FunctionGroup, Proto);
|
|
46
|
+
return Object.assign(FunctionGroup, fields);
|
|
47
|
+
};
|