@confect/core 1.0.0-next.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 (67) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +7 -0
  3. package/dist/FunctionSpec.d.ts +95 -0
  4. package/dist/FunctionSpec.d.ts.map +1 -0
  5. package/dist/FunctionSpec.js +38 -0
  6. package/dist/FunctionSpec.js.map +1 -0
  7. package/dist/GenericId.d.ts +13 -0
  8. package/dist/GenericId.d.ts.map +1 -0
  9. package/dist/GenericId.js +15 -0
  10. package/dist/GenericId.js.map +1 -0
  11. package/dist/GroupPath.d.ts +33 -0
  12. package/dist/GroupPath.d.ts.map +1 -0
  13. package/dist/GroupPath.js +6 -0
  14. package/dist/GroupPath.js.map +1 -0
  15. package/dist/GroupSpec.d.ts +32 -0
  16. package/dist/GroupSpec.d.ts.map +1 -0
  17. package/dist/GroupSpec.js +49 -0
  18. package/dist/GroupSpec.js.map +1 -0
  19. package/dist/PaginationResult.d.ts +20 -0
  20. package/dist/PaginationResult.d.ts.map +1 -0
  21. package/dist/PaginationResult.js +16 -0
  22. package/dist/PaginationResult.js.map +1 -0
  23. package/dist/Ref.d.ts +40 -0
  24. package/dist/Ref.d.ts.map +1 -0
  25. package/dist/Ref.js +20 -0
  26. package/dist/Ref.js.map +1 -0
  27. package/dist/Refs.d.ts +22 -0
  28. package/dist/Refs.d.ts.map +1 -0
  29. package/dist/Refs.js +24 -0
  30. package/dist/Refs.js.map +1 -0
  31. package/dist/Spec.d.ts +23 -0
  32. package/dist/Spec.d.ts.map +1 -0
  33. package/dist/Spec.js +23 -0
  34. package/dist/Spec.js.map +1 -0
  35. package/dist/SystemFields.d.ts +28 -0
  36. package/dist/SystemFields.d.ts.map +1 -0
  37. package/dist/SystemFields.js +24 -0
  38. package/dist/SystemFields.js.map +1 -0
  39. package/dist/Types.d.ts +35 -0
  40. package/dist/Types.d.ts.map +1 -0
  41. package/dist/Types.js +6 -0
  42. package/dist/Types.js.map +1 -0
  43. package/dist/UserIdentity.d.ts +65 -0
  44. package/dist/UserIdentity.d.ts.map +1 -0
  45. package/dist/UserIdentity.js +32 -0
  46. package/dist/UserIdentity.js.map +1 -0
  47. package/dist/_virtual/rolldown_runtime.js +13 -0
  48. package/dist/index.d.ts +12 -0
  49. package/dist/index.js +13 -0
  50. package/dist/internal/utils.d.ts +5 -0
  51. package/dist/internal/utils.d.ts.map +1 -0
  52. package/dist/internal/utils.js +68 -0
  53. package/dist/internal/utils.js.map +1 -0
  54. package/package.json +73 -0
  55. package/src/FunctionSpec.ts +153 -0
  56. package/src/GenericId.ts +18 -0
  57. package/src/GroupPath.ts +61 -0
  58. package/src/GroupSpec.ts +120 -0
  59. package/src/PaginationResult.ts +21 -0
  60. package/src/Ref.ts +175 -0
  61. package/src/Refs.ts +99 -0
  62. package/src/Spec.ts +52 -0
  63. package/src/SystemFields.ts +51 -0
  64. package/src/Types.ts +166 -0
  65. package/src/UserIdentity.ts +28 -0
  66. package/src/index.ts +11 -0
  67. package/src/internal/utils.ts +86 -0
@@ -0,0 +1,61 @@
1
+ import type { Record } from "effect";
2
+ import type * as GroupSpec from "./GroupSpec";
3
+
4
+ /**
5
+ * Recursively generates paths for a group and its nested groups.
6
+ *
7
+ * - For a group with no subgroups, returns just the group name.
8
+ * - For a group with subgroups, returns the group name plus all possible paths through its direct subgroups.
9
+ */
10
+ export type All<
11
+ Group extends GroupSpec.AnyWithProps,
12
+ Depth extends 1[] = [],
13
+ > = Depth["length"] extends 15
14
+ ? string
15
+ : Group extends any
16
+ ? [GroupSpec.Groups<Group>] extends [never]
17
+ ? GroupSpec.Name<Group>
18
+ : GroupSpec.Name<Group> | AllHelper<Group, GroupSpec.Groups<Group>, Depth>
19
+ : never;
20
+
21
+ type AllHelper<
22
+ Parent extends GroupSpec.AnyWithProps,
23
+ Groups_ extends GroupSpec.AnyWithProps,
24
+ Depth extends 1[] = [],
25
+ > = Groups_ extends GroupSpec.AnyWithProps
26
+ ? `${GroupSpec.Name<Parent>}.${All<Groups_, [...Depth, 1]>}`
27
+ : never;
28
+
29
+ /**
30
+ * Recursively extracts the group at the given dot-separated path.
31
+ * Path must match the format defined in `Path` above, e.g. "group" or "group.subgroup".
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * type G = WithPath<RootGroup, "group.subgroup">;
36
+ * ```
37
+ */
38
+ export type GroupAt<
39
+ Group,
40
+ Path extends string,
41
+ > = Group extends GroupSpec.AnyWithProps
42
+ ? Path extends `${infer Head}.${infer Tail}`
43
+ ? Group extends { readonly name: Head }
44
+ ? Group extends {
45
+ readonly groups: Record.ReadonlyRecord<string, infer SubGroup>;
46
+ }
47
+ ? GroupAt<SubGroup, Tail>
48
+ : never
49
+ : never
50
+ : GroupSpec.WithName<Group, Path>
51
+ : never;
52
+
53
+ export type SubGroupsAt<
54
+ Group extends GroupSpec.AnyWithProps,
55
+ GroupPath extends string,
56
+ > =
57
+ GroupSpec.Groups<GroupAt<Group, GroupPath>> extends infer SubGroups
58
+ ? SubGroups extends GroupSpec.AnyWithProps
59
+ ? `${GroupPath}.${GroupSpec.Name<SubGroups>}`
60
+ : never
61
+ : never;
@@ -0,0 +1,120 @@
1
+ import { Predicate, Record } from "effect";
2
+ import type * as FunctionSpec from "./FunctionSpec";
3
+ import { validateConfectFunctionIdentifier } from "./internal/utils";
4
+
5
+ export const TypeId = "@confect/core/api/GroupSpec";
6
+ export type TypeId = typeof TypeId;
7
+
8
+ export const isGroupSpec = (u: unknown): u is Any =>
9
+ Predicate.hasProperty(u, TypeId);
10
+
11
+ export interface GroupSpec<
12
+ Name_ extends string,
13
+ Functions_ extends FunctionSpec.AnyWithProps = never,
14
+ Groups_ extends AnyWithProps = never,
15
+ > {
16
+ readonly [TypeId]: TypeId;
17
+ readonly name: Name_;
18
+ readonly functions: {
19
+ [FunctionName in FunctionSpec.Name<Functions_>]: FunctionSpec.WithName<
20
+ Functions_,
21
+ FunctionName
22
+ >;
23
+ };
24
+ readonly groups: {
25
+ [GroupName in Name<Groups_>]: WithName<Groups_, GroupName>;
26
+ };
27
+
28
+ addFunction<Function extends FunctionSpec.AnyWithProps>(
29
+ function_: Function,
30
+ ): GroupSpec<Name_, Functions_ | Function, Groups_>;
31
+
32
+ addGroup<Group extends AnyWithProps>(
33
+ group: Group,
34
+ ): GroupSpec<Name_, Functions_, Groups_ | Group>;
35
+ }
36
+
37
+ export interface Any {
38
+ readonly [TypeId]: TypeId;
39
+ }
40
+
41
+ export interface AnyWithProps
42
+ extends GroupSpec<string, FunctionSpec.AnyWithProps, AnyWithProps> {}
43
+
44
+ export type Name<Group extends AnyWithProps> = Group["name"];
45
+
46
+ export type Functions<Group extends AnyWithProps> =
47
+ Group["functions"][keyof Group["functions"]];
48
+
49
+ export type Groups<Group extends AnyWithProps> =
50
+ Group["groups"][keyof Group["groups"]];
51
+
52
+ export type GroupNames<Group extends AnyWithProps> = [Groups<Group>] extends [
53
+ never,
54
+ ]
55
+ ? never
56
+ : Name<Groups<Group>>;
57
+
58
+ export type WithName<
59
+ Group extends AnyWithProps,
60
+ Name_ extends Name<Group>,
61
+ > = Extract<Group, { readonly name: Name_ }>;
62
+
63
+ const Proto = {
64
+ [TypeId]: TypeId,
65
+
66
+ addFunction<Function extends FunctionSpec.AnyWithProps>(
67
+ this: Any,
68
+ function_: Function,
69
+ ) {
70
+ const this_ = this as AnyWithProps;
71
+
72
+ return makeProto({
73
+ name: this_.name,
74
+ functions: Record.set(this_.functions, function_.name, function_),
75
+ groups: this_.groups,
76
+ });
77
+ },
78
+
79
+ addGroup<Group extends Any>(this: Any, group: Group) {
80
+ const this_ = this as AnyWithProps;
81
+ const group_ = group as unknown as AnyWithProps;
82
+
83
+ return makeProto({
84
+ name: this_.name,
85
+ functions: this_.functions,
86
+ groups: Record.set(this_.groups, group_.name, group_),
87
+ });
88
+ },
89
+ };
90
+
91
+ const makeProto = <
92
+ Name_ extends string,
93
+ Functions_ extends FunctionSpec.AnyWithProps,
94
+ Groups_ extends AnyWithProps,
95
+ >({
96
+ name,
97
+ functions,
98
+ groups,
99
+ }: {
100
+ name: Name_;
101
+ functions: Record.ReadonlyRecord<string, Functions_>;
102
+ groups: Record.ReadonlyRecord<string, Groups_>;
103
+ }): GroupSpec<Name_, Functions_, Groups_> =>
104
+ Object.assign(Object.create(Proto), {
105
+ name,
106
+ functions,
107
+ groups,
108
+ });
109
+
110
+ export const make = <const Name_ extends string>(
111
+ name: Name_,
112
+ ): GroupSpec<Name_> => {
113
+ validateConfectFunctionIdentifier(name);
114
+
115
+ return makeProto({
116
+ name,
117
+ functions: Record.empty(),
118
+ groups: Record.empty(),
119
+ });
120
+ };
@@ -0,0 +1,21 @@
1
+ import { Schema } from "effect";
2
+
3
+ export const PaginationResult = <Doc extends Schema.Schema.AnyNoContext>(
4
+ Doc: Doc,
5
+ ) =>
6
+ Schema.Struct({
7
+ page: Schema.mutable(Schema.Array(Doc)),
8
+ isDone: Schema.Boolean,
9
+ continueCursor: Schema.String,
10
+ splitCursor: Schema.optionalWith(Schema.Union(Schema.String, Schema.Null), {
11
+ exact: true,
12
+ }),
13
+ pageStatus: Schema.optionalWith(
14
+ Schema.Union(
15
+ Schema.Literal("SplitRecommended"),
16
+ Schema.Literal("SplitRequired"),
17
+ Schema.Null,
18
+ ),
19
+ { exact: true },
20
+ ),
21
+ });
package/src/Ref.ts ADDED
@@ -0,0 +1,175 @@
1
+ import type { FunctionType, FunctionVisibility } from "convex/server";
2
+ import type { Schema } from "effect";
3
+ import type * as FunctionSpec from "./FunctionSpec";
4
+
5
+ export interface Ref<
6
+ _FunctionType extends FunctionType,
7
+ _FunctionVisibility extends FunctionVisibility,
8
+ _Args extends Schema.Schema.AnyNoContext,
9
+ _Returns extends Schema.Schema.AnyNoContext,
10
+ > {
11
+ readonly _FunctionType?: _FunctionType;
12
+ readonly _FunctionVisibility?: _FunctionVisibility;
13
+ readonly _Args?: _Args;
14
+ readonly _Returns?: _Returns;
15
+ }
16
+
17
+ export interface Any extends Ref<any, any, any, any> {}
18
+
19
+ export interface AnyInternal extends Ref<any, "internal", any, any> {}
20
+
21
+ export interface AnyPublic extends Ref<any, "public", any, any> {}
22
+
23
+ export interface AnyQuery
24
+ extends Ref<
25
+ "query",
26
+ FunctionVisibility,
27
+ Schema.Schema.AnyNoContext,
28
+ Schema.Schema.AnyNoContext
29
+ > {}
30
+
31
+ export interface AnyMutation
32
+ extends Ref<
33
+ "mutation",
34
+ FunctionVisibility,
35
+ Schema.Schema.AnyNoContext,
36
+ Schema.Schema.AnyNoContext
37
+ > {}
38
+
39
+ export interface AnyAction
40
+ extends Ref<
41
+ "action",
42
+ FunctionVisibility,
43
+ Schema.Schema.AnyNoContext,
44
+ Schema.Schema.AnyNoContext
45
+ > {}
46
+
47
+ export interface AnyPublicQuery
48
+ extends Ref<
49
+ "query",
50
+ "public",
51
+ Schema.Schema.AnyNoContext,
52
+ Schema.Schema.AnyNoContext
53
+ > {}
54
+
55
+ export interface AnyPublicMutation
56
+ extends Ref<
57
+ "mutation",
58
+ "public",
59
+ Schema.Schema.AnyNoContext,
60
+ Schema.Schema.AnyNoContext
61
+ > {}
62
+
63
+ export interface AnyPublicAction
64
+ extends Ref<
65
+ "action",
66
+ "public",
67
+ Schema.Schema.AnyNoContext,
68
+ Schema.Schema.AnyNoContext
69
+ > {}
70
+
71
+ export type GetFunctionType<Ref_> =
72
+ Ref_ extends Ref<
73
+ infer FunctionType_,
74
+ infer _FunctionVisibility,
75
+ infer _Args,
76
+ infer _Returns
77
+ >
78
+ ? FunctionType_
79
+ : never;
80
+
81
+ export type GetFunctionVisibility<Ref_> =
82
+ Ref_ extends Ref<
83
+ infer _FunctionType,
84
+ infer FunctionVisibility_,
85
+ infer _Args,
86
+ infer _Returns
87
+ >
88
+ ? FunctionVisibility_
89
+ : never;
90
+
91
+ export type Args<Ref_> =
92
+ Ref_ extends Ref<
93
+ infer _FunctionType,
94
+ infer _FunctionVisibility,
95
+ infer Args_,
96
+ infer _Returns
97
+ >
98
+ ? Args_
99
+ : never;
100
+
101
+ export type Returns<Ref_> =
102
+ Ref_ extends Ref<
103
+ infer _FunctionType,
104
+ infer _FunctionVisibility,
105
+ infer _Args,
106
+ infer Returns_
107
+ >
108
+ ? Returns_
109
+ : never;
110
+
111
+ export type FromFunctionSpec<F extends FunctionSpec.AnyWithProps> = Ref<
112
+ FunctionSpec.GetFunctionType<F>,
113
+ FunctionSpec.GetFunctionVisibility<F>,
114
+ FunctionSpec.Args<F>,
115
+ FunctionSpec.Returns<F>
116
+ >;
117
+
118
+ export const make = <
119
+ FunctionType_ extends FunctionType,
120
+ FunctionVisibility_ extends FunctionVisibility,
121
+ Args_ extends Schema.Schema.AnyNoContext,
122
+ Returns_ extends Schema.Schema.AnyNoContext,
123
+ >(
124
+ /**
125
+ * This is a Convex "function name" of the format "myGroupDir/myGroupMod:myFunc".
126
+ */
127
+ convexFunctionName: string,
128
+ // TODO: Pull out all of the fields from the function spec except the name (we don't need it because we already have the convex function name) and spread them here
129
+ function_: FunctionSpec.FunctionSpec<
130
+ FunctionType_,
131
+ FunctionVisibility_,
132
+ string,
133
+ Args_,
134
+ Returns_
135
+ >,
136
+ ): Ref<FunctionType_, FunctionVisibility_, Args_, Returns_> =>
137
+ ({
138
+ [HiddenFunctionKey]: function_,
139
+ [HiddenConvexFunctionNameKey]: convexFunctionName,
140
+ }) as Ref<FunctionType_, FunctionVisibility_, Args_, Returns_>;
141
+
142
+ // TODO: Is this hidden stuff necessary/useful still?
143
+ const HiddenFunctionKey = "@confect/core/api/HiddenFunctionKey";
144
+ type HiddenFunctionKey = typeof HiddenFunctionKey;
145
+ type HiddenFunction<Ref_ extends Any> = FunctionSpec.FunctionSpec<
146
+ GetFunctionType<Ref_>,
147
+ GetFunctionVisibility<Ref_>,
148
+ string,
149
+ Args<Ref_>,
150
+ Returns<Ref_>
151
+ >;
152
+
153
+ export const getFunction = <
154
+ FunctionType_ extends FunctionType,
155
+ FunctionVisibility_ extends FunctionVisibility,
156
+ Args_ extends Schema.Schema.AnyNoContext,
157
+ Returns_ extends Schema.Schema.AnyNoContext,
158
+ Ref_ extends Ref<FunctionType_, FunctionVisibility_, Args_, Returns_>,
159
+ >(
160
+ ref: Ref_,
161
+ ): HiddenFunction<Ref_> => (ref as any)[HiddenFunctionKey];
162
+
163
+ const HiddenConvexFunctionNameKey =
164
+ "@confect/core/api/HiddenConvexFunctionNameKey";
165
+ type HiddenConvexFunctionNameKey = typeof HiddenConvexFunctionNameKey;
166
+ type HiddenConvexFunctionName = string;
167
+
168
+ export const getConvexFunctionName = <
169
+ FunctionType_ extends FunctionType,
170
+ FunctionVisibility_ extends FunctionVisibility,
171
+ Args_ extends Schema.Schema.AnyNoContext,
172
+ Returns_ extends Schema.Schema.AnyNoContext,
173
+ >(
174
+ ref: Ref<FunctionType_, FunctionVisibility_, Args_, Returns_>,
175
+ ): HiddenConvexFunctionName => (ref as any)[HiddenConvexFunctionNameKey];
package/src/Refs.ts ADDED
@@ -0,0 +1,99 @@
1
+ import type { Types } from "effect";
2
+ import { pipe, Record } from "effect";
3
+ import type * as FunctionSpec from "./FunctionSpec";
4
+ import type * as GroupSpec from "./GroupSpec";
5
+ import * as Ref from "./Ref";
6
+ import type * as Spec from "./Spec";
7
+
8
+ export type Refs<
9
+ Spec_ extends Spec.AnyWithProps,
10
+ Predicate extends Ref.Any = Ref.Any,
11
+ > = Types.Simplify<Helper<Spec.Groups<Spec_>, Predicate>>;
12
+
13
+ type GroupRefs<
14
+ Group extends GroupSpec.AnyWithProps,
15
+ Predicate extends Ref.Any,
16
+ > = Types.Simplify<
17
+ Helper<GroupSpec.Groups<Group>, Predicate> &
18
+ FilteredFunctions<GroupSpec.Functions<Group>, Predicate>
19
+ >;
20
+
21
+ type FilteredFunctions<
22
+ Functions extends FunctionSpec.AnyWithProps,
23
+ Predicate extends Ref.Any,
24
+ > = {
25
+ [Name in FunctionSpec.Name<Functions> as FunctionSpec.WithName<
26
+ Functions,
27
+ Name
28
+ > extends infer F extends FunctionSpec.AnyWithProps
29
+ ? Ref.FromFunctionSpec<F> extends Predicate
30
+ ? Name
31
+ : never
32
+ : never]: FunctionSpec.WithName<Functions, Name> extends infer F extends
33
+ FunctionSpec.AnyWithProps
34
+ ? Ref.FromFunctionSpec<F>
35
+ : never;
36
+ };
37
+
38
+ type Helper<
39
+ Groups extends GroupSpec.AnyWithProps,
40
+ Predicate extends Ref.Any,
41
+ > = {
42
+ [GroupName in GroupSpec.Name<Groups> as GroupSpec.WithName<
43
+ Groups,
44
+ GroupName
45
+ > extends infer Group extends GroupSpec.AnyWithProps
46
+ ? GroupRefs<Group, Predicate> extends Record<string, never>
47
+ ? never
48
+ : GroupName
49
+ : never]: GroupSpec.WithName<Groups, GroupName> extends infer Group extends
50
+ GroupSpec.AnyWithProps
51
+ ? GroupRefs<Group, Predicate>
52
+ : never;
53
+ };
54
+
55
+ type Any =
56
+ | {
57
+ readonly [key: string]: Any;
58
+ }
59
+ | Ref.Any;
60
+
61
+ export const make = <Spec_ extends Spec.AnyWithProps>(
62
+ spec: Spec_,
63
+ ): {
64
+ all: Refs<Spec_>;
65
+ public: Refs<Spec_, Ref.AnyPublic>;
66
+ internal: Refs<Spec_, Ref.AnyInternal>;
67
+ } => {
68
+ const refs = makeHelper(spec.groups);
69
+ return {
70
+ all: refs as Refs<Spec_>,
71
+ public: refs as Refs<Spec_, Ref.AnyPublic>,
72
+ internal: refs as Refs<Spec_, Ref.AnyInternal>,
73
+ };
74
+ };
75
+
76
+ const makeHelper = (
77
+ groups: Record.ReadonlyRecord<string, GroupSpec.Any>,
78
+ groupPath: string | null = null,
79
+ ): Any =>
80
+ pipe(
81
+ groups as Record.ReadonlyRecord<string, GroupSpec.AnyWithProps>,
82
+ Record.map((group) => {
83
+ const currentGroupPath = groupPath
84
+ ? `${groupPath}/${group.name}`
85
+ : group.name;
86
+
87
+ return Record.union(
88
+ makeHelper(group.groups, currentGroupPath),
89
+ Record.map(group.functions, (function_) =>
90
+ Ref.make(`${currentGroupPath}:${function_.name}`, function_),
91
+ ),
92
+ (_subGroup, _function) => {
93
+ throw new Error(
94
+ `Group and function at same level have same name ('${Ref.getConvexFunctionName(_function)}')`,
95
+ );
96
+ },
97
+ );
98
+ }),
99
+ );
package/src/Spec.ts ADDED
@@ -0,0 +1,52 @@
1
+ import { Predicate, Record } from "effect";
2
+ import type * as GroupSpec from "./GroupSpec";
3
+
4
+ export const TypeId = "@confect/core/api/Spec";
5
+ export type TypeId = typeof TypeId;
6
+
7
+ export const isSpec = (u: unknown): u is AnyWithProps =>
8
+ Predicate.hasProperty(u, TypeId);
9
+
10
+ export interface Spec<Groups_ extends GroupSpec.AnyWithProps = never> {
11
+ readonly [TypeId]: TypeId;
12
+ readonly groups: {
13
+ [GroupName in GroupSpec.Name<Groups_>]: GroupSpec.WithName<
14
+ Groups_,
15
+ GroupName
16
+ >;
17
+ };
18
+
19
+ add<Group extends GroupSpec.AnyWithProps>(
20
+ group: Group,
21
+ ): Spec<Groups_ | Group>;
22
+ }
23
+
24
+ export interface Any {
25
+ readonly [TypeId]: TypeId;
26
+ }
27
+
28
+ export interface AnyWithProps extends Spec<GroupSpec.AnyWithProps> {}
29
+
30
+ export type Groups<Spec_ extends AnyWithProps> =
31
+ Spec_["groups"][keyof Spec_["groups"]];
32
+
33
+ const Proto = {
34
+ [TypeId]: TypeId,
35
+
36
+ add<Group extends GroupSpec.AnyWithProps>(this: AnyWithProps, group: Group) {
37
+ return makeProto({
38
+ groups: Record.set(this.groups, group.name, group),
39
+ });
40
+ },
41
+ };
42
+
43
+ const makeProto = <Groups_ extends GroupSpec.AnyWithProps>({
44
+ groups,
45
+ }: {
46
+ groups: Record.ReadonlyRecord<string, Groups_>;
47
+ }): Spec<Groups_> =>
48
+ Object.assign(Object.create(Proto), {
49
+ groups,
50
+ });
51
+
52
+ export const make = (): Spec => makeProto({ groups: {} });
@@ -0,0 +1,51 @@
1
+ import type {
2
+ Expand,
3
+ IdField,
4
+ SystemFields as NonIdSystemFields,
5
+ } from "convex/server";
6
+ import { Schema } from "effect";
7
+ import * as GenericId from "./GenericId";
8
+
9
+ type SystemFieldsSchema<TableName extends string> = Schema.Struct<{
10
+ _id: Schema.Schema<
11
+ GenericId.GenericId<TableName>,
12
+ GenericId.GenericId<TableName>,
13
+ never
14
+ >;
15
+ _creationTime: typeof Schema.Number;
16
+ }>;
17
+
18
+ /**
19
+ * Produces a schema for Convex system fields.
20
+ */
21
+ export const SystemFields = <TableName extends string>(
22
+ tableName: TableName,
23
+ ): SystemFieldsSchema<TableName> =>
24
+ Schema.Struct({
25
+ _id: GenericId.GenericId(tableName),
26
+ _creationTime: Schema.Number,
27
+ });
28
+
29
+ /**
30
+ * Extend a table schema with Convex system fields.
31
+ */
32
+ export const extendWithSystemFields = <
33
+ TableName extends string,
34
+ TableSchema extends Schema.Schema.AnyNoContext,
35
+ >(
36
+ tableName: TableName,
37
+ schema: TableSchema,
38
+ ): ExtendWithSystemFields<TableName, TableSchema> =>
39
+ Schema.extend(SystemFields(tableName), schema);
40
+
41
+ /**
42
+ * Extend a table schema with Convex system fields at the type level.
43
+ */
44
+ export type ExtendWithSystemFields<
45
+ TableName extends string,
46
+ TableSchema extends Schema.Schema.AnyNoContext,
47
+ > = Schema.extend<SystemFieldsSchema<TableName>, TableSchema>;
48
+
49
+ export type WithSystemFields<TableName extends string, Document> = Expand<
50
+ Readonly<IdField<TableName>> & Readonly<NonIdSystemFields> & Document
51
+ >;