effect-zero 0.1.0 → 0.2.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/README.md +138 -95
- package/dist/client-transaction.d.ts +22 -0
- package/dist/client-transaction.d.ts.map +1 -0
- package/dist/client-transaction.js +15 -0
- package/dist/client-transaction.js.map +1 -0
- package/dist/client.d.ts +10 -38
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +23 -50
- package/dist/client.js.map +1 -1
- package/dist/internal/server.d.ts +54 -0
- package/dist/internal/server.d.ts.map +1 -0
- package/dist/internal/server.js +64 -0
- package/dist/internal/server.js.map +1 -0
- package/dist/internal/utils.d.ts.map +1 -0
- package/dist/internal/utils.js.map +1 -0
- package/dist/mutators.d.ts +18 -23
- package/dist/mutators.d.ts.map +1 -1
- package/dist/mutators.js +9 -18
- package/dist/mutators.js.map +1 -1
- package/dist/query.d.ts +30 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +54 -0
- package/dist/query.js.map +1 -0
- package/dist/server-transaction.d.ts +42 -0
- package/dist/server-transaction.d.ts.map +1 -0
- package/dist/server-transaction.js +88 -0
- package/dist/server-transaction.js.map +1 -0
- package/dist/server.d.ts +111 -168
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +80 -201
- package/dist/server.js.map +1 -1
- package/dist/snapshot.d.ts.map +1 -1
- package/dist/snapshot.js +3 -1
- package/dist/snapshot.js.map +1 -1
- package/dist/types/common.d.ts +4 -0
- package/dist/types/common.d.ts.map +1 -0
- package/dist/types/common.js +4 -0
- package/dist/types/common.js.map +1 -0
- package/dist/{types.d.ts → types/push.d.ts} +15 -15
- package/dist/types/push.d.ts.map +1 -0
- package/dist/{types.js → types/push.js} +54 -54
- package/dist/types/push.js.map +1 -0
- package/dist/types/queries.d.ts +29 -0
- package/dist/types/queries.d.ts.map +1 -0
- package/dist/types/queries.js +42 -0
- package/dist/types/queries.js.map +1 -0
- package/package.json +46 -21
- package/src/client-transaction.ts +30 -0
- package/src/client.ts +66 -116
- package/src/internal/server.ts +90 -0
- package/src/mutators.ts +42 -44
- package/src/query.ts +117 -0
- package/src/server-transaction.ts +141 -0
- package/src/server.ts +174 -320
- package/src/snapshot.ts +0 -2
- package/src/types/common.ts +4 -0
- package/src/types/push.ts +197 -0
- package/src/types/queries.ts +56 -0
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js.map +0 -1
- package/src/types.ts +0 -201
- /package/dist/{utils.d.ts → internal/utils.d.ts} +0 -0
- /package/dist/{utils.js → internal/utils.js} +0 -0
- /package/src/{utils.ts → internal/utils.ts} +0 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import * as Context from "effect/Context";
|
|
2
|
+
import * as Data from "effect/Data";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Predicate from "effect/Predicate";
|
|
5
|
+
import * as SynchronizedRef from "effect/SynchronizedRef";
|
|
6
|
+
import { prefixId } from "./utils.js";
|
|
7
|
+
export class ServerTransactionInput extends Context.Tag(prefixId("ServerTransactionInput"))() {
|
|
8
|
+
}
|
|
9
|
+
export class ServerSynchronizationContext extends Effect.Service()(prefixId("ServerSynchronizationContext"), {
|
|
10
|
+
effect: Effect.gen(function* () {
|
|
11
|
+
return {
|
|
12
|
+
wasTransactionExecuted: yield* SynchronizedRef.make(false),
|
|
13
|
+
};
|
|
14
|
+
}),
|
|
15
|
+
}) {
|
|
16
|
+
// Ensures that only one transaction is executed at a time and checks that another transaction wasn't already executed.
|
|
17
|
+
static guard = (effect) => Effect.flatMap(this, (ctx) => SynchronizedRef.modifyEffect(ctx.wasTransactionExecuted, Effect.fn(function* (wasTransactionExecuted) {
|
|
18
|
+
if (wasTransactionExecuted) {
|
|
19
|
+
return yield* new MultipleTransactionsError();
|
|
20
|
+
}
|
|
21
|
+
const result = yield* effect;
|
|
22
|
+
return [result, true];
|
|
23
|
+
})));
|
|
24
|
+
static finalize = (effect) => Effect.gen(this, function* () {
|
|
25
|
+
const wasTransactionExecuted = yield* this.pipe(Effect.flatMap((ctx) => ctx.wasTransactionExecuted));
|
|
26
|
+
return yield* effect.pipe(
|
|
27
|
+
// Case #2 "One transaction then fail"
|
|
28
|
+
// If the transaction was executed successfully, swallow the error and just log it, otherwise re-throw it
|
|
29
|
+
Effect.catchAllCause((e) => {
|
|
30
|
+
if (wasTransactionExecuted) {
|
|
31
|
+
return Effect.logError("Error occurred after transaction execution completed", e);
|
|
32
|
+
}
|
|
33
|
+
return Effect.failCause(e);
|
|
34
|
+
}),
|
|
35
|
+
// Case #4 "Zero transactions then succeed"
|
|
36
|
+
// Check that the transaction was executed during the mutation
|
|
37
|
+
Effect.tap(!wasTransactionExecuted ? new NoTransactionError() : Effect.void));
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
export class NoTransactionError extends Data.TaggedError("NoTransactionError") {
|
|
41
|
+
}
|
|
42
|
+
export class MultipleTransactionsError extends Data.TaggedError("MultipleTransactionsError") {
|
|
43
|
+
}
|
|
44
|
+
const OutOfOrderMutationErrorTypeId = Symbol.for(prefixId("OutOfOrderMutationError"));
|
|
45
|
+
export class OutOfOrderMutationError extends Data.TaggedError("OutOfOrderMutationError") {
|
|
46
|
+
[OutOfOrderMutationErrorTypeId] = OutOfOrderMutationErrorTypeId;
|
|
47
|
+
get message() {
|
|
48
|
+
return `Client ${this.clientID} sent mutation ID ${this.receivedMutationID} but expected ${this.lastMutationID}`;
|
|
49
|
+
}
|
|
50
|
+
static is(e) {
|
|
51
|
+
return Predicate.hasProperty(e, OutOfOrderMutationErrorTypeId);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const MutationAlreadyProcessedErrorTypeId = Symbol.for(prefixId("MutationAlreadyProcessedError"));
|
|
55
|
+
export class MutationAlreadyProcessedError extends Data.TaggedError("MutationAlreadyProcessedError") {
|
|
56
|
+
[MutationAlreadyProcessedErrorTypeId] = MutationAlreadyProcessedErrorTypeId;
|
|
57
|
+
get message() {
|
|
58
|
+
return `Ignoring mutation from ${this.clientID} with ID ${this.received} as it was already processed. Expected: ${this.actual}`;
|
|
59
|
+
}
|
|
60
|
+
static is(e) {
|
|
61
|
+
return Predicate.hasProperty(e, MutationAlreadyProcessedErrorTypeId);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/internal/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/internal/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,MAAM,EAAE,MAAM,CAAC,uBAAmC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/internal/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAmB,IAAO,EAAE,EAAE,CAAC,eAAe,IAAI,EAAW,CAAC"}
|
package/dist/mutators.d.ts
CHANGED
|
@@ -1,35 +1,30 @@
|
|
|
1
1
|
import type * as Effect from "effect/Effect";
|
|
2
2
|
import * as Schema from "effect/Schema";
|
|
3
|
-
export type
|
|
4
|
-
export type
|
|
5
|
-
[K: string]:
|
|
6
|
-
[K: string]:
|
|
3
|
+
export type AnyMutatorFn<R = any, TArgs extends any[] = any[]> = (...args: TArgs) => Effect.Effect<any, any, R>;
|
|
4
|
+
export type AnyMutatorFns<R = any> = {
|
|
5
|
+
[K: string]: AnyMutatorFn<R> | {
|
|
6
|
+
[K: string]: AnyMutatorFn<R>;
|
|
7
7
|
};
|
|
8
8
|
};
|
|
9
|
-
export type
|
|
10
|
-
export type
|
|
11
|
-
export type
|
|
12
|
-
[K in keyof TSchema]: TSchema[K] extends
|
|
13
|
-
[K in keyof TSchema]:
|
|
9
|
+
export type AnyMutatorSchema = Schema.Schema<any, any, never>;
|
|
10
|
+
export type AnyMutatorSchemas = Record<string, AnyMutatorSchema | Record<string, AnyMutatorSchema>>;
|
|
11
|
+
export type MutatorFns<TSchema extends AnyMutatorSchemas> = {
|
|
12
|
+
[K in keyof TSchema]: TSchema[K] extends AnyMutatorSchema ? AnyMutatorFn<unknown, [Schema.Schema.Type<TSchema[K]>]> : TSchema[K] extends infer TSchema extends Record<string, AnyMutatorSchema> ? {
|
|
13
|
+
[K in keyof TSchema]: AnyMutatorFn<unknown, [Schema.Schema.Type<TSchema[K]>]>;
|
|
14
14
|
} : never;
|
|
15
15
|
};
|
|
16
|
-
export declare const
|
|
17
|
-
export type Mutator<TFunc extends
|
|
18
|
-
[
|
|
16
|
+
export declare const MutatorSchemaSymbol: unique symbol;
|
|
17
|
+
export type Mutator<TFunc extends AnyMutatorFn = AnyMutatorFn, TSchema extends AnyMutatorSchema = AnyMutatorSchema> = TFunc & {
|
|
18
|
+
[MutatorSchemaSymbol]: TSchema;
|
|
19
19
|
};
|
|
20
|
-
export type Mutators<TSchema extends
|
|
21
|
-
[K in keyof
|
|
22
|
-
[K in keyof
|
|
20
|
+
export type Mutators<TSchema extends AnyMutatorSchemas, TFns extends AnyMutatorFns> = {
|
|
21
|
+
[K in keyof TFns & keyof TSchema]: TFns[K] extends AnyMutatorFn ? TSchema[K] extends AnyMutatorSchema ? Mutator<TFns[K], TSchema[K]> : never : TSchema[K] extends infer TSchema extends Record<string, AnyMutatorSchema> ? TFns[K] extends infer TFns extends Record<string, AnyMutatorFn> ? {
|
|
22
|
+
[K in keyof TFns & keyof TSchema]: Mutator<TFns[K], TSchema[K]>;
|
|
23
23
|
} : never : never;
|
|
24
24
|
} & {};
|
|
25
25
|
export type AnyMutator<R = any, E = any> = Mutator<(...args: any[]) => Effect.Effect<any, E, R>>;
|
|
26
26
|
export type AnyMutators<R = any> = Record<string, AnyMutator<R> | Record<string, AnyMutator<R>>>;
|
|
27
|
-
export type ExtractMutatorsRequirements<
|
|
28
|
-
export declare
|
|
29
|
-
|
|
30
|
-
private constructor();
|
|
31
|
-
static make<T extends AnyMutatorSchema>(schema: T): MutatorSchema<T>;
|
|
32
|
-
private makeMutator;
|
|
33
|
-
makeMutators<TDefs extends MutatorDefs<T>>(mutators: TDefs): Mutators<T, TDefs>;
|
|
34
|
-
}
|
|
27
|
+
export type ExtractMutatorsRequirements<TMutators extends AnyMutators> = TMutators extends AnyMutators<infer R> ? R : never;
|
|
28
|
+
export declare const schema: <TSchema extends AnyMutatorSchemas>(schema: TSchema) => TSchema;
|
|
29
|
+
export declare function make<TSchema extends AnyMutatorSchemas, TFns extends MutatorFns<TSchema>>(schema: TSchema, mutators: TFns): Mutators<TSchema, TFns>;
|
|
35
30
|
//# sourceMappingURL=mutators.d.ts.map
|
package/dist/mutators.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mutators.d.ts","sourceRoot":"","sources":["../src/mutators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAC;AAK7C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAIxC,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"mutators.d.ts","sourceRoot":"","sources":["../src/mutators.ts"],"names":[],"mappings":"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"}
|
package/dist/mutators.js
CHANGED
|
@@ -3,24 +3,15 @@ import * as Option from "effect/Option";
|
|
|
3
3
|
import * as Predicate from "effect/Predicate";
|
|
4
4
|
import * as Rec from "effect/Record";
|
|
5
5
|
import * as Schema from "effect/Schema";
|
|
6
|
-
import { prefixId } from "./utils.js";
|
|
7
|
-
export const
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
static make(schema) {
|
|
14
|
-
return new MutatorSchema(schema);
|
|
15
|
-
}
|
|
16
|
-
// Associates mutator with its args schema
|
|
17
|
-
makeMutator(argsSchema, fn) {
|
|
18
|
-
return Object.assign(fn, { [MutatorArgsSchemaSym]: argsSchema });
|
|
19
|
-
}
|
|
20
|
-
makeMutators(mutators) {
|
|
21
|
-
return Rec.map(mutators, (v, name) => {
|
|
22
|
-
return Match.value([v, this.schema[name]]).pipe(Match.when([Predicate.isFunction, Schema.isSchema], ([mutator, schema]) => this.makeMutator(schema, mutator)), Match.when([Predicate.isRecord, Predicate.isRecord], ([mutator, schema]) => Rec.map(mutator, (mutator, name) => this.makeMutator(Option.getOrThrow(Rec.get(schema, name)), mutator))), Match.orElseAbsurd);
|
|
23
|
-
});
|
|
6
|
+
import { prefixId } from "./internal/utils.js";
|
|
7
|
+
export const MutatorSchemaSymbol = Symbol.for(prefixId("MutatorSchema"));
|
|
8
|
+
export const schema = (schema) => schema;
|
|
9
|
+
export function make(schema, mutators) {
|
|
10
|
+
function makeMutator(schema, fn) {
|
|
11
|
+
return Object.assign(fn, { [MutatorSchemaSymbol]: schema });
|
|
24
12
|
}
|
|
13
|
+
return Rec.map(mutators, (v, name) => {
|
|
14
|
+
return Match.value([v, schema[name]]).pipe(Match.when([Predicate.isFunction, Schema.isSchema], ([mutator, schema]) => makeMutator(schema, mutator)), Match.when([Predicate.isRecord, Predicate.isRecord], ([mutator, schema]) => Rec.map(mutator, (mutator, name) => makeMutator(Option.getOrThrow(Rec.get(schema, name)), mutator))), Match.orElseAbsurd);
|
|
15
|
+
});
|
|
25
16
|
}
|
|
26
17
|
//# sourceMappingURL=mutators.js.map
|
package/dist/mutators.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mutators.js","sourceRoot":"","sources":["../src/mutators.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,SAAS,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,GAAG,MAAM,eAAe,CAAC;AACrC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"mutators.js","sourceRoot":"","sources":["../src/mutators.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,SAAS,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,GAAG,MAAM,eAAe,CAAC;AACrC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAsB/C,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC;AA+BzE,MAAM,CAAC,MAAM,MAAM,GAAG,CAAoC,MAAe,EAAE,EAAE,CAAC,MAAM,CAAC;AAMrF,MAAM,UAAU,IAAI,CAAC,MAAyB,EAAE,QAAuB;IACrE,SAAS,WAAW,CAAC,MAAwB,EAAE,EAAgB;QAC7D,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE;QACnC,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CACxC,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACxG,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,QAAQ,EAAE,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,EAAE,CACzE,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CACpG,EACD,KAAK,CAAC,YAAY,CACnB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/query.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { HumanReadable, ReadonlyJSONValue, Zero, Query as ZeroQuery, Schema as ZeroSchema } from "@rocicorp/zero";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Equal from "effect/Equal";
|
|
4
|
+
import * as Schema from "effect/Schema";
|
|
5
|
+
import * as Subscribable from "effect/Subscribable";
|
|
6
|
+
export type Query<S extends ZeroSchema, T extends keyof S["tables"] & string, R> = ZeroQuery<S, T, R> & Equal.Equal;
|
|
7
|
+
type QueryArgs<A extends ReadonlyJSONValue[], B extends unknown[]> = {
|
|
8
|
+
_tag: "Encoded";
|
|
9
|
+
args: any extends A ? any : readonly [...A];
|
|
10
|
+
} | {
|
|
11
|
+
_tag: "Decoded";
|
|
12
|
+
args: any extends B ? any : readonly [...B];
|
|
13
|
+
};
|
|
14
|
+
export declare const RunQuerySymbol: unique symbol;
|
|
15
|
+
export declare const QueryNameSymbol: unique symbol;
|
|
16
|
+
export declare const make: <N extends string, A extends ReadonlyJSONValue[], B extends unknown[], S extends ZeroSchema, T extends keyof S["tables"] & string, R, E, R1, R2>(options: {
|
|
17
|
+
name: N;
|
|
18
|
+
payload: Schema.Schema<readonly [...B], readonly [...A], R1>;
|
|
19
|
+
query: (...args: NoInfer<B>) => Effect.Effect<ZeroQuery<S, T, R>, E, R2>;
|
|
20
|
+
}) => ((...args: B) => Effect.Effect<Query<S, T, R>, import("effect/ParseResult").ParseError | E, R1 | R2>) & {
|
|
21
|
+
[QueryNameSymbol]: N;
|
|
22
|
+
[RunQuerySymbol]: (args: QueryArgs<A, B>) => Effect.Effect<Query<S, T, R>, import("effect/ParseResult").ParseError | E, R1 | R2>;
|
|
23
|
+
};
|
|
24
|
+
export type MakeQueryResult<E = any, R1 = any, R2 = any> = ReturnType<typeof make<string, any, any, ZeroSchema, string, Record<string, any> | undefined, E, R1, R2>>;
|
|
25
|
+
export declare const subscribe: <S extends ZeroSchema, T extends keyof S["tables"] & string, R>(zero: Zero<S, undefined>, query: ZeroQuery<S, T, R> | Query<S, T, R>) => Effect.Effect<Subscribable.Subscribable<{
|
|
26
|
+
data: HumanReadable<R>;
|
|
27
|
+
status: "error" | "unknown" | "complete";
|
|
28
|
+
}, never, never>, never, import("effect/Scope").Scope>;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,IAAI,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEvH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,YAAY,MAAM,qBAAqB,CAAC;AAKpD,MAAM,MAAM,KAAK,CAAC,CAAC,SAAS,UAAU,EAAE,CAAC,SAAS,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;AAEpH,KAAK,SAAS,CACZ,CAAC,SAAS,iBAAiB,EAAE,EAC7B,CAAC,SAAS,OAAO,EAAE,IAEnB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,GAAG,SAAS,CAAC,GAAG,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAA;CAAE,GAEhE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,GAAG,SAAS,CAAC,GAAG,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAA;CAAE,CAAC;AAEnE,eAAO,MAAM,cAAc,eAAmC,CAAC;AAC/D,eAAO,MAAM,eAAe,eAAoC,CAAC;AAEjE,eAAO,MAAM,IAAI,GACf,CAAC,SAAS,MAAM,EAEhB,CAAC,SAAS,iBAAiB,EAAE,EAE7B,CAAC,SAAS,OAAO,EAAE,EACnB,CAAC,SAAS,UAAU,EACpB,CAAC,SAAS,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,MAAM,EACpC,CAAC,EACD,CAAC,EACD,EAAE,EACF,EAAE,EACF,SAAS;IACT,IAAI,EAAE,CAAC,CAAC;IACR,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC7D,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;CAC1E,gBA+BgC,CAAC;;;CAIjC,CAAC;AAGF,MAAM,MAAM,eAAe,CAAC,CAAC,GAAG,GAAG,EAAE,EAAE,GAAG,GAAG,EAAE,EAAE,GAAG,GAAG,IAAI,UAAU,CAEnE,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAC9F,CAAC;AAEF,eAAO,MAAM,SAAS,GAAwB,CAAC,SAAS,UAAU,EAAE,CAAC,SAAS,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE,CAAC;;;sDA+BzG,CAAC"}
|
package/dist/query.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Equal from "effect/Equal";
|
|
3
|
+
import * as Hash from "effect/Hash";
|
|
4
|
+
import * as Match from "effect/Match";
|
|
5
|
+
import * as Schema from "effect/Schema";
|
|
6
|
+
import * as Stream from "effect/Stream";
|
|
7
|
+
import * as Subscribable from "effect/Subscribable";
|
|
8
|
+
import * as SubscriptionRef from "effect/SubscriptionRef";
|
|
9
|
+
import { prefixId } from "./internal/utils.js";
|
|
10
|
+
import { deepClone, getDefaultSnapshot, getSnapshot } from "./snapshot.js";
|
|
11
|
+
export const RunQuerySymbol = Symbol.for(prefixId("RunQuery"));
|
|
12
|
+
export const QueryNameSymbol = Symbol.for(prefixId("QueryName"));
|
|
13
|
+
export const make = (options) => {
|
|
14
|
+
const runQuery = Effect.fn(function* (args) {
|
|
15
|
+
const { encoded, decoded } = yield* Match.valueTags(args, {
|
|
16
|
+
Encoded: ({ args: encoded }) => Effect.map(Schema.decode(options.payload)(encoded), (decoded) => ({ encoded, decoded })),
|
|
17
|
+
Decoded: ({ args: decoded }) => Effect.map(Schema.encode(options.payload)(decoded), (encoded) => ({ encoded, decoded })),
|
|
18
|
+
});
|
|
19
|
+
return yield* options.query(...decoded).pipe(Effect.map((rawQuery) => {
|
|
20
|
+
const query = rawQuery.nameAndArgs(options.name,
|
|
21
|
+
// We pass the encoded `args` to the `nameAndArgs` method, as that is the wire format which
|
|
22
|
+
// is sent to the server.
|
|
23
|
+
encoded);
|
|
24
|
+
query[Hash.symbol] = function () {
|
|
25
|
+
return Hash.hash(this.hash());
|
|
26
|
+
};
|
|
27
|
+
query[Equal.symbol] = function (that) {
|
|
28
|
+
if (Hash.isHash(that)) {
|
|
29
|
+
return Equal.equals(this[Hash.symbol](), that[Hash.symbol]());
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
};
|
|
33
|
+
return query;
|
|
34
|
+
}));
|
|
35
|
+
});
|
|
36
|
+
return Object.assign((...args) => runQuery({ _tag: "Decoded", args }), {
|
|
37
|
+
[QueryNameSymbol]: options.name,
|
|
38
|
+
[RunQuerySymbol]: runQuery,
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
export const subscribe = Effect.fn(function* (zero, query) {
|
|
42
|
+
const view = yield* Effect.acquireRelease(Effect.sync(() => zero.materialize(query)), (view) => Effect.sync(() => view.destroy()));
|
|
43
|
+
const subscriptionRef = yield* SubscriptionRef.make(getDefaultSnapshot(query.format.singular));
|
|
44
|
+
yield* Stream.asyncEffect((emit) => Effect.sync(() => view.addListener((...args) => emit.single(args)))).pipe(Stream.mapEffect(([data, resultType]) => Effect.sync(() => {
|
|
45
|
+
// logic here borrowed from: https://github.com/rocicorp/mono/blob/288b00ec94f5a9ae6e988513423af25c281dbb2a/packages/zero-react/src/use-query.tsx#L295
|
|
46
|
+
const cloned = (data === undefined ? data : deepClone(data));
|
|
47
|
+
return getSnapshot(query.format.singular, cloned, resultType);
|
|
48
|
+
})), Stream.runForEach((snapshot) => SubscriptionRef.set(subscriptionRef, snapshot)), Effect.forkScoped);
|
|
49
|
+
return subscriptionRef.pipe(Subscribable.map(([data, { type: status }]) => ({
|
|
50
|
+
data,
|
|
51
|
+
status,
|
|
52
|
+
})));
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Schema as ZeroSchema, ServerTransaction as ZeroServerTransaction, Transaction as ZeroTransaction } from "@rocicorp/zero";
|
|
2
|
+
import type { TransactionProviderHooks, ZQLDatabase } from "@rocicorp/zero/server";
|
|
3
|
+
import * as Cause from "effect/Cause";
|
|
4
|
+
import * as Context from "effect/Context";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import type * as ClientTransaction from "./client-transaction.js";
|
|
7
|
+
import { MutationAlreadyProcessedError, OutOfOrderMutationError, ServerSynchronizationContext, ServerTransactionInput } from "./internal/server.js";
|
|
8
|
+
export interface ServerTransactionContext {
|
|
9
|
+
readonly _tag: unique symbol;
|
|
10
|
+
}
|
|
11
|
+
export declare const make: <const Id extends string, TSchema extends ZeroSchema, TTransaction>(id: Id, database: ZQLDatabase<TSchema, TTransaction>, clientTransaction: Context.TagClass<ClientTransaction.ClientTransaction, string, ZeroTransaction<TSchema>>) => Context.TagClass<ServerTransactionContext, `${Id}/ServerTransactionContext`, {
|
|
12
|
+
transaction: ZeroServerTransaction<TSchema, TTransaction>;
|
|
13
|
+
transactionHooks: TransactionProviderHooks;
|
|
14
|
+
}> & {
|
|
15
|
+
use: <A>(fn: (transaction: ZeroServerTransaction<TSchema, TTransaction>, options: {
|
|
16
|
+
readonly signal: AbortSignal;
|
|
17
|
+
}) => PromiseLike<A>) => Effect.Effect<A, ServerTransactionError, ServerTransactionContext>;
|
|
18
|
+
execute: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, import("./internal/server.js").MultipleTransactionsError | OutOfOrderMutationError | MutationAlreadyProcessedError | UpdateClientMutationIdError | ZeroDatabaseError | E, ServerTransactionInput | ServerSynchronizationContext | Exclude<R, ClientTransaction.ClientTransaction | ServerTransactionContext>>;
|
|
19
|
+
};
|
|
20
|
+
declare const ServerTransactionError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => Cause.YieldableError & {
|
|
21
|
+
readonly _tag: "ServerTransactionError";
|
|
22
|
+
} & Readonly<A>;
|
|
23
|
+
declare class ServerTransactionError extends ServerTransactionError_base<{
|
|
24
|
+
readonly cause: Cause.Cause<unknown>;
|
|
25
|
+
}> {
|
|
26
|
+
}
|
|
27
|
+
declare const UpdateClientMutationIdError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => Cause.YieldableError & {
|
|
28
|
+
readonly _tag: "UpdateClientMutationIdError";
|
|
29
|
+
} & Readonly<A>;
|
|
30
|
+
declare class UpdateClientMutationIdError extends UpdateClientMutationIdError_base<{
|
|
31
|
+
readonly cause: Cause.Cause<unknown>;
|
|
32
|
+
}> {
|
|
33
|
+
}
|
|
34
|
+
declare const ZeroDatabaseError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => Cause.YieldableError & {
|
|
35
|
+
readonly _tag: "ZeroDatabaseError";
|
|
36
|
+
} & Readonly<A>;
|
|
37
|
+
declare class ZeroDatabaseError extends ZeroDatabaseError_base<{
|
|
38
|
+
readonly cause: Cause.Cause<unknown>;
|
|
39
|
+
}> {
|
|
40
|
+
}
|
|
41
|
+
export {};
|
|
42
|
+
//# sourceMappingURL=server-transaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-transaction.d.ts","sourceRoot":"","sources":["../src/server-transaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,IAAI,UAAU,EACpB,iBAAiB,IAAI,qBAAqB,EAC1C,WAAW,IAAI,eAAe,EAC/B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,wBAAwB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAG1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAKxC,OAAO,KAAK,KAAK,iBAAiB,MAAM,yBAAyB,CAAC;AAClE,OAAO,EACL,6BAA6B,EAC7B,uBAAuB,EACvB,4BAA4B,EAC5B,sBAAsB,EACvB,MAAM,sBAAsB,CAAC;AAK9B,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,OAAO,MAAM,CAAC;CAC9B;AAED,eAAO,MAAM,IAAI,GAAI,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,OAAO,SAAS,UAAU,EAAE,YAAY,EACpF,IAAI,EAAE,EACN,UAAU,WAAW,CAAC,OAAO,EAAE,YAAY,CAAC,EAC5C,mBAAmB,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;iBAIzF,qBAAqB,CAAC,OAAO,EAAE,YAAY,CAAC;sBAAoB,wBAAwB;;UAG5F,CAAC,MACR,CACF,WAAW,EAAE,qBAAqB,CAAC,OAAO,EAAE,YAAY,CAAC,EACzD,OAAO,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;KAAE,KACtC,WAAW,CAAC,CAAC,CAAC;cASgB,CAAC,EAAE,CAAC,EAAE,CAAC;CAoE7C,CAAC;;;;AAEF,cAAM,sBAAuB,SAAQ,4BAA2C;IAC9E,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;CACtC,CAAC;CAAG;;;;AAEL,cAAM,2BAA4B,SAAQ,iCAAgD;IACxF,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;CACtC,CAAC;CAAG;;;;AACL,cAAM,iBAAkB,SAAQ,uBAAsC;IACpE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;CACtC,CAAC;CAAG"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as Cause from "effect/Cause";
|
|
2
|
+
import * as Context from "effect/Context";
|
|
3
|
+
import * as Data from "effect/Data";
|
|
4
|
+
import * as Deferred from "effect/Deferred";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Exit from "effect/Exit";
|
|
7
|
+
import * as Layer from "effect/Layer";
|
|
8
|
+
import * as Predicate from "effect/Predicate";
|
|
9
|
+
import * as Runtime from "effect/Runtime";
|
|
10
|
+
import { MutationAlreadyProcessedError, OutOfOrderMutationError, ServerSynchronizationContext, ServerTransactionInput, } from "./internal/server.js";
|
|
11
|
+
import { prefixId } from "./internal/utils.js";
|
|
12
|
+
export const make = (id, database, clientTransaction) => {
|
|
13
|
+
const ServerTransactionContext = Context.Tag(`${id}/ServerTransactionContext`)();
|
|
14
|
+
const use = (fn) => Effect.flatMap(ServerTransactionContext, (ctx) => Effect.tryPromise({
|
|
15
|
+
try: (signal) => fn(ctx.transaction, { signal }),
|
|
16
|
+
catch: (error) => new ServerTransactionError({ cause: Cause.fail(error) }),
|
|
17
|
+
}));
|
|
18
|
+
const execute = Effect.fn(function* (effect) {
|
|
19
|
+
const runtime = yield* Effect.runtime();
|
|
20
|
+
const result = yield* Deferred.make();
|
|
21
|
+
const transactionInput = yield* ServerTransactionInput;
|
|
22
|
+
yield* Effect.tryPromise({
|
|
23
|
+
try: (signal) => database.transaction(async (transaction, transactionHooks) => {
|
|
24
|
+
const exit = await Effect.zipRight(checkAndIncrementLastMutationId, effect).pipe(Effect.provide([
|
|
25
|
+
Layer.succeed(ServerTransactionContext, { transaction, transactionHooks }),
|
|
26
|
+
Layer.succeed(clientTransaction, transaction),
|
|
27
|
+
]), (effect) => Runtime.runPromiseExit(runtime, effect, { signal }));
|
|
28
|
+
Deferred.unsafeDone(result, exit);
|
|
29
|
+
return Exit.getOrElse(exit, () => {
|
|
30
|
+
// This error's purpose is to differentiate between "external" errors
|
|
31
|
+
// that originate from the user-defined mutator code and "internal" errors
|
|
32
|
+
// that originate from our own code and the Zero API.
|
|
33
|
+
// Both types are caught in the "catch" block below, but at this point we only need to handle
|
|
34
|
+
// the "internal" errors wrapping them in a `ZeroDatabaseError`, because "external" errors
|
|
35
|
+
// are already covered by passing the Exit result to the Deferred, which is why
|
|
36
|
+
// we have the ServerTransactionUserError silenced below in the pipe.
|
|
37
|
+
throw new ServerTransactionUserError();
|
|
38
|
+
});
|
|
39
|
+
}, transactionInput),
|
|
40
|
+
catch: (error) => {
|
|
41
|
+
if (ServerTransactionUserError.is(error)) {
|
|
42
|
+
return error;
|
|
43
|
+
}
|
|
44
|
+
// This is for errors that occur when calling `database.transaction` despite the provided `effect` succeeding.
|
|
45
|
+
// This can be caused by e.g. the database connection timing out or other database-related issues.
|
|
46
|
+
return new ZeroDatabaseError({ cause: Cause.fail(error) });
|
|
47
|
+
},
|
|
48
|
+
}).pipe(Effect.catchTag("ServerTransactionUserError", () => Effect.void));
|
|
49
|
+
return yield* result;
|
|
50
|
+
}, ServerSynchronizationContext.guard);
|
|
51
|
+
const checkAndIncrementLastMutationId = Effect.gen(function* () {
|
|
52
|
+
const { transactionHooks } = yield* ServerTransactionContext;
|
|
53
|
+
const { clientID, mutationID: receivedMutationID } = yield* ServerTransactionInput;
|
|
54
|
+
const { lastMutationID } = yield* Effect.tryPromise({
|
|
55
|
+
try: () => transactionHooks.updateClientMutationID(),
|
|
56
|
+
catch: (error) => new UpdateClientMutationIdError({ cause: Cause.fail(error) }),
|
|
57
|
+
});
|
|
58
|
+
if (receivedMutationID < lastMutationID) {
|
|
59
|
+
return yield* new MutationAlreadyProcessedError({
|
|
60
|
+
clientID,
|
|
61
|
+
received: receivedMutationID,
|
|
62
|
+
actual: lastMutationID,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
if (receivedMutationID > lastMutationID) {
|
|
66
|
+
return yield* new OutOfOrderMutationError({
|
|
67
|
+
clientID,
|
|
68
|
+
receivedMutationID,
|
|
69
|
+
lastMutationID,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
return Object.assign(ServerTransactionContext, { use, execute });
|
|
74
|
+
};
|
|
75
|
+
class ServerTransactionError extends Data.TaggedError("ServerTransactionError") {
|
|
76
|
+
}
|
|
77
|
+
class UpdateClientMutationIdError extends Data.TaggedError("UpdateClientMutationIdError") {
|
|
78
|
+
}
|
|
79
|
+
class ZeroDatabaseError extends Data.TaggedError("ZeroDatabaseError") {
|
|
80
|
+
}
|
|
81
|
+
const ServerTransactionUserErrorTypeId = Symbol.for(prefixId("ServerTransactionUserError"));
|
|
82
|
+
class ServerTransactionUserError extends Data.TaggedError("ServerTransactionUserError") {
|
|
83
|
+
[ServerTransactionUserErrorTypeId] = ServerTransactionUserErrorTypeId;
|
|
84
|
+
static is(e) {
|
|
85
|
+
return Predicate.hasProperty(e, ServerTransactionUserErrorTypeId);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=server-transaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-transaction.js","sourceRoot":"","sources":["../src/server-transaction.ts"],"names":[],"mappings":"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"}
|