@confect/server 8.0.0 → 9.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.
- package/CHANGELOG.md +41 -0
- package/dist/DatabaseSchema.d.ts +9 -4
- package/dist/DatabaseSchema.d.ts.map +1 -1
- package/dist/DatabaseSchema.js +4 -3
- package/dist/DatabaseSchema.js.map +1 -1
- package/dist/FunctionImpl.d.ts +10 -7
- package/dist/FunctionImpl.d.ts.map +1 -1
- package/dist/FunctionImpl.js +8 -8
- package/dist/FunctionImpl.js.map +1 -1
- package/dist/GroupImpl.d.ts +51 -12
- package/dist/GroupImpl.d.ts.map +1 -1
- package/dist/GroupImpl.js +72 -4
- package/dist/GroupImpl.js.map +1 -1
- package/dist/GroupPath.d.ts +8 -0
- package/dist/GroupPath.d.ts.map +1 -0
- package/dist/GroupPath.js +10 -0
- package/dist/GroupPath.js.map +1 -0
- package/dist/RegisteredConvexFunction.d.ts +6 -6
- package/dist/RegisteredConvexFunction.d.ts.map +1 -1
- package/dist/RegisteredFunction.d.ts +3 -3
- package/dist/RegisteredFunction.d.ts.map +1 -1
- package/dist/RegisteredFunctions.d.ts +15 -4
- package/dist/RegisteredFunctions.d.ts.map +1 -1
- package/dist/RegisteredFunctions.js +20 -11
- package/dist/RegisteredFunctions.js.map +1 -1
- package/dist/StorageActionWriter.d.ts +1 -1
- package/dist/index.d.ts +1 -3
- package/dist/index.js +1 -3
- package/package.json +4 -6
- package/src/DatabaseSchema.ts +10 -7
- package/src/FunctionImpl.ts +27 -36
- package/src/GroupImpl.ts +168 -32
- package/src/GroupPath.ts +43 -0
- package/src/RegisteredFunctions.ts +78 -28
- package/src/index.ts +0 -2
- package/dist/Impl.d.ts +0 -24
- package/dist/Impl.d.ts.map +0 -1
- package/dist/Impl.js +0 -28
- package/dist/Impl.js.map +0 -1
- package/dist/Registry.d.ts +0 -15
- package/dist/Registry.d.ts.map +0 -1
- package/dist/Registry.js +0 -10
- package/dist/Registry.js.map +0 -1
- package/src/Impl.ts +0 -59
- package/src/Registry.ts +0 -13
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AnyWithProps as AnyWithProps$1 } from "./Api.js";
|
|
2
2
|
import { Any, RegisteredFunction } from "./RegisteredFunction.js";
|
|
3
|
-
import {
|
|
3
|
+
import { GroupImpl } from "./GroupImpl.js";
|
|
4
4
|
import { AnyWithProps as AnyWithProps$2 } from "./RegistryItem.js";
|
|
5
5
|
import { Layer, Types } from "effect";
|
|
6
6
|
import * as Spec from "@confect/core/Spec";
|
|
@@ -9,14 +9,25 @@ import * as GroupSpec from "@confect/core/GroupSpec";
|
|
|
9
9
|
|
|
10
10
|
//#region src/RegisteredFunctions.d.ts
|
|
11
11
|
declare namespace RegisteredFunctions_d_exports {
|
|
12
|
-
export { AnyWithProps, RegisteredFunctions,
|
|
12
|
+
export { AnyWithProps, ForGroupPath, RegisteredFunctions, buildForGroup };
|
|
13
13
|
}
|
|
14
14
|
type RegisteredFunctions<Spec_ extends Spec.AnyWithProps> = Types.Simplify<RegisteredFunctionsHelper<Spec.Groups<Spec_>>>;
|
|
15
15
|
type RegisteredFunctionsHelper<Groups extends GroupSpec.AnyWithProps> = { [GroupName in GroupSpec.Name<Groups>]: GroupSpec.WithName<Groups, GroupName> extends infer Group extends GroupSpec.AnyWithProps ? GroupSpec.Groups<Group> extends infer SubGroups extends GroupSpec.AnyWithProps ? Types.Simplify<RegisteredFunctionsHelper<SubGroups> & { [FunctionName in FunctionSpec.Name<GroupSpec.Functions<Group>>]: FunctionSpec.WithName<GroupSpec.Functions<Group>, FunctionName> extends infer FunctionSpec_ extends FunctionSpec.AnyWithProps ? RegisteredFunction<FunctionSpec_> : never }> : { [FunctionName in FunctionSpec.Name<GroupSpec.Functions<Group>>]: FunctionSpec.WithName<GroupSpec.Functions<Group>, FunctionName> extends infer FunctionSpec_ extends FunctionSpec.AnyWithProps ? RegisteredFunction<FunctionSpec_> : never } : never };
|
|
16
16
|
interface AnyWithProps {
|
|
17
17
|
readonly [key: string]: Any | AnyWithProps;
|
|
18
18
|
}
|
|
19
|
-
|
|
19
|
+
type RegisteredFunctionsAtPath<Tree, Path extends string> = Path extends `${infer Head}.${infer Tail}` ? Head extends keyof Tree ? Tree[Head] extends AnyWithProps ? RegisteredFunctionsAtPath<Tree[Head], Tail> : never : never : Path extends keyof Tree ? Tree[Path] : never;
|
|
20
|
+
type ForGroupPath<Spec_ extends Spec.AnyWithProps, Path extends string> = RegisteredFunctionsAtPath<RegisteredFunctions<Spec_>, Path>;
|
|
21
|
+
/**
|
|
22
|
+
* Build the registered Convex functions for a single group from its finalized
|
|
23
|
+
* `GroupImpl` layer.
|
|
24
|
+
*
|
|
25
|
+
* The `groupLayer` parameter requires `GroupImpl<string, "Finalized">`, so
|
|
26
|
+
* impls that were never piped through `GroupImpl.finalize` (and impls with
|
|
27
|
+
* unmet `FunctionImpl` requirements, which cannot be finalized) are rejected
|
|
28
|
+
* at the codegen boundary, not just deep inside Convex at runtime.
|
|
29
|
+
*/
|
|
30
|
+
declare const buildForGroup: <Api_ extends AnyWithProps$1, const GroupPath_ extends string>(api: Api_, groupPath: GroupPath_, groupLayer: Layer.Layer<GroupImpl<string, "Finalized">>, makeRegisteredFunction: (api: Api_, registryItem: AnyWithProps$2) => Any) => ForGroupPath<Api_["spec"], GroupPath_>;
|
|
20
31
|
//#endregion
|
|
21
|
-
export { AnyWithProps, RegisteredFunctions, RegisteredFunctions_d_exports,
|
|
32
|
+
export { AnyWithProps, ForGroupPath, RegisteredFunctions, RegisteredFunctions_d_exports, buildForGroup };
|
|
22
33
|
//# sourceMappingURL=RegisteredFunctions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RegisteredFunctions.d.ts","names":[],"sources":["../src/RegisteredFunctions.ts"],"mappings":";;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"RegisteredFunctions.d.ts","names":[],"sources":["../src/RegisteredFunctions.ts"],"mappings":";;;;;;;;;;;;;KAqBY,mBAAA,eAAkC,IAAA,CAAK,YAAA,IACjD,KAAA,CAAM,QAAA,CAAS,yBAAA,CAA0B,IAAA,CAAK,MAAA,CAAO,KAAA;AAAA,KAElD,yBAAA,gBAAyC,SAAA,CAAU,YAAA,oBACxC,SAAA,CAAU,IAAA,CAAK,MAAA,IAAU,SAAA,CAAU,QAAA,CAC/C,MAAA,EACA,SAAA,8BAC4B,SAAA,CAAU,YAAA,GACpC,SAAA,CAAU,MAAA,CAAO,KAAA,kCACf,SAAA,CAAU,YAAA,GACV,KAAA,CAAM,QAAA,CACJ,yBAAA,CAA0B,SAAA,uBACP,YAAA,CAAa,IAAA,CAC5B,SAAA,CAAU,SAAA,CAAU,KAAA,KAClB,YAAA,CAAa,QAAA,CACf,SAAA,CAAU,SAAA,CAAU,KAAA,GACpB,YAAA,sCACoC,YAAA,CAAa,YAAA,GAC/C,kBAAA,CAAsC,aAAA,kCAK3B,YAAA,CAAa,IAAA,CAC5B,SAAA,CAAU,SAAA,CAAU,KAAA,KAClB,YAAA,CAAa,QAAA,CACf,SAAA,CAAU,SAAA,CAAU,KAAA,GACpB,YAAA,sCACoC,YAAA,CAAa,YAAA,GAC/C,kBAAA,CAAsC,aAAA;AAAA,UAMnC,YAAA;EAAA,UACL,GAAA,WAAc,GAAA,GAAyB,YAAA;AAAA;AAAA,KAG9C,yBAAA,8BAGD,IAAA,yCACA,IAAA,eAAmB,IAAA,GACjB,IAAA,CAAK,IAAA,UAAc,YAAA,GACjB,yBAAA,CAA0B,IAAA,CAAK,IAAA,GAAO,IAAA,oBAG1C,IAAA,eAAmB,IAAA,GACjB,IAAA,CAAK,IAAA;AAAA,KAGC,YAAA,eACI,IAAA,CAAK,YAAA,yBAEjB,yBAAA,CAA0B,mBAAA,CAAoB,KAAA,GAAQ,IAAA;;;;;;;;;;cAW7C,aAAA,gBACE,cAAA,mCAGb,GAAA,EAAK,IAAA,EACL,SAAA,EAAW,UAAA,EACX,UAAA,EAAY,KAAA,CAAM,KAAA,CAAM,SAAA,wBACxB,sBAAA,GACE,GAAA,EAAK,IAAA,EACL,YAAA,EAAc,cAAA,KACX,GAAA,KACJ,YAAA,CAAa,IAAA,UAAc,UAAA"}
|
|
@@ -1,19 +1,28 @@
|
|
|
1
1
|
import { __exportAll } from "./_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { mapLeaves } from "./internal/utils.js";
|
|
3
|
-
import { Registry } from "./Registry.js";
|
|
4
3
|
import { isRegistryItem } from "./RegistryItem.js";
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
4
|
+
import { Array, Effect, Option, Predicate, Ref, String, pipe } from "effect";
|
|
5
|
+
import * as Registry from "@confect/core/Registry";
|
|
7
6
|
|
|
8
7
|
//#region src/RegisteredFunctions.ts
|
|
9
|
-
var RegisteredFunctions_exports = /* @__PURE__ */ __exportAll({
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
var RegisteredFunctions_exports = /* @__PURE__ */ __exportAll({ buildForGroup: () => buildForGroup });
|
|
9
|
+
/**
|
|
10
|
+
* Build the registered Convex functions for a single group from its finalized
|
|
11
|
+
* `GroupImpl` layer.
|
|
12
|
+
*
|
|
13
|
+
* The `groupLayer` parameter requires `GroupImpl<string, "Finalized">`, so
|
|
14
|
+
* impls that were never piped through `GroupImpl.finalize` (and impls with
|
|
15
|
+
* unmet `FunctionImpl` requirements, which cannot be finalized) are rejected
|
|
16
|
+
* at the codegen boundary, not just deep inside Convex at runtime.
|
|
17
|
+
*/
|
|
18
|
+
const buildForGroup = (api, groupPath, groupLayer, makeRegisteredFunction) => {
|
|
19
|
+
const registeredFunctions = mapLeaves(Effect.gen(function* () {
|
|
20
|
+
const registry = yield* Registry.Registry;
|
|
21
|
+
return yield* Ref.get(registry);
|
|
22
|
+
}).pipe(Effect.provide(groupLayer), Effect.runSync), isRegistryItem, (registryItem) => makeRegisteredFunction(api, registryItem));
|
|
23
|
+
return pipe(String.split(groupPath, "."), Array.reduce(Option.some(registeredFunctions), (currentNode, segment) => currentNode.pipe(Option.filter(Predicate.isRecord), Option.flatMap((nodeRecord) => segment in nodeRecord ? Option.some(nodeRecord[segment]) : Option.none()))), Option.getOrThrowWith(() => /* @__PURE__ */ new Error(`No functions registered for group path "${groupPath}"`)));
|
|
24
|
+
};
|
|
16
25
|
|
|
17
26
|
//#endregion
|
|
18
|
-
export { RegisteredFunctions_exports,
|
|
27
|
+
export { RegisteredFunctions_exports, buildForGroup };
|
|
19
28
|
//# sourceMappingURL=RegisteredFunctions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RegisteredFunctions.js","names":["
|
|
1
|
+
{"version":3,"file":"RegisteredFunctions.js","names":["RegistryItem.isRegistryItem"],"sources":["../src/RegisteredFunctions.ts"],"sourcesContent":["import type * as FunctionSpec from \"@confect/core/FunctionSpec\";\nimport type * as GroupSpec from \"@confect/core/GroupSpec\";\nimport * as Registry from \"@confect/core/Registry\";\nimport type * as Spec from \"@confect/core/Spec\";\nimport {\n Array,\n Effect,\n type Layer,\n Option,\n pipe,\n Predicate,\n Ref,\n String,\n type Types,\n} from \"effect\";\nimport type * as Api from \"./Api\";\nimport type * as GroupImpl from \"./GroupImpl\";\nimport { mapLeaves } from \"./internal/utils\";\nimport type * as RegisteredFunction from \"./RegisteredFunction\";\nimport * as RegistryItem from \"./RegistryItem\";\n\nexport type RegisteredFunctions<Spec_ extends Spec.AnyWithProps> =\n Types.Simplify<RegisteredFunctionsHelper<Spec.Groups<Spec_>>>;\n\ntype RegisteredFunctionsHelper<Groups extends GroupSpec.AnyWithProps> = {\n [GroupName in GroupSpec.Name<Groups>]: GroupSpec.WithName<\n Groups,\n GroupName\n > extends infer Group extends GroupSpec.AnyWithProps\n ? GroupSpec.Groups<Group> extends infer SubGroups extends\n GroupSpec.AnyWithProps\n ? Types.Simplify<\n RegisteredFunctionsHelper<SubGroups> & {\n [FunctionName in FunctionSpec.Name<\n GroupSpec.Functions<Group>\n >]: FunctionSpec.WithName<\n GroupSpec.Functions<Group>,\n FunctionName\n > extends infer FunctionSpec_ extends FunctionSpec.AnyWithProps\n ? RegisteredFunction.RegisteredFunction<FunctionSpec_>\n : never;\n }\n >\n : {\n [FunctionName in FunctionSpec.Name<\n GroupSpec.Functions<Group>\n >]: FunctionSpec.WithName<\n GroupSpec.Functions<Group>,\n FunctionName\n > extends infer FunctionSpec_ extends FunctionSpec.AnyWithProps\n ? RegisteredFunction.RegisteredFunction<FunctionSpec_>\n : never;\n }\n : never;\n};\n\nexport interface AnyWithProps {\n readonly [key: string]: RegisteredFunction.Any | AnyWithProps;\n}\n\ntype RegisteredFunctionsAtPath<\n Tree,\n Path extends string,\n> = Path extends `${infer Head}.${infer Tail}`\n ? Head extends keyof Tree\n ? Tree[Head] extends AnyWithProps\n ? RegisteredFunctionsAtPath<Tree[Head], Tail>\n : never\n : never\n : Path extends keyof Tree\n ? Tree[Path]\n : never;\n\nexport type ForGroupPath<\n Spec_ extends Spec.AnyWithProps,\n Path extends string,\n> = RegisteredFunctionsAtPath<RegisteredFunctions<Spec_>, Path>;\n\n/**\n * Build the registered Convex functions for a single group from its finalized\n * `GroupImpl` layer.\n *\n * The `groupLayer` parameter requires `GroupImpl<string, \"Finalized\">`, so\n * impls that were never piped through `GroupImpl.finalize` (and impls with\n * unmet `FunctionImpl` requirements, which cannot be finalized) are rejected\n * at the codegen boundary, not just deep inside Convex at runtime.\n */\nexport const buildForGroup = <\n Api_ extends Api.AnyWithProps,\n const GroupPath_ extends string,\n>(\n api: Api_,\n groupPath: GroupPath_,\n groupLayer: Layer.Layer<GroupImpl.GroupImpl<string, \"Finalized\">>,\n makeRegisteredFunction: (\n api: Api_,\n registryItem: RegistryItem.AnyWithProps,\n ) => RegisteredFunction.Any,\n): ForGroupPath<Api_[\"spec\"], GroupPath_> => {\n const registryItems = Effect.gen(function* () {\n const registry = yield* Registry.Registry;\n return yield* Ref.get(registry);\n }).pipe(Effect.provide(groupLayer), Effect.runSync);\n\n const registeredFunctions = mapLeaves<\n RegistryItem.AnyWithProps,\n RegisteredFunction.Any\n >(\n registryItems as { [key: string]: RegistryItem.AnyWithProps },\n RegistryItem.isRegistryItem,\n (registryItem) => makeRegisteredFunction(api, registryItem),\n );\n\n return pipe(\n String.split(groupPath, \".\"),\n Array.reduce(\n Option.some<unknown>(registeredFunctions),\n (currentNode, segment) =>\n currentNode.pipe(\n Option.filter(Predicate.isRecord),\n Option.flatMap((nodeRecord) =>\n segment in nodeRecord\n ? Option.some(nodeRecord[segment])\n : Option.none(),\n ),\n ),\n ),\n Option.getOrThrowWith(\n () => new Error(`No functions registered for group path \"${groupPath}\"`),\n ),\n ) as ForGroupPath<Api_[\"spec\"], GroupPath_>;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AAuFA,MAAa,iBAIX,KACA,WACA,YACA,2BAI2C;CAM3C,MAAM,sBAAsB,UALN,OAAO,IAAI,aAAa;EAC5C,MAAM,WAAW,OAAO,SAAS;AACjC,SAAO,OAAO,IAAI,IAAI,SAAS;GAC/B,CAAC,KAAK,OAAO,QAAQ,WAAW,EAAE,OAAO,QAAQ,EAOjDA,iBACC,iBAAiB,uBAAuB,KAAK,aAAa,CAC5D;AAED,QAAO,KACL,OAAO,MAAM,WAAW,IAAI,EAC5B,MAAM,OACJ,OAAO,KAAc,oBAAoB,GACxC,aAAa,YACZ,YAAY,KACV,OAAO,OAAO,UAAU,SAAS,EACjC,OAAO,SAAS,eACd,WAAW,aACP,OAAO,KAAK,WAAW,SAAS,GAChC,OAAO,MAAM,CAClB,CACF,CACJ,EACD,OAAO,qCACC,IAAI,MAAM,2CAA2C,UAAU,GAAG,CACzE,CACF"}
|
|
@@ -25,7 +25,7 @@ declare const StorageActionWriter_base: effect_Context0.TagClass<StorageActionWr
|
|
|
25
25
|
store: (blob: Blob, options?: {
|
|
26
26
|
sha256?: string;
|
|
27
27
|
}) => Effect.Effect<GenericId<"_storage">, never, never>;
|
|
28
|
-
}) => X) => [X] extends [Effect.Effect<infer A, infer E, infer R>] ? Effect.Effect<A, E,
|
|
28
|
+
}) => X) => [X] extends [Effect.Effect<infer A, infer E, infer R>] ? Effect.Effect<A, E, R | StorageActionWriter> : [X] extends [PromiseLike<infer A_1>] ? Effect.Effect<A_1, effect_Cause0.UnknownException, StorageActionWriter> : Effect.Effect<X, never, StorageActionWriter>;
|
|
29
29
|
};
|
|
30
30
|
declare class StorageActionWriter extends StorageActionWriter_base {
|
|
31
31
|
static readonly layer: (storageActionWriter: StorageActionWriter$1) => Layer.Layer<StorageActionWriter, never, never>;
|
package/dist/index.d.ts
CHANGED
|
@@ -30,9 +30,7 @@ import { Handler_d_exports } from "./Handler.js";
|
|
|
30
30
|
import { FunctionImpl_d_exports } from "./FunctionImpl.js";
|
|
31
31
|
import { GroupImpl_d_exports } from "./GroupImpl.js";
|
|
32
32
|
import { HttpApi_d_exports } from "./HttpApi.js";
|
|
33
|
-
import { Impl_d_exports } from "./Impl.js";
|
|
34
33
|
import { RegistryItem_d_exports } from "./RegistryItem.js";
|
|
35
34
|
import { RegisteredConvexFunction_d_exports } from "./RegisteredConvexFunction.js";
|
|
36
35
|
import { RegisteredFunctions_d_exports } from "./RegisteredFunctions.js";
|
|
37
|
-
|
|
38
|
-
export { ActionCtx_d_exports as ActionCtx, ActionRunner_d_exports as ActionRunner, Api_d_exports as Api, Auth_d_exports as Auth, BlobNotFoundError_d_exports as BlobNotFoundError, ConvexConfigProvider_d_exports as ConvexConfigProvider, CronJob_d_exports as CronJob, CronJobs_d_exports as CronJobs, DataModel_d_exports as DataModel, DatabaseReader_d_exports as DatabaseReader, DatabaseSchema_d_exports as DatabaseSchema, DatabaseWriter_d_exports as DatabaseWriter, Document_d_exports as Document, FunctionImpl_d_exports as FunctionImpl, GroupImpl_d_exports as GroupImpl, Handler_d_exports as Handler, HttpApi_d_exports as HttpApi, Impl_d_exports as Impl, MutationCtx_d_exports as MutationCtx, MutationRunner_d_exports as MutationRunner, OrderedQuery_d_exports as OrderedQuery, QueryCtx_d_exports as QueryCtx, QueryInitializer_d_exports as QueryInitializer, QueryRunner_d_exports as QueryRunner, RegisteredConvexFunction_d_exports as RegisteredConvexFunction, RegisteredFunction_d_exports as RegisteredFunction, RegisteredFunctions_d_exports as RegisteredFunctions, Registry_d_exports as Registry, RegistryItem_d_exports as RegistryItem, Scheduler_d_exports as Scheduler, SchemaToValidator_d_exports as SchemaToValidator, StorageActionWriter_d_exports as StorageActionWriter, StorageReader_d_exports as StorageReader, StorageWriter_d_exports as StorageWriter, Table_d_exports as Table, TableInfo_d_exports as TableInfo, VectorSearch_d_exports as VectorSearch };
|
|
36
|
+
export { ActionCtx_d_exports as ActionCtx, ActionRunner_d_exports as ActionRunner, Api_d_exports as Api, Auth_d_exports as Auth, BlobNotFoundError_d_exports as BlobNotFoundError, ConvexConfigProvider_d_exports as ConvexConfigProvider, CronJob_d_exports as CronJob, CronJobs_d_exports as CronJobs, DataModel_d_exports as DataModel, DatabaseReader_d_exports as DatabaseReader, DatabaseSchema_d_exports as DatabaseSchema, DatabaseWriter_d_exports as DatabaseWriter, Document_d_exports as Document, FunctionImpl_d_exports as FunctionImpl, GroupImpl_d_exports as GroupImpl, Handler_d_exports as Handler, HttpApi_d_exports as HttpApi, MutationCtx_d_exports as MutationCtx, MutationRunner_d_exports as MutationRunner, OrderedQuery_d_exports as OrderedQuery, QueryCtx_d_exports as QueryCtx, QueryInitializer_d_exports as QueryInitializer, QueryRunner_d_exports as QueryRunner, RegisteredConvexFunction_d_exports as RegisteredConvexFunction, RegisteredFunction_d_exports as RegisteredFunction, RegisteredFunctions_d_exports as RegisteredFunctions, RegistryItem_d_exports as RegistryItem, Scheduler_d_exports as Scheduler, SchemaToValidator_d_exports as SchemaToValidator, StorageActionWriter_d_exports as StorageActionWriter, StorageReader_d_exports as StorageReader, StorageWriter_d_exports as StorageWriter, Table_d_exports as Table, TableInfo_d_exports as TableInfo, VectorSearch_d_exports as VectorSearch };
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,6 @@ import { OrderedQuery_exports } from "./OrderedQuery.js";
|
|
|
15
15
|
import { QueryInitializer_exports } from "./QueryInitializer.js";
|
|
16
16
|
import { DatabaseReader_exports } from "./DatabaseReader.js";
|
|
17
17
|
import { DatabaseWriter_exports } from "./DatabaseWriter.js";
|
|
18
|
-
import { Registry_exports } from "./Registry.js";
|
|
19
18
|
import { RegistryItem_exports } from "./RegistryItem.js";
|
|
20
19
|
import { FunctionImpl_exports } from "./FunctionImpl.js";
|
|
21
20
|
import { GroupImpl_exports } from "./GroupImpl.js";
|
|
@@ -27,7 +26,6 @@ import { StorageActionWriter_exports } from "./StorageActionWriter.js";
|
|
|
27
26
|
import { StorageReader_exports } from "./StorageReader.js";
|
|
28
27
|
import { StorageWriter_exports } from "./StorageWriter.js";
|
|
29
28
|
import { HttpApi_exports } from "./HttpApi.js";
|
|
30
|
-
import { Impl_exports } from "./Impl.js";
|
|
31
29
|
import { MutationCtx_exports } from "./MutationCtx.js";
|
|
32
30
|
import { QueryCtx_exports } from "./QueryCtx.js";
|
|
33
31
|
import { VectorSearch_exports } from "./VectorSearch.js";
|
|
@@ -36,4 +34,4 @@ import { RegisteredConvexFunction_exports } from "./RegisteredConvexFunction.js"
|
|
|
36
34
|
import { RegisteredFunctions_exports } from "./RegisteredFunctions.js";
|
|
37
35
|
import { TableInfo_exports } from "./TableInfo.js";
|
|
38
36
|
|
|
39
|
-
export { ActionCtx_exports as ActionCtx, ActionRunner_exports as ActionRunner, Api_exports as Api, Auth_exports as Auth, BlobNotFoundError_exports as BlobNotFoundError, ConvexConfigProvider_exports as ConvexConfigProvider, CronJob_exports as CronJob, CronJobs_exports as CronJobs, DataModel_exports as DataModel, DatabaseReader_exports as DatabaseReader, DatabaseSchema_exports as DatabaseSchema, DatabaseWriter_exports as DatabaseWriter, Document_exports as Document, FunctionImpl_exports as FunctionImpl, GroupImpl_exports as GroupImpl, Handler_exports as Handler, HttpApi_exports as HttpApi,
|
|
37
|
+
export { ActionCtx_exports as ActionCtx, ActionRunner_exports as ActionRunner, Api_exports as Api, Auth_exports as Auth, BlobNotFoundError_exports as BlobNotFoundError, ConvexConfigProvider_exports as ConvexConfigProvider, CronJob_exports as CronJob, CronJobs_exports as CronJobs, DataModel_exports as DataModel, DatabaseReader_exports as DatabaseReader, DatabaseSchema_exports as DatabaseSchema, DatabaseWriter_exports as DatabaseWriter, Document_exports as Document, FunctionImpl_exports as FunctionImpl, GroupImpl_exports as GroupImpl, Handler_exports as Handler, HttpApi_exports as HttpApi, MutationCtx_exports as MutationCtx, MutationRunner_exports as MutationRunner, OrderedQuery_exports as OrderedQuery, QueryCtx_exports as QueryCtx, QueryInitializer_exports as QueryInitializer, QueryRunner_exports as QueryRunner, RegisteredConvexFunction_exports as RegisteredConvexFunction, RegisteredFunction_exports as RegisteredFunction, RegisteredFunctions_exports as RegisteredFunctions, RegistryItem_exports as RegistryItem, Scheduler_exports as Scheduler, SchemaToValidator_exports as SchemaToValidator, StorageActionWriter_exports as StorageActionWriter, StorageReader_exports as StorageReader, StorageWriter_exports as StorageWriter, Table_exports as Table, TableInfo_exports as TableInfo, VectorSearch_exports as VectorSearch };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@confect/server",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0-next.0",
|
|
4
4
|
"description": "Backend bindings to the Convex platform",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -66,16 +66,14 @@
|
|
|
66
66
|
"typescript-eslint": "8.56.1",
|
|
67
67
|
"vite": "7.3.1",
|
|
68
68
|
"vite-tsconfig-paths": "6.1.1",
|
|
69
|
-
"vitest": "3.2.4"
|
|
70
|
-
"@confect/cli": "8.0.0",
|
|
71
|
-
"@confect/test": "8.0.0"
|
|
69
|
+
"vitest": "3.2.4"
|
|
72
70
|
},
|
|
73
71
|
"peerDependencies": {
|
|
74
72
|
"@effect/platform": "^0.96.1",
|
|
75
73
|
"@effect/platform-node": "^0.106.0",
|
|
76
|
-
"convex": "
|
|
74
|
+
"convex": "1.39.1",
|
|
77
75
|
"effect": "^3.21.2",
|
|
78
|
-
"@confect/core": "^
|
|
76
|
+
"@confect/core": "^9.0.0-next.0"
|
|
79
77
|
},
|
|
80
78
|
"engines": {
|
|
81
79
|
"node": ">=22",
|
package/src/DatabaseSchema.ts
CHANGED
|
@@ -3,15 +3,18 @@ import {
|
|
|
3
3
|
defineSchema as defineConvexSchema,
|
|
4
4
|
type SchemaDefinition,
|
|
5
5
|
} from "convex/server";
|
|
6
|
-
import { Array, pipe, Record } from "effect";
|
|
6
|
+
import { Array, pipe, Predicate, Record } from "effect";
|
|
7
7
|
import * as Table from "./Table";
|
|
8
|
-
import { TypeId } from "@confect/core/DatabaseSchema";
|
|
9
8
|
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
export const TypeId = "@confect/server/DatabaseSchema";
|
|
10
|
+
export type TypeId = typeof TypeId;
|
|
11
|
+
|
|
12
|
+
export interface Any {
|
|
13
|
+
readonly [TypeId]: TypeId;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const isDatabaseSchema = (u: unknown): u is Any =>
|
|
17
|
+
Predicate.hasProperty(u, TypeId);
|
|
15
18
|
|
|
16
19
|
/**
|
|
17
20
|
* A schema definition tracks the schema and its Convex schema definition.
|
package/src/FunctionImpl.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type * as FunctionSpec from "@confect/core/FunctionSpec";
|
|
2
|
-
import type * as GroupPath from "@confect/core/GroupPath";
|
|
3
2
|
import type * as GroupSpec from "@confect/core/GroupSpec";
|
|
4
|
-
import
|
|
3
|
+
import * as Registry from "@confect/core/Registry";
|
|
4
|
+
import { Context, Effect, Layer, Ref, String } from "effect";
|
|
5
5
|
import type * as Api from "./Api";
|
|
6
|
+
import { resolveGroupPathUnsafe } from "./GroupPath";
|
|
6
7
|
import type * as Handler from "./Handler";
|
|
7
8
|
import { setNestedProperty } from "./internal/utils";
|
|
8
|
-
import * as Registry from "./Registry";
|
|
9
9
|
import * as RegistryItem from "./RegistryItem";
|
|
10
10
|
|
|
11
11
|
export interface FunctionImpl<
|
|
@@ -32,34 +32,23 @@ export const FunctionImpl = <
|
|
|
32
32
|
|
|
33
33
|
export const make = <
|
|
34
34
|
Api_ extends Api.AnyWithProps,
|
|
35
|
-
|
|
36
|
-
const FunctionName extends FunctionSpec.Name<
|
|
37
|
-
GroupSpec.Functions<GroupPath.GroupAt<Api.Groups<Api_>, GroupPath_>>
|
|
38
|
-
>,
|
|
35
|
+
Group extends GroupSpec.AnyWithProps,
|
|
36
|
+
const FunctionName extends FunctionSpec.Name<GroupSpec.Functions<Group>>,
|
|
39
37
|
>(
|
|
40
38
|
api: Api_,
|
|
41
|
-
|
|
39
|
+
group: Group,
|
|
42
40
|
functionName: FunctionName,
|
|
43
41
|
handler: Handler.WithName<
|
|
44
42
|
Api.Schema<Api_>,
|
|
45
|
-
GroupSpec.Functions<
|
|
43
|
+
GroupSpec.Functions<Group>,
|
|
46
44
|
FunctionName
|
|
47
45
|
>,
|
|
48
|
-
): Layer.Layer<FunctionImpl<
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
const group_: GroupSpec.AnyWithProps = Array.reduce(
|
|
53
|
-
restGroupPathParts,
|
|
54
|
-
(api as any).spec.groups[firstGroupPathPart as any]!,
|
|
55
|
-
(currentGroup: any, groupPathPart: any) =>
|
|
56
|
-
currentGroup.groups[groupPathPart],
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
const functionSpec = group_.functions[functionName]!;
|
|
46
|
+
): Layer.Layer<FunctionImpl<string, FunctionName>> => {
|
|
47
|
+
const groupPath = resolveGroupPathUnsafe(api.spec, group);
|
|
48
|
+
const functionSpec = group.functions[functionName]!;
|
|
60
49
|
|
|
61
50
|
return Layer.effect(
|
|
62
|
-
FunctionImpl<
|
|
51
|
+
FunctionImpl<string, FunctionName>({
|
|
63
52
|
groupPath,
|
|
64
53
|
functionName,
|
|
65
54
|
}),
|
|
@@ -69,7 +58,7 @@ export const make = <
|
|
|
69
58
|
yield* Ref.update(registry, (registryItems) =>
|
|
70
59
|
setNestedProperty(
|
|
71
60
|
registryItems,
|
|
72
|
-
[...
|
|
61
|
+
[...String.split(groupPath, "."), functionName],
|
|
73
62
|
RegistryItem.make({
|
|
74
63
|
functionSpec,
|
|
75
64
|
handler,
|
|
@@ -94,19 +83,21 @@ export type ForGroupPathAndFunction<
|
|
|
94
83
|
> = FunctionImpl<GroupPath_, FunctionName>;
|
|
95
84
|
|
|
96
85
|
/**
|
|
97
|
-
* Get all function implementation services required for a group
|
|
86
|
+
* Get all function implementation services required for a group spec.
|
|
98
87
|
*/
|
|
99
|
-
export type
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
? FunctionSpec.Name<
|
|
106
|
-
GroupSpec.Functions<GroupAtPath>
|
|
107
|
-
> extends infer FunctionNames extends string
|
|
108
|
-
? FunctionNames extends string
|
|
109
|
-
? FunctionImpl<GroupPath_, FunctionNames>
|
|
110
|
-
: never
|
|
88
|
+
export type FromGroupSpec<Group extends GroupSpec.AnyWithProps> =
|
|
89
|
+
FunctionSpec.Name<
|
|
90
|
+
GroupSpec.Functions<Group>
|
|
91
|
+
> extends infer FunctionNames extends string
|
|
92
|
+
? FunctionNames extends string
|
|
93
|
+
? FunctionImpl<string, FunctionNames>
|
|
111
94
|
: never
|
|
112
95
|
: never;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @deprecated Use {@link FromGroupSpec} instead.
|
|
99
|
+
*/
|
|
100
|
+
export type FromGroupAtPath<
|
|
101
|
+
_GroupPath extends string,
|
|
102
|
+
Group extends GroupSpec.AnyWithProps,
|
|
103
|
+
> = FromGroupSpec<Group>;
|
package/src/GroupImpl.ts
CHANGED
|
@@ -1,60 +1,196 @@
|
|
|
1
|
-
import type * as GroupPath from "@confect/core/GroupPath";
|
|
2
1
|
import type * as GroupSpec from "@confect/core/GroupSpec";
|
|
3
|
-
import
|
|
2
|
+
import * as Registry from "@confect/core/Registry";
|
|
3
|
+
import {
|
|
4
|
+
Array,
|
|
5
|
+
Context,
|
|
6
|
+
Effect,
|
|
7
|
+
Layer,
|
|
8
|
+
Option,
|
|
9
|
+
pipe,
|
|
10
|
+
Predicate,
|
|
11
|
+
Record,
|
|
12
|
+
Ref,
|
|
13
|
+
String,
|
|
14
|
+
} from "effect";
|
|
4
15
|
import type * as Api from "./Api";
|
|
5
16
|
import type * as FunctionImpl from "./FunctionImpl";
|
|
17
|
+
import { resolveGroupPathUnsafe } from "./GroupPath";
|
|
6
18
|
|
|
7
|
-
export
|
|
19
|
+
export const TypeId = "@confect/server/GroupImpl";
|
|
20
|
+
export type TypeId = typeof TypeId;
|
|
21
|
+
|
|
22
|
+
export type FinalizationStatus = "Unfinalized" | "Finalized";
|
|
23
|
+
|
|
24
|
+
export interface GroupImpl<
|
|
25
|
+
GroupPath_ extends string,
|
|
26
|
+
FinalizationStatus_ extends FinalizationStatus = "Unfinalized",
|
|
27
|
+
> {
|
|
28
|
+
readonly [TypeId]: TypeId;
|
|
8
29
|
readonly groupPath: GroupPath_;
|
|
30
|
+
readonly finalizationStatus: FinalizationStatus_;
|
|
31
|
+
/**
|
|
32
|
+
* Names of every function registered into this group's layer scope by
|
|
33
|
+
* `FunctionImpl.make`. Authoritative only when `finalizationStatus` is
|
|
34
|
+
* `"Finalized"`; the `"Unfinalized"` value is set to `[]` at `make`-time
|
|
35
|
+
* since the list is only known once `finalize` snapshots the registry.
|
|
36
|
+
*/
|
|
37
|
+
readonly registeredFunctionNames: ReadonlyArray<string>;
|
|
9
38
|
}
|
|
10
39
|
|
|
11
|
-
export
|
|
40
|
+
export interface Any extends GroupImpl<string, FinalizationStatus> {}
|
|
41
|
+
|
|
42
|
+
export const isGroupImpl = (u: unknown): u is Any =>
|
|
43
|
+
Predicate.hasProperty(u, TypeId);
|
|
44
|
+
|
|
45
|
+
export interface AnyFinalized extends GroupImpl<string, "Finalized"> {}
|
|
46
|
+
export interface AnyUnfinalized extends GroupImpl<string, "Unfinalized"> {}
|
|
47
|
+
|
|
48
|
+
export const isFinalizedGroupImpl = (u: unknown): u is AnyFinalized =>
|
|
49
|
+
isGroupImpl(u) && u.finalizationStatus === "Finalized";
|
|
50
|
+
|
|
51
|
+
export const isUnfinalizedGroupImpl = (u: unknown): u is AnyUnfinalized =>
|
|
52
|
+
isGroupImpl(u) && u.finalizationStatus === "Unfinalized";
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Build the runtime tag for a `GroupImpl` service. The finalization status is
|
|
56
|
+
* embedded in the tag string so that `Unfinalized` and `Finalized` are distinct
|
|
57
|
+
* services at runtime; consumers of a finalized layer (the server's
|
|
58
|
+
* `RegisteredFunctions.buildForGroup` and the CLI's `implValidation`) retrieve
|
|
59
|
+
* the typed `Finalized` service directly rather than scanning the context.
|
|
60
|
+
*/
|
|
61
|
+
export const GroupImpl = <
|
|
62
|
+
GroupPath_ extends string,
|
|
63
|
+
FinalizationStatus_ extends FinalizationStatus,
|
|
64
|
+
>({
|
|
12
65
|
groupPath,
|
|
66
|
+
finalizationStatus,
|
|
13
67
|
}: {
|
|
14
68
|
groupPath: GroupPath_;
|
|
69
|
+
finalizationStatus: FinalizationStatus_;
|
|
15
70
|
}) =>
|
|
16
|
-
Context.GenericTag<GroupImpl<GroupPath_>>(
|
|
17
|
-
`@confect/server/GroupImpl/${groupPath}`,
|
|
71
|
+
Context.GenericTag<GroupImpl<GroupPath_, FinalizationStatus_>>(
|
|
72
|
+
`@confect/server/GroupImpl/${finalizationStatus}/${groupPath}`,
|
|
18
73
|
);
|
|
19
74
|
|
|
20
75
|
export const make = <
|
|
21
76
|
Api_ extends Api.AnyWithProps,
|
|
22
|
-
|
|
77
|
+
Group extends GroupSpec.AnyWithProps,
|
|
23
78
|
>(
|
|
24
|
-
|
|
25
|
-
|
|
79
|
+
api: Api_,
|
|
80
|
+
group: Group,
|
|
26
81
|
): Layer.Layer<
|
|
27
|
-
GroupImpl<
|
|
82
|
+
GroupImpl<string, "Unfinalized">,
|
|
28
83
|
never,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
84
|
+
FunctionImpl.FromGroupSpec<Group>
|
|
85
|
+
> => {
|
|
86
|
+
const groupPath = resolveGroupPathUnsafe(api.spec, group);
|
|
87
|
+
|
|
88
|
+
return Layer.succeed(
|
|
89
|
+
GroupImpl<string, "Unfinalized">({
|
|
34
90
|
groupPath,
|
|
91
|
+
finalizationStatus: "Unfinalized",
|
|
35
92
|
}),
|
|
36
93
|
{
|
|
94
|
+
[TypeId]: TypeId,
|
|
37
95
|
groupPath,
|
|
96
|
+
finalizationStatus: "Unfinalized" as const,
|
|
97
|
+
registeredFunctionNames: [],
|
|
38
98
|
},
|
|
39
99
|
) as Layer.Layer<
|
|
40
|
-
GroupImpl<
|
|
100
|
+
GroupImpl<string, "Unfinalized">,
|
|
41
101
|
never,
|
|
42
|
-
|
|
43
|
-
| FunctionImpl.FromGroupAtPath<GroupPath_, Api.Groups<Api_>>
|
|
102
|
+
FunctionImpl.FromGroupSpec<Group>
|
|
44
103
|
>;
|
|
104
|
+
};
|
|
45
105
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
: Groups extends GroupSpec.AnyWithProps
|
|
49
|
-
? GroupImpl<GroupSpec.Name<Groups>>
|
|
50
|
-
: never;
|
|
106
|
+
const isFunctionShaped = (value: unknown): boolean =>
|
|
107
|
+
Predicate.isRecord(value) && "functionSpec" in value;
|
|
51
108
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Walk a `RegistryItems` tree to the entries at `groupPath` and return the
|
|
111
|
+
* names of the function-shaped leaves directly underneath.
|
|
112
|
+
*/
|
|
113
|
+
const collectFunctionNamesAtPath = (
|
|
114
|
+
items: Registry.RegistryItems,
|
|
115
|
+
groupPath: string,
|
|
116
|
+
): ReadonlyArray<string> =>
|
|
117
|
+
pipe(
|
|
118
|
+
String.split(groupPath, "."),
|
|
119
|
+
Array.reduce(Option.some<unknown>(items), (acc, segment) =>
|
|
120
|
+
acc.pipe(
|
|
121
|
+
Option.filter(Predicate.isRecord),
|
|
122
|
+
Option.flatMap((node) =>
|
|
123
|
+
segment in node ? Option.some(node[segment]) : Option.none(),
|
|
124
|
+
),
|
|
125
|
+
),
|
|
126
|
+
),
|
|
127
|
+
Option.filter(Predicate.isRecord),
|
|
128
|
+
Option.map(Record.toEntries),
|
|
129
|
+
Option.map(
|
|
130
|
+
Array.filterMap(([name, value]) =>
|
|
131
|
+
isFunctionShaped(value) ? Option.some(name) : Option.none(),
|
|
132
|
+
),
|
|
133
|
+
),
|
|
134
|
+
Option.getOrElse((): ReadonlyArray<string> => []),
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
const findUnfinalizedGroupImpl = <S>(
|
|
138
|
+
context: Context.Context<S>,
|
|
139
|
+
): Option.Option<AnyUnfinalized> =>
|
|
140
|
+
Array.findFirst(context.unsafeMap.values(), isUnfinalizedGroupImpl);
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Mark a `GroupImpl` layer as fully implemented. The parameter type defaults
|
|
144
|
+
* `RIn = never`, so passing a layer that still requires any `FunctionImpl`
|
|
145
|
+
* service produces a type error at the impl author's site. The codegen
|
|
146
|
+
* boundary requires the resulting `"Finalized"` brand, so omitting this call
|
|
147
|
+
* is also rejected downstream.
|
|
148
|
+
*
|
|
149
|
+
* As a side effect of finalization, the names of every `FunctionImpl` that
|
|
150
|
+
* registered into this group's scope are snapshotted onto the produced
|
|
151
|
+
* service value's `registeredFunctionNames` field, so consumers can verify
|
|
152
|
+
* impl completeness against a `GroupSpec`'s expected functions without
|
|
153
|
+
* having to inspect the `Registry` themselves.
|
|
154
|
+
*/
|
|
155
|
+
export const finalize = <GroupPath_ extends string>(
|
|
156
|
+
group: Layer.Layer<GroupImpl<GroupPath_, "Unfinalized">>,
|
|
157
|
+
): Layer.Layer<GroupImpl<GroupPath_, "Finalized">> =>
|
|
158
|
+
Layer.flatMap(
|
|
159
|
+
group,
|
|
160
|
+
(context): Layer.Layer<GroupImpl<GroupPath_, "Finalized">> =>
|
|
161
|
+
findUnfinalizedGroupImpl(context).pipe(
|
|
162
|
+
Option.match({
|
|
163
|
+
onNone: () =>
|
|
164
|
+
Layer.die(
|
|
165
|
+
new Error(
|
|
166
|
+
"GroupImpl.finalize: no Unfinalized GroupImpl service was found in the layer's context.",
|
|
167
|
+
),
|
|
168
|
+
),
|
|
169
|
+
onSome: (unfinalized) => {
|
|
170
|
+
const groupPath = unfinalized.groupPath as GroupPath_;
|
|
171
|
+
return Layer.effect(
|
|
172
|
+
GroupImpl<GroupPath_, "Finalized">({
|
|
173
|
+
groupPath,
|
|
174
|
+
finalizationStatus: "Finalized",
|
|
175
|
+
}),
|
|
176
|
+
Effect.gen(function* () {
|
|
177
|
+
const registry = yield* Registry.Registry;
|
|
178
|
+
const items = yield* Ref.get(registry);
|
|
179
|
+
return {
|
|
180
|
+
[TypeId]: TypeId,
|
|
181
|
+
groupPath,
|
|
182
|
+
finalizationStatus: "Finalized" as const,
|
|
183
|
+
registeredFunctionNames: collectFunctionNamesAtPath(
|
|
184
|
+
items,
|
|
185
|
+
groupPath,
|
|
186
|
+
),
|
|
187
|
+
};
|
|
188
|
+
}),
|
|
189
|
+
);
|
|
190
|
+
},
|
|
191
|
+
}),
|
|
192
|
+
),
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
export type FromGroupSpec<Group extends GroupSpec.AnyWithProps> =
|
|
196
|
+
FunctionImpl.FromGroupSpec<Group>;
|
package/src/GroupPath.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type * as GroupSpec from "@confect/core/GroupSpec";
|
|
2
|
+
import type * as Spec from "@confect/core/Spec";
|
|
3
|
+
import { Array, Option, pipe, Record } from "effect";
|
|
4
|
+
|
|
5
|
+
const resolveGroupPathInGroup = (
|
|
6
|
+
group: GroupSpec.AnyWithProps,
|
|
7
|
+
target: GroupSpec.AnyWithProps,
|
|
8
|
+
pathSegments: ReadonlyArray<string>,
|
|
9
|
+
): Option.Option<string> =>
|
|
10
|
+
pipe(
|
|
11
|
+
Record.toEntries(group.groups),
|
|
12
|
+
Array.findFirst(([name, child]) =>
|
|
13
|
+
child === target
|
|
14
|
+
? Option.some(Array.join([...pathSegments, name], "."))
|
|
15
|
+
: resolveGroupPathInGroup(child, target, [...pathSegments, name]),
|
|
16
|
+
),
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const resolveGroupPath = (
|
|
20
|
+
spec: Spec.AnyWithProps,
|
|
21
|
+
target: GroupSpec.AnyWithProps,
|
|
22
|
+
): Option.Option<string> =>
|
|
23
|
+
pipe(
|
|
24
|
+
Record.toEntries(spec.groups),
|
|
25
|
+
Array.findFirst(([name, group]) =>
|
|
26
|
+
group === target
|
|
27
|
+
? Option.some(name)
|
|
28
|
+
: resolveGroupPathInGroup(group, target, [name]),
|
|
29
|
+
),
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
export const resolveGroupPathUnsafe = (
|
|
33
|
+
spec: Spec.AnyWithProps,
|
|
34
|
+
target: GroupSpec.AnyWithProps,
|
|
35
|
+
): string =>
|
|
36
|
+
resolveGroupPath(spec, target).pipe(
|
|
37
|
+
Option.getOrThrowWith(
|
|
38
|
+
() =>
|
|
39
|
+
new Error(
|
|
40
|
+
"Could not resolve group path for the provided GroupSpec. Ensure the spec is part of the assembled API spec tree.",
|
|
41
|
+
),
|
|
42
|
+
),
|
|
43
|
+
);
|