@gaganref/confect-core 10.3.1-fork.65 → 10.3.1-fork.67

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/dist/App.d.ts CHANGED
@@ -31,11 +31,7 @@ export type Bindings<E extends EnvDefinition> = {
31
31
  readonly [K in Exclude<keyof E, RequiredKeys<E>>]?: Slot<E[K]>;
32
32
  };
33
33
  type HttpOptions = {
34
- readonly httpPrefix?: never;
35
- readonly api?: never;
36
- } | {
37
- readonly httpPrefix: HttpPrefix;
38
- readonly api?: Api;
34
+ readonly httpPrefix?: HttpPrefix;
39
35
  };
40
36
  export type Options<D extends Definition> = HttpOptions & {
41
37
  /**
@@ -50,7 +46,7 @@ export type Options<D extends Definition> = HttpOptions & {
50
46
  readonly env: Bindings<EnvOf<D>>;
51
47
  });
52
48
  type Exact<D extends Definition, O> = {
53
- readonly [K in Exclude<keyof O, "env" | "httpPrefix" | "api" | "testing">]: never;
49
+ readonly [K in Exclude<keyof O, "env" | "httpPrefix" | "testing">]: never;
54
50
  } & (O extends {
55
51
  readonly env: infer B;
56
52
  } ? {
@@ -61,7 +57,6 @@ type Exact<D extends Definition, O> = {
61
57
  export interface MountData {
62
58
  readonly definition: Definition;
63
59
  readonly httpPrefix: HttpPrefix | undefined;
64
- readonly api: Api | undefined;
65
60
  readonly env: Readonly<Record<string, string | Env.AnyEntry | undefined>>;
66
61
  readonly testing: string | undefined;
67
62
  }
@@ -84,7 +79,7 @@ export type AnyMount = Mount<Definition, unknown>;
84
79
  * official or Confect-authored. `env` is typed against the component's own
85
80
  * `defineComponent({ env })` declaration, so a missing required binding, an
86
81
  * optional entry in a required slot, a wrong literal and an unknown slot fail
87
- * to typecheck. `api` is the component's `HttpApi`, for route checks.
82
+ * to typecheck.
88
83
  */
89
84
  export declare function mount<const D extends Definition>(definition: D & ([RequiredKeys<EnvOf<D>>] extends [never] ? unknown : "App.mount: this component declares required env; pass { env }")): Mount<D, {}>;
90
85
  export declare function mount<const D extends Definition, const O extends Options<D>>(definition: D, options: O & Exact<NoInfer<D>, NoInfer<O>>): Mount<D, O>;
package/dist/App.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../src/App.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../src/App.ts"],"names":[],"mappings":"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"}
package/dist/App.js CHANGED
@@ -19,7 +19,6 @@ function mount(definition, options) {
19
19
  },
20
20
  definition,
21
21
  httpPrefix: options?.httpPrefix,
22
- api: options?.api,
23
22
  env: options?.env ?? {},
24
23
  testing: options?.testing
25
24
  };
@@ -61,7 +60,6 @@ const mounts = (app) => Object.entries(app.mounts).map(([name, installed]) => ({
61
60
  name,
62
61
  definition: installed.definition,
63
62
  httpPrefix: installed.httpPrefix,
64
- api: installed.api,
65
63
  env: installed.env,
66
64
  testing: installed.testing
67
65
  }));
package/dist/App.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"App.js","names":[],"sources":["../src/App.ts"],"sourcesContent":["import type { ComponentDefinition, EnvDefinition } from \"convex/server\";\nimport type { Infer, Validator } from \"convex/values\";\nimport type * as HttpApi from \"effect/http-api/HttpApi\";\nimport * as Predicate from \"effect/Predicate\";\nimport type * as Env from \"./Env.js\";\nimport type * as MiddlewareSpec from \"./MiddlewareSpec.js\";\n\nconst TypeId = \"~@confect/core/App\";\nconst MountTypeId = \"~@confect/core/App/Mount\";\n\n/**\n * The default export of a Convex component's `convex.config` module.\n */\nexport type Definition = ComponentDefinition<any, any>;\n\nexport type HttpPrefix = `/${string}`;\n\n/**\n * Any `HttpApi`, with its identifier and groups erased.\n */\nexport type Api = HttpApi.HttpApi<string, any>;\n\ntype EnvOf<D extends Definition> = D[\"__env\"];\n\ntype IsOptional<V> = V extends Validator<any, \"optional\", any> ? true : false;\n\ntype RequiredKeys<E extends EnvDefinition> = {\n [K in keyof E]: IsOptional<E[K]> extends true ? never : K;\n}[keyof E];\n\ntype SlotValue<V extends Validator<any, any, any>> = Extract<Infer<V>, string>;\n\n/**\n * What one component env slot accepts: a constant, or an entry whose Convex\n * value fits. A required slot takes only a required entry.\n */\ntype Slot<V extends Validator<any, any, any>> =\n IsOptional<V> extends true\n ? SlotValue<V> | undefined | Env.Entry<string, any, SlotValue<V>, boolean>\n : SlotValue<V> | Env.Entry<string, any, SlotValue<V>, false>;\n\nexport type Bindings<E extends EnvDefinition> = {\n readonly [K in RequiredKeys<E>]: Slot<E[K]>;\n} & {\n readonly [K in Exclude<keyof E, RequiredKeys<E>>]?: Slot<E[K]>;\n};\n\ntype HttpOptions =\n | { readonly httpPrefix?: never; readonly api?: never }\n | { readonly httpPrefix: HttpPrefix; readonly api?: Api };\n\nexport type Options<D extends Definition> = HttpOptions & {\n /**\n * The package specifier of the module whose `register(t, name)` the generated\n * test registry calls for this mount, in place of the component package's own\n * `<package>/test`. The kit registers the mount's children.\n */\n readonly testing?: string;\n} & ([RequiredKeys<EnvOf<D>>] extends [never]\n ? { readonly env?: Bindings<EnvOf<D>> }\n : { readonly env: Bindings<EnvOf<D>> });\n\ntype Exact<D extends Definition, O> = {\n readonly [\n K in Exclude<keyof O, \"env\" | \"httpPrefix\" | \"api\" | \"testing\">\n ]: never;\n} & (O extends { readonly env: infer B }\n ? {\n readonly env: { readonly [K in Exclude<keyof B, keyof EnvOf<D>>]: never };\n }\n : unknown);\n\nexport interface MountData {\n readonly definition: Definition;\n readonly httpPrefix: HttpPrefix | undefined;\n readonly api: Api | undefined;\n readonly env: Readonly<Record<string, string | Env.AnyEntry | undefined>>;\n readonly testing: string | undefined;\n}\n\n/**\n * A mounted Convex component. `O` keeps the options as written, so {@link make}\n * can see which backends the bound entries come from.\n */\nexport interface Mount<out D extends Definition, out O> extends MountData {\n readonly [MountTypeId]: { readonly definition: D; readonly options: O };\n readonly httpPrefix: O extends {\n readonly httpPrefix: infer P extends HttpPrefix;\n }\n ? P\n : undefined;\n}\n\nexport type AnyMount = Mount<Definition, unknown>;\n\n/**\n * Mount a Convex component: the default export of its `convex.config` module,\n * official or Confect-authored. `env` is typed against the component's own\n * `defineComponent({ env })` declaration, so a missing required binding, an\n * optional entry in a required slot, a wrong literal and an unknown slot fail\n * to typecheck. `api` is the component's `HttpApi`, for route checks.\n */\nexport function mount<const D extends Definition>(\n definition: D &\n ([RequiredKeys<EnvOf<D>>] extends [never]\n ? unknown\n : \"App.mount: this component declares required env; pass { env }\"),\n): Mount<D, {}>;\nexport function mount<const D extends Definition, const O extends Options<D>>(\n definition: D,\n options: O & Exact<NoInfer<D>, NoInfer<O>>,\n): Mount<D, O>;\nexport function mount(\n definition: Definition,\n options?: {\n readonly httpPrefix?: HttpPrefix;\n readonly api?: Api;\n readonly env?: MountData[\"env\"];\n readonly testing?: string;\n },\n): AnyMount {\n return {\n [MountTypeId]: { definition, options },\n definition,\n httpPrefix: options?.httpPrefix,\n api: options?.api,\n env: options?.env ?? {},\n testing: options?.testing,\n // The overloads above carry the precise types; this body serves both.\n } as AnyMount;\n}\n\ntype OwnerOf<V> = V extends Env.Entry<infer N, any, any, any> ? N : never;\n\ntype Owners<M> =\n M extends Mount<Definition, infer O>\n ? O extends { readonly env: infer B }\n ? { [K in keyof B]: OwnerOf<B[K]> }[keyof B]\n : never\n : never;\n\ntype OwnedBy<N extends string, M> = {\n readonly [K in keyof M]: [Exclude<Owners<M[K]>, N>] extends [never]\n ? unknown\n : { readonly foreignEnvBackend: Exclude<Owners<M[K]>, N> };\n};\n\nexport type Kind = \"app\" | \"component\";\n\nexport interface App<\n E extends Env.Any,\n M extends Readonly<Record<string, AnyMount>>,\n K extends Kind = Kind,\n> {\n readonly [TypeId]: typeof TypeId;\n readonly kind: K;\n readonly env: E;\n readonly mounts: M;\n readonly requiresMiddleware: ReadonlyArray<MiddlewareSpec.AnyMiddlewareSpec>;\n}\n\nexport type Any = App<Env.Any, Readonly<Record<string, AnyMount>>>;\n\n/**\n * Declare a backend, in `confect/app.ts`: its env and its mounted Convex\n * components by name. Set `kind: \"component\"` when declaring a component; the\n * default is `\"app\"`. Codegen rejects a kind that differs from its target.\n * Codegen writes `convex/convex.config.ts` from it. A mount that binds another\n * backend's env entry fails to typecheck.\n *\n * ```ts\n * export default App.make({\n * env,\n * mounts: {\n * email: App.mount(email, {\n * httpPrefix: \"/email\",\n * env: { FROM: env.EMAIL_FROM, KEY: env.RESEND_API_KEY },\n * }),\n * importsPool: App.mount(workpool),\n * },\n * });\n * ```\n */\nexport const make = <\n const E extends Env.Any,\n const M extends Readonly<Record<string, AnyMount>> = {},\n const K extends Kind = \"app\",\n>(\n options: {\n readonly env: E;\n readonly requiresMiddleware?: ReadonlyArray<MiddlewareSpec.AnyMiddlewareSpec>;\n readonly mounts?: M & OwnedBy<NoInfer<Env.Name<E>>, NoInfer<M>>;\n } & ([K] extends [\"app\"] ? { readonly kind?: K } : { readonly kind: K }),\n): App<E, M, K> => ({\n [TypeId]: TypeId,\n kind: options.kind ?? (\"app\" as K),\n env: options.env,\n mounts: options.mounts ?? ({} as M),\n requiresMiddleware: options.requiresMiddleware ?? [],\n});\n\nexport const isApp = (u: unknown): u is Any =>\n Predicate.hasProperty(u, TypeId) &&\n u[TypeId] === TypeId &&\n Predicate.hasProperty(u, \"kind\") &&\n (u.kind === \"app\" || u.kind === \"component\");\n\nexport const isMount = (u: unknown): u is AnyMount =>\n Predicate.hasProperty(u, MountTypeId);\n\nexport const env = <A extends Any>(app: A): A[\"env\"] => app.env;\n\n/**\n * Every mount with its name, in declaration order.\n */\nexport const mounts = (\n app: Any,\n): ReadonlyArray<MountData & { readonly name: string }> =>\n Object.entries(app.mounts).map(([name, installed]) => ({\n name,\n definition: installed.definition,\n httpPrefix: installed.httpPrefix,\n api: installed.api,\n env: installed.env,\n testing: installed.testing,\n }));\n"],"mappings":";;;;;;;;;;;AAOA,MAAM,SAAS;AACf,MAAM,cAAc;AAwGpB,SAAgB,MACd,YACA,SAMU;CACV,OAAO;GACJ,cAAc;GAAE;GAAY;EAAQ;EACrC;EACA,YAAY,SAAS;EACrB,KAAK,SAAS;EACd,KAAK,SAAS,OAAO,CAAC;EACtB,SAAS,SAAS;CAEpB;AACF;;;;;;;;;;;;;;;;;;;;;AAqDA,MAAa,QAKX,aAKkB;EACjB,SAAS;CACV,MAAM,QAAQ,QAAS;CACvB,KAAK,QAAQ;CACb,QAAQ,QAAQ,UAAW,CAAC;CAC5B,oBAAoB,QAAQ,sBAAsB,CAAC;AACrD;AAEA,MAAa,SAAS,MACpB,UAAU,YAAY,GAAG,MAAM,KAC/B,EAAE,YAAY,UACd,UAAU,YAAY,GAAG,MAAM,MAC9B,EAAE,SAAS,SAAS,EAAE,SAAS;AAElC,MAAa,WAAW,MACtB,UAAU,YAAY,GAAG,WAAW;AAEtC,MAAa,OAAsB,QAAqB,IAAI;;;;AAK5D,MAAa,UACX,QAEA,OAAO,QAAQ,IAAI,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,gBAAgB;CACrD;CACA,YAAY,UAAU;CACtB,YAAY,UAAU;CACtB,KAAK,UAAU;CACf,KAAK,UAAU;CACf,SAAS,UAAU;AACrB,EAAE"}
1
+ {"version":3,"file":"App.js","names":[],"sources":["../src/App.ts"],"sourcesContent":["import type { ComponentDefinition, EnvDefinition } from \"convex/server\";\nimport type { Infer, Validator } from \"convex/values\";\nimport type * as HttpApi from \"effect/http-api/HttpApi\";\nimport * as Predicate from \"effect/Predicate\";\nimport type * as Env from \"./Env.js\";\nimport type * as MiddlewareSpec from \"./MiddlewareSpec.js\";\n\nconst TypeId = \"~@confect/core/App\";\nconst MountTypeId = \"~@confect/core/App/Mount\";\n\n/**\n * The default export of a Convex component's `convex.config` module.\n */\nexport type Definition = ComponentDefinition<any, any>;\n\nexport type HttpPrefix = `/${string}`;\n\n/**\n * Any `HttpApi`, with its identifier and groups erased.\n */\nexport type Api = HttpApi.HttpApi<string, any>;\n\ntype EnvOf<D extends Definition> = D[\"__env\"];\n\ntype IsOptional<V> = V extends Validator<any, \"optional\", any> ? true : false;\n\ntype RequiredKeys<E extends EnvDefinition> = {\n [K in keyof E]: IsOptional<E[K]> extends true ? never : K;\n}[keyof E];\n\ntype SlotValue<V extends Validator<any, any, any>> = Extract<Infer<V>, string>;\n\n/**\n * What one component env slot accepts: a constant, or an entry whose Convex\n * value fits. A required slot takes only a required entry.\n */\ntype Slot<V extends Validator<any, any, any>> =\n IsOptional<V> extends true\n ? SlotValue<V> | undefined | Env.Entry<string, any, SlotValue<V>, boolean>\n : SlotValue<V> | Env.Entry<string, any, SlotValue<V>, false>;\n\nexport type Bindings<E extends EnvDefinition> = {\n readonly [K in RequiredKeys<E>]: Slot<E[K]>;\n} & {\n readonly [K in Exclude<keyof E, RequiredKeys<E>>]?: Slot<E[K]>;\n};\n\ntype HttpOptions = { readonly httpPrefix?: HttpPrefix };\n\nexport type Options<D extends Definition> = HttpOptions & {\n /**\n * The package specifier of the module whose `register(t, name)` the generated\n * test registry calls for this mount, in place of the component package's own\n * `<package>/test`. The kit registers the mount's children.\n */\n readonly testing?: string;\n} & ([RequiredKeys<EnvOf<D>>] extends [never]\n ? { readonly env?: Bindings<EnvOf<D>> }\n : { readonly env: Bindings<EnvOf<D>> });\n\ntype Exact<D extends Definition, O> = {\n readonly [K in Exclude<keyof O, \"env\" | \"httpPrefix\" | \"testing\">]: never;\n} & (O extends { readonly env: infer B }\n ? {\n readonly env: { readonly [K in Exclude<keyof B, keyof EnvOf<D>>]: never };\n }\n : unknown);\n\nexport interface MountData {\n readonly definition: Definition;\n readonly httpPrefix: HttpPrefix | undefined;\n readonly env: Readonly<Record<string, string | Env.AnyEntry | undefined>>;\n readonly testing: string | undefined;\n}\n\n/**\n * A mounted Convex component. `O` keeps the options as written, so {@link make}\n * can see which backends the bound entries come from.\n */\nexport interface Mount<out D extends Definition, out O> extends MountData {\n readonly [MountTypeId]: { readonly definition: D; readonly options: O };\n readonly httpPrefix: O extends {\n readonly httpPrefix: infer P extends HttpPrefix;\n }\n ? P\n : undefined;\n}\n\nexport type AnyMount = Mount<Definition, unknown>;\n\n/**\n * Mount a Convex component: the default export of its `convex.config` module,\n * official or Confect-authored. `env` is typed against the component's own\n * `defineComponent({ env })` declaration, so a missing required binding, an\n * optional entry in a required slot, a wrong literal and an unknown slot fail\n * to typecheck.\n */\nexport function mount<const D extends Definition>(\n definition: D &\n ([RequiredKeys<EnvOf<D>>] extends [never]\n ? unknown\n : \"App.mount: this component declares required env; pass { env }\"),\n): Mount<D, {}>;\nexport function mount<const D extends Definition, const O extends Options<D>>(\n definition: D,\n options: O & Exact<NoInfer<D>, NoInfer<O>>,\n): Mount<D, O>;\nexport function mount(\n definition: Definition,\n options?: {\n readonly httpPrefix?: HttpPrefix;\n readonly env?: MountData[\"env\"];\n readonly testing?: string;\n },\n): AnyMount {\n return {\n [MountTypeId]: { definition, options },\n definition,\n httpPrefix: options?.httpPrefix,\n env: options?.env ?? {},\n testing: options?.testing,\n // The overloads above carry the precise types; this body serves both.\n } as AnyMount;\n}\n\ntype OwnerOf<V> = V extends Env.Entry<infer N, any, any, any> ? N : never;\n\ntype Owners<M> =\n M extends Mount<Definition, infer O>\n ? O extends { readonly env: infer B }\n ? { [K in keyof B]: OwnerOf<B[K]> }[keyof B]\n : never\n : never;\n\ntype OwnedBy<N extends string, M> = {\n readonly [K in keyof M]: [Exclude<Owners<M[K]>, N>] extends [never]\n ? unknown\n : { readonly foreignEnvBackend: Exclude<Owners<M[K]>, N> };\n};\n\nexport type Kind = \"app\" | \"component\";\n\nexport interface App<\n E extends Env.Any,\n M extends Readonly<Record<string, AnyMount>>,\n K extends Kind = Kind,\n> {\n readonly [TypeId]: typeof TypeId;\n readonly kind: K;\n readonly env: E;\n readonly mounts: M;\n readonly requiresMiddleware: ReadonlyArray<MiddlewareSpec.AnyMiddlewareSpec>;\n}\n\nexport type Any = App<Env.Any, Readonly<Record<string, AnyMount>>>;\n\n/**\n * Declare a backend, in `confect/app.ts`: its env and its mounted Convex\n * components by name. Set `kind: \"component\"` when declaring a component; the\n * default is `\"app\"`. Codegen rejects a kind that differs from its target.\n * Codegen writes `convex/convex.config.ts` from it. A mount that binds another\n * backend's env entry fails to typecheck.\n *\n * ```ts\n * export default App.make({\n * env,\n * mounts: {\n * email: App.mount(email, {\n * httpPrefix: \"/email\",\n * env: { FROM: env.EMAIL_FROM, KEY: env.RESEND_API_KEY },\n * }),\n * importsPool: App.mount(workpool),\n * },\n * });\n * ```\n */\nexport const make = <\n const E extends Env.Any,\n const M extends Readonly<Record<string, AnyMount>> = {},\n const K extends Kind = \"app\",\n>(\n options: {\n readonly env: E;\n readonly requiresMiddleware?: ReadonlyArray<MiddlewareSpec.AnyMiddlewareSpec>;\n readonly mounts?: M & OwnedBy<NoInfer<Env.Name<E>>, NoInfer<M>>;\n } & ([K] extends [\"app\"] ? { readonly kind?: K } : { readonly kind: K }),\n): App<E, M, K> => ({\n [TypeId]: TypeId,\n kind: options.kind ?? (\"app\" as K),\n env: options.env,\n mounts: options.mounts ?? ({} as M),\n requiresMiddleware: options.requiresMiddleware ?? [],\n});\n\nexport const isApp = (u: unknown): u is Any =>\n Predicate.hasProperty(u, TypeId) &&\n u[TypeId] === TypeId &&\n Predicate.hasProperty(u, \"kind\") &&\n (u.kind === \"app\" || u.kind === \"component\");\n\nexport const isMount = (u: unknown): u is AnyMount =>\n Predicate.hasProperty(u, MountTypeId);\n\nexport const env = <A extends Any>(app: A): A[\"env\"] => app.env;\n\n/**\n * Every mount with its name, in declaration order.\n */\nexport const mounts = (\n app: Any,\n): ReadonlyArray<MountData & { readonly name: string }> =>\n Object.entries(app.mounts).map(([name, installed]) => ({\n name,\n definition: installed.definition,\n httpPrefix: installed.httpPrefix,\n env: installed.env,\n testing: installed.testing,\n }));\n"],"mappings":";;;;;;;;;;;AAOA,MAAM,SAAS;AACf,MAAM,cAAc;AAmGpB,SAAgB,MACd,YACA,SAKU;CACV,OAAO;GACJ,cAAc;GAAE;GAAY;EAAQ;EACrC;EACA,YAAY,SAAS;EACrB,KAAK,SAAS,OAAO,CAAC;EACtB,SAAS,SAAS;CAEpB;AACF;;;;;;;;;;;;;;;;;;;;;AAqDA,MAAa,QAKX,aAKkB;EACjB,SAAS;CACV,MAAM,QAAQ,QAAS;CACvB,KAAK,QAAQ;CACb,QAAQ,QAAQ,UAAW,CAAC;CAC5B,oBAAoB,QAAQ,sBAAsB,CAAC;AACrD;AAEA,MAAa,SAAS,MACpB,UAAU,YAAY,GAAG,MAAM,KAC/B,EAAE,YAAY,UACd,UAAU,YAAY,GAAG,MAAM,MAC9B,EAAE,SAAS,SAAS,EAAE,SAAS;AAElC,MAAa,WAAW,MACtB,UAAU,YAAY,GAAG,WAAW;AAEtC,MAAa,OAAsB,QAAqB,IAAI;;;;AAK5D,MAAa,UACX,QAEA,OAAO,QAAQ,IAAI,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,gBAAgB;CACrD;CACA,YAAY,UAAU;CACtB,YAAY,UAAU;CACtB,KAAK,UAAU;CACf,SAAS,UAAU;AACrB,EAAE"}
package/dist/Http.d.ts CHANGED
@@ -42,9 +42,6 @@ export type Owner = {
42
42
  readonly kind: "app";
43
43
  } | {
44
44
  readonly kind: "docs";
45
- } | {
46
- readonly kind: "mount";
47
- readonly mount: string;
48
45
  };
49
46
  export interface Route {
50
47
  readonly method: string;
@@ -90,11 +87,10 @@ export declare class OverlappingMountPrefixes extends OverlappingMountPrefixes_b
90
87
  }
91
88
  export type RouteError = RouteUnderMountPrefix | DuplicateRoute | OverlappingMountPrefixes;
92
89
  /**
93
- * Every HTTP route the backend serves: the app's api, its docs page and each
94
- * mount's api under its prefix. Fails when an app route or the docs page is at
95
- * or under a mount's prefix (Convex accepts that and lets the app route
96
- * silently shadow the component's), when two routes share a method and path, or
97
- * when two mount prefixes overlap.
90
+ * The backend's own HTTP routes and docs page. Fails when a route is at or
91
+ * under a mount's prefix (Convex accepts that and lets the app route silently
92
+ * shadow the component's), when two routes share a method and path, or when two
93
+ * mount prefixes overlap.
98
94
  */
99
95
  export declare const routes: (app: App.Any, http?: Any) => Result.Result<ReadonlyArray<Route>, RouteError>;
100
96
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"Http.d.ts","sourceRoot":"","sources":["../src/Http.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Http.d.ts","sourceRoot":"","sources":["../src/Http.ts"],"names":[],"mappings":"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"}
package/dist/Http.js CHANGED
@@ -47,7 +47,7 @@ var RouteUnderMountPrefix = class extends Data.TaggedError("RouteUnderMountPrefi
47
47
  };
48
48
  var DuplicateRoute = class extends Data.TaggedError("DuplicateRoute") {
49
49
  get message() {
50
- return `${this.method} ${this.path} is declared twice (${ownerLabel(this.first)} and ${ownerLabel(this.second)}).`;
50
+ return `${this.method} ${this.path} is declared twice (${this.first.kind} and ${this.second.kind}).`;
51
51
  }
52
52
  };
53
53
  var OverlappingMountPrefixes = class extends Data.TaggedError("OverlappingMountPrefixes") {
@@ -55,7 +55,6 @@ var OverlappingMountPrefixes = class extends Data.TaggedError("OverlappingMountP
55
55
  return `The mounts "${this.first.mount}" (${this.first.httpPrefix}) and "${this.second.mount}" (${this.second.httpPrefix}) have overlapping HTTP prefixes.`;
56
56
  }
57
57
  };
58
- const ownerLabel = (owner) => owner.kind === "mount" ? `mount "${owner.mount}"` : owner.kind;
59
58
  const trimSlash = (prefix) => prefix.length > 1 && prefix.endsWith("/") ? prefix.slice(0, -1) : prefix;
60
59
  const isUnder = (path, prefix) => prefix === "/" || path === prefix || path === `${prefix}/` || path.startsWith(`${prefix}/`);
61
60
  /**
@@ -69,8 +68,8 @@ const paramNames = (params) => {
69
68
  while (ast.encoding !== void 0) ast = ast.encoding[ast.encoding.length - 1].to;
70
69
  return SchemaAST.isObjects(ast) ? new Set(ast.propertySignatures.map(({ name }) => String(name))) : /* @__PURE__ */ new Set();
71
70
  };
72
- const apiRoutes = (api, prefix, owner) => Object.values(api.groups).flatMap((group) => Object.values(group.endpoints).map((endpoint) => {
73
- const path = prefix + endpoint.path;
71
+ const apiRoutes = (api, owner) => Object.values(api.groups).flatMap((group) => Object.values(group.endpoints).map((endpoint) => {
72
+ const path = endpoint.path;
74
73
  const declared = paramNames(endpoint.params);
75
74
  return {
76
75
  route: {
@@ -82,17 +81,15 @@ const apiRoutes = (api, prefix, owner) => Object.values(api.groups).flatMap((gro
82
81
  };
83
82
  }));
84
83
  /**
85
- * Every HTTP route the backend serves: the app's api, its docs page and each
86
- * mount's api under its prefix. Fails when an app route or the docs page is at
87
- * or under a mount's prefix (Convex accepts that and lets the app route
88
- * silently shadow the component's), when two routes share a method and path, or
89
- * when two mount prefixes overlap.
84
+ * The backend's own HTTP routes and docs page. Fails when a route is at or
85
+ * under a mount's prefix (Convex accepts that and lets the app route silently
86
+ * shadow the component's), when two routes share a method and path, or when two
87
+ * mount prefixes overlap.
90
88
  */
91
89
  const routes = (app, http) => {
92
- const mounts$1 = mounts(app).flatMap(({ name, httpPrefix, api }) => httpPrefix === void 0 ? [] : [{
90
+ const mounts$1 = mounts(app).flatMap(({ name, httpPrefix }) => httpPrefix === void 0 ? [] : [{
93
91
  name,
94
- httpPrefix: trimSlash(httpPrefix),
95
- api
92
+ httpPrefix: trimSlash(httpPrefix)
96
93
  }]);
97
94
  for (const [index, first] of mounts$1.entries()) for (const second of mounts$1.slice(index + 1)) if (isUnder(second.httpPrefix, first.httpPrefix) || isUnder(first.httpPrefix, second.httpPrefix)) return Result.fail(new OverlappingMountPrefixes({
98
95
  first: {
@@ -104,7 +101,7 @@ const routes = (app, http) => {
104
101
  httpPrefix: second.httpPrefix
105
102
  }
106
103
  }));
107
- const own = http === void 0 ? [] : [...apiRoutes(http.api, "", { kind: "app" }), ...http.docs === void 0 ? [] : [{
104
+ const own = http === void 0 ? [] : [...apiRoutes(http.api, { kind: "app" }), ...http.docs === void 0 ? [] : [{
108
105
  route: {
109
106
  method: "GET",
110
107
  path: http.docs,
@@ -121,12 +118,8 @@ const routes = (app, http) => {
121
118
  httpPrefix: mount.httpPrefix
122
119
  }));
123
120
  }
124
- const all = [...own, ...mounts$1.flatMap(({ name, httpPrefix, api }) => api === void 0 ? [] : apiRoutes(api, httpPrefix, {
125
- kind: "mount",
126
- mount: name
127
- }))];
128
121
  const seen = /* @__PURE__ */ new Map();
129
- for (const { route, key } of all) {
122
+ for (const { route, key } of own) {
130
123
  const previous = seen.get(key);
131
124
  if (previous !== void 0) return Result.fail(new DuplicateRoute({
132
125
  method: route.method,
@@ -136,7 +129,7 @@ const routes = (app, http) => {
136
129
  }));
137
130
  seen.set(key, route);
138
131
  }
139
- return Result.succeed(all.map(({ route }) => route));
132
+ return Result.succeed(own.map(({ route }) => route));
140
133
  };
141
134
  //#endregion
142
135
  export { DuplicateRoute, Http_exports, OverlappingMountPrefixes, RouteUnderMountPrefix, isHttp, make, routes };
package/dist/Http.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Http.js","names":["mounts","App.mounts"],"sources":["../src/Http.ts"],"sourcesContent":["import * as Data from \"effect/Data\";\nimport * as Layer from \"effect/Layer\";\nimport * as Predicate from \"effect/Predicate\";\nimport * as Result from \"effect/Result\";\nimport type * as Schema from \"effect/Schema\";\nimport * as SchemaAST from \"effect/SchemaAST\";\nimport type * as HttpApi from \"effect/http-api/HttpApi\";\nimport * as HttpApiBuilder from \"effect/http-api/HttpApiBuilder\";\nimport type * as HttpApiGroup from \"effect/http-api/HttpApiGroup\";\nimport { scalarDocs } from \"./internal/scalarDocs.js\";\nimport * as App from \"./App.js\";\n\nconst TypeId = \"~@confect/core/Http\";\n\n/**\n * A backend's HTTP declaration: the app's own `HttpApi`, its handlers, and an\n * optional Scalar docs path. `routes` is the layer the generated\n * `convex/http.ts` serves. Mounted components serve their own routes.\n *\n * It does not reference `confect/app.ts`: `http.ts` runs in every HTTP action,\n * and `app.ts` imports component definitions that only load in Convex's config\n * analysis. Codegen checks these routes against the app's mounts.\n */\nexport interface Http<Api extends App.Api, Routes extends Layer.Any> {\n readonly [TypeId]: typeof TypeId;\n readonly api: Api;\n readonly docs: `/${string}` | undefined;\n readonly routes: Routes;\n}\n\nexport type Any = Http<App.Api, Layer.Any>;\n\n/**\n * Declare the backend's HTTP API, in `confect/http.ts`. Every route is an\n * `HttpApi` endpoint. `docs` serves a Scalar page for the api at that path.\n *\n * ```ts\n * export default Http.make({\n * api: TenantApi,\n * handlers: TenantHandlers,\n * docs: \"/docs\",\n * });\n * ```\n */\nexport const make = <\n Id extends string,\n Groups extends HttpApiGroup.Constraint,\n R,\n>(options: {\n readonly api: HttpApi.HttpApi<Id, Groups>;\n readonly handlers: Layer.Layer<HttpApiGroup.ToService<Id, Groups>, never, R>;\n readonly docs?: `/${string}`;\n}) => {\n const api = HttpApiBuilder.layer(options.api).pipe(\n Layer.provide(options.handlers),\n );\n const routes =\n options.docs === undefined\n ? api\n : Layer.merge(api, scalarDocs(options.api, options.docs));\n const http: Http<HttpApi.HttpApi<Id, Groups>, typeof routes> = {\n [TypeId]: TypeId,\n api: options.api,\n docs: options.docs,\n routes,\n };\n return http;\n};\n\nexport const isHttp = (u: unknown): u is Any =>\n Predicate.hasProperty(u, TypeId) && u[TypeId] === TypeId;\n\nexport type Owner =\n | { readonly kind: \"app\" }\n | { readonly kind: \"docs\" }\n | { readonly kind: \"mount\"; readonly mount: string };\n\nexport interface Route {\n readonly method: string;\n readonly path: string;\n readonly owner: Owner;\n}\n\nexport class RouteUnderMountPrefix extends Data.TaggedError(\n \"RouteUnderMountPrefix\",\n)<{\n readonly method: string;\n readonly path: string;\n readonly mount: string;\n readonly httpPrefix: string;\n}> {\n override get message(): string {\n return `The app route ${this.method} ${this.path} is under the HTTP prefix ${this.httpPrefix} of the mount \"${this.mount}\". Convex would let it shadow the component's routes; move it or change the prefix.`;\n }\n}\n\nexport class DuplicateRoute extends Data.TaggedError(\"DuplicateRoute\")<{\n readonly method: string;\n readonly path: string;\n readonly first: Owner;\n readonly second: Owner;\n}> {\n override get message(): string {\n return `${this.method} ${this.path} is declared twice (${ownerLabel(this.first)} and ${ownerLabel(this.second)}).`;\n }\n}\n\nexport class OverlappingMountPrefixes extends Data.TaggedError(\n \"OverlappingMountPrefixes\",\n)<{\n readonly first: { readonly mount: string; readonly httpPrefix: string };\n readonly second: { readonly mount: string; readonly httpPrefix: string };\n}> {\n override get message(): string {\n return `The mounts \"${this.first.mount}\" (${this.first.httpPrefix}) and \"${this.second.mount}\" (${this.second.httpPrefix}) have overlapping HTTP prefixes.`;\n }\n}\n\nexport type RouteError =\n | RouteUnderMountPrefix\n | DuplicateRoute\n | OverlappingMountPrefixes;\n\nconst ownerLabel = (owner: Owner): string =>\n owner.kind === \"mount\" ? `mount \"${owner.mount}\"` : owner.kind;\n\nconst trimSlash = (prefix: string): string =>\n prefix.length > 1 && prefix.endsWith(\"/\") ? prefix.slice(0, -1) : prefix;\n\nconst isUnder = (path: string, prefix: string): boolean =>\n prefix === \"/\" ||\n path === prefix ||\n path === `${prefix}/` ||\n path.startsWith(`${prefix}/`);\n\n/**\n * The parameter names an endpoint declares. As in Effect's router, a colon\n * segment is a parameter only when its name is declared; otherwise it is\n * literal text.\n */\nconst paramNames = (params: Schema.Top | undefined): ReadonlySet<string> => {\n if (params === undefined) return new Set();\n let ast = params.ast;\n while (ast.encoding !== undefined) {\n ast = ast.encoding[ast.encoding.length - 1].to;\n }\n return SchemaAST.isObjects(ast)\n ? new Set(ast.propertySignatures.map(({ name }) => String(name)))\n : new Set();\n};\n\ninterface KeyedRoute {\n readonly route: Route;\n /**\n * Method and path with declared parameter names erased.\n */\n readonly key: string;\n}\n\nconst apiRoutes = (\n api: App.Api,\n prefix: string,\n owner: Owner,\n): ReadonlyArray<KeyedRoute> =>\n Object.values<HttpApiGroup.Top>(api.groups).flatMap((group) =>\n Object.values(group.endpoints).map((endpoint) => {\n const path = prefix + endpoint.path;\n const declared = paramNames(endpoint.params);\n return {\n route: { method: endpoint.method, path, owner },\n key: `${endpoint.method} ${path.replaceAll(/:(\\w+)/g, (param, name: string) => (declared.has(name) ? \":\" : param))}`,\n };\n }),\n );\n\n/**\n * Every HTTP route the backend serves: the app's api, its docs page and each\n * mount's api under its prefix. Fails when an app route or the docs page is at\n * or under a mount's prefix (Convex accepts that and lets the app route\n * silently shadow the component's), when two routes share a method and path, or\n * when two mount prefixes overlap.\n */\nexport const routes = (\n app: App.Any,\n http?: Any,\n): Result.Result<ReadonlyArray<Route>, RouteError> => {\n const mounts = App.mounts(app).flatMap(({ name, httpPrefix, api }) =>\n httpPrefix === undefined\n ? []\n : [{ name, httpPrefix: trimSlash(httpPrefix), api }],\n );\n\n for (const [index, first] of mounts.entries()) {\n for (const second of mounts.slice(index + 1)) {\n if (\n isUnder(second.httpPrefix, first.httpPrefix) ||\n isUnder(first.httpPrefix, second.httpPrefix)\n ) {\n return Result.fail(\n new OverlappingMountPrefixes({\n first: { mount: first.name, httpPrefix: first.httpPrefix },\n second: { mount: second.name, httpPrefix: second.httpPrefix },\n }),\n );\n }\n }\n }\n\n const own: ReadonlyArray<KeyedRoute> =\n http === undefined\n ? []\n : [\n ...apiRoutes(http.api, \"\", { kind: \"app\" }),\n ...(http.docs === undefined\n ? []\n : [\n {\n route: {\n method: \"GET\",\n path: http.docs,\n owner: { kind: \"docs\" } as const,\n },\n key: `GET ${http.docs}`,\n },\n ]),\n ];\n\n for (const { route } of own) {\n const mount = mounts.find(({ httpPrefix }) =>\n isUnder(route.path, httpPrefix),\n );\n if (mount !== undefined) {\n return Result.fail(\n new RouteUnderMountPrefix({\n method: route.method,\n path: route.path,\n mount: mount.name,\n httpPrefix: mount.httpPrefix,\n }),\n );\n }\n }\n\n const all = [\n ...own,\n ...mounts.flatMap(({ name, httpPrefix, api }) =>\n api === undefined\n ? []\n : apiRoutes(api, httpPrefix, { kind: \"mount\", mount: name }),\n ),\n ];\n const seen = new Map<string, Route>();\n for (const { route, key } of all) {\n const previous = seen.get(key);\n if (previous !== undefined) {\n return Result.fail(\n new DuplicateRoute({\n method: route.method,\n path: route.path,\n first: previous.owner,\n second: route.owner,\n }),\n );\n }\n seen.set(key, route);\n }\n return Result.succeed(all.map(({ route }) => route));\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAYA,MAAM,SAAS;;;;;;;;;;;;;AAgCf,MAAa,QAIX,YAII;CACJ,MAAM,MAAM,eAAe,MAAM,QAAQ,GAAG,CAAC,CAAC,KAC5C,MAAM,QAAQ,QAAQ,QAAQ,CAChC;CACA,MAAM,SACJ,QAAQ,SAAS,KAAA,IACb,MACA,MAAM,MAAM,KAAK,WAAW,QAAQ,KAAK,QAAQ,IAAI,CAAC;CAO5D,OAAO;GALJ,SAAS;EACV,KAAK,QAAQ;EACb,MAAM,QAAQ;EACd;CAEQ;AACZ;AAEA,MAAa,UAAU,MACrB,UAAU,YAAY,GAAG,MAAM,KAAK,EAAE,YAAY;AAapD,IAAa,wBAAb,cAA2C,KAAK,YAC9C,uBACF,CAAC,CAKE;CACD,IAAa,UAAkB;EAC7B,OAAO,iBAAiB,KAAK,OAAO,GAAG,KAAK,KAAK,4BAA4B,KAAK,WAAW,iBAAiB,KAAK,MAAM;CAC3H;AACF;AAEA,IAAa,iBAAb,cAAoC,KAAK,YAAY,gBAAgB,CAAC,CAKnE;CACD,IAAa,UAAkB;EAC7B,OAAO,GAAG,KAAK,OAAO,GAAG,KAAK,KAAK,sBAAsB,WAAW,KAAK,KAAK,EAAE,OAAO,WAAW,KAAK,MAAM,EAAE;CACjH;AACF;AAEA,IAAa,2BAAb,cAA8C,KAAK,YACjD,0BACF,CAAC,CAGE;CACD,IAAa,UAAkB;EAC7B,OAAO,eAAe,KAAK,MAAM,MAAM,KAAK,KAAK,MAAM,WAAW,SAAS,KAAK,OAAO,MAAM,KAAK,KAAK,OAAO,WAAW;CAC3H;AACF;AAOA,MAAM,cAAc,UAClB,MAAM,SAAS,UAAU,UAAU,MAAM,MAAM,KAAK,MAAM;AAE5D,MAAM,aAAa,WACjB,OAAO,SAAS,KAAK,OAAO,SAAS,GAAG,IAAI,OAAO,MAAM,GAAG,EAAE,IAAI;AAEpE,MAAM,WAAW,MAAc,WAC7B,WAAW,OACX,SAAS,UACT,SAAS,GAAG,OAAO,MACnB,KAAK,WAAW,GAAG,OAAO,EAAE;;;;;;AAO9B,MAAM,cAAc,WAAwD;CAC1E,IAAI,WAAW,KAAA,GAAW,uBAAO,IAAI,IAAI;CACzC,IAAI,MAAM,OAAO;CACjB,OAAO,IAAI,aAAa,KAAA,GACtB,MAAM,IAAI,SAAS,IAAI,SAAS,SAAS,EAAE,CAAC;CAE9C,OAAO,UAAU,UAAU,GAAG,IAC1B,IAAI,IAAI,IAAI,mBAAmB,KAAK,EAAE,WAAW,OAAO,IAAI,CAAC,CAAC,oBAC9D,IAAI,IAAI;AACd;AAUA,MAAM,aACJ,KACA,QACA,UAEA,OAAO,OAAyB,IAAI,MAAM,CAAC,CAAC,SAAS,UACnD,OAAO,OAAO,MAAM,SAAS,CAAC,CAAC,KAAK,aAAa;CAC/C,MAAM,OAAO,SAAS,SAAS;CAC/B,MAAM,WAAW,WAAW,SAAS,MAAM;CAC3C,OAAO;EACL,OAAO;GAAE,QAAQ,SAAS;GAAQ;GAAM;EAAM;EAC9C,KAAK,GAAG,SAAS,OAAO,GAAG,KAAK,WAAW,YAAY,OAAO,SAAkB,SAAS,IAAI,IAAI,IAAI,MAAM,KAAM;CACnH;AACF,CAAC,CACH;;;;;;;;AASF,MAAa,UACX,KACA,SACoD;CACpD,MAAMA,WAASC,OAAW,GAAG,CAAC,CAAC,SAAS,EAAE,MAAM,YAAY,UAC1D,eAAe,KAAA,IACX,CAAC,IACD,CAAC;EAAE;EAAM,YAAY,UAAU,UAAU;EAAG;CAAI,CAAC,CACvD;CAEA,KAAK,MAAM,CAAC,OAAO,UAAUD,SAAO,QAAQ,GAC1C,KAAK,MAAM,UAAUA,SAAO,MAAM,QAAQ,CAAC,GACzC,IACE,QAAQ,OAAO,YAAY,MAAM,UAAU,KAC3C,QAAQ,MAAM,YAAY,OAAO,UAAU,GAE3C,OAAO,OAAO,KACZ,IAAI,yBAAyB;EAC3B,OAAO;GAAE,OAAO,MAAM;GAAM,YAAY,MAAM;EAAW;EACzD,QAAQ;GAAE,OAAO,OAAO;GAAM,YAAY,OAAO;EAAW;CAC9D,CAAC,CACH;CAKN,MAAM,MACJ,SAAS,KAAA,IACL,CAAC,IACD,CACE,GAAG,UAAU,KAAK,KAAK,IAAI,EAAE,MAAM,MAAM,CAAC,GAC1C,GAAI,KAAK,SAAS,KAAA,IACd,CAAC,IACD,CACE;EACE,OAAO;GACL,QAAQ;GACR,MAAM,KAAK;GACX,OAAO,EAAE,MAAM,OAAO;EACxB;EACA,KAAK,OAAO,KAAK;CACnB,CACF,CACN;CAEN,KAAK,MAAM,EAAE,WAAW,KAAK;EAC3B,MAAM,QAAQA,SAAO,MAAM,EAAE,iBAC3B,QAAQ,MAAM,MAAM,UAAU,CAChC;EACA,IAAI,UAAU,KAAA,GACZ,OAAO,OAAO,KACZ,IAAI,sBAAsB;GACxB,QAAQ,MAAM;GACd,MAAM,MAAM;GACZ,OAAO,MAAM;GACb,YAAY,MAAM;EACpB,CAAC,CACH;CAEJ;CAEA,MAAM,MAAM,CACV,GAAG,KACH,GAAGA,SAAO,SAAS,EAAE,MAAM,YAAY,UACrC,QAAQ,KAAA,IACJ,CAAC,IACD,UAAU,KAAK,YAAY;EAAE,MAAM;EAAS,OAAO;CAAK,CAAC,CAC/D,CACF;CACA,MAAM,uBAAO,IAAI,IAAmB;CACpC,KAAK,MAAM,EAAE,OAAO,SAAS,KAAK;EAChC,MAAM,WAAW,KAAK,IAAI,GAAG;EAC7B,IAAI,aAAa,KAAA,GACf,OAAO,OAAO,KACZ,IAAI,eAAe;GACjB,QAAQ,MAAM;GACd,MAAM,MAAM;GACZ,OAAO,SAAS;GAChB,QAAQ,MAAM;EAChB,CAAC,CACH;EAEF,KAAK,IAAI,KAAK,KAAK;CACrB;CACA,OAAO,OAAO,QAAQ,IAAI,KAAK,EAAE,YAAY,KAAK,CAAC;AACrD"}
1
+ {"version":3,"file":"Http.js","names":["mounts","App.mounts"],"sources":["../src/Http.ts"],"sourcesContent":["import * as Data from \"effect/Data\";\nimport * as Layer from \"effect/Layer\";\nimport * as Predicate from \"effect/Predicate\";\nimport * as Result from \"effect/Result\";\nimport type * as Schema from \"effect/Schema\";\nimport * as SchemaAST from \"effect/SchemaAST\";\nimport type * as HttpApi from \"effect/http-api/HttpApi\";\nimport * as HttpApiBuilder from \"effect/http-api/HttpApiBuilder\";\nimport type * as HttpApiGroup from \"effect/http-api/HttpApiGroup\";\nimport { scalarDocs } from \"./internal/scalarDocs.js\";\nimport * as App from \"./App.js\";\n\nconst TypeId = \"~@confect/core/Http\";\n\n/**\n * A backend's HTTP declaration: the app's own `HttpApi`, its handlers, and an\n * optional Scalar docs path. `routes` is the layer the generated\n * `convex/http.ts` serves. Mounted components serve their own routes.\n *\n * It does not reference `confect/app.ts`: `http.ts` runs in every HTTP action,\n * and `app.ts` imports component definitions that only load in Convex's config\n * analysis. Codegen checks these routes against the app's mounts.\n */\nexport interface Http<Api extends App.Api, Routes extends Layer.Any> {\n readonly [TypeId]: typeof TypeId;\n readonly api: Api;\n readonly docs: `/${string}` | undefined;\n readonly routes: Routes;\n}\n\nexport type Any = Http<App.Api, Layer.Any>;\n\n/**\n * Declare the backend's HTTP API, in `confect/http.ts`. Every route is an\n * `HttpApi` endpoint. `docs` serves a Scalar page for the api at that path.\n *\n * ```ts\n * export default Http.make({\n * api: TenantApi,\n * handlers: TenantHandlers,\n * docs: \"/docs\",\n * });\n * ```\n */\nexport const make = <\n Id extends string,\n Groups extends HttpApiGroup.Constraint,\n R,\n>(options: {\n readonly api: HttpApi.HttpApi<Id, Groups>;\n readonly handlers: Layer.Layer<HttpApiGroup.ToService<Id, Groups>, never, R>;\n readonly docs?: `/${string}`;\n}) => {\n const api = HttpApiBuilder.layer(options.api).pipe(\n Layer.provide(options.handlers),\n );\n const routes =\n options.docs === undefined\n ? api\n : Layer.merge(api, scalarDocs(options.api, options.docs));\n const http: Http<HttpApi.HttpApi<Id, Groups>, typeof routes> = {\n [TypeId]: TypeId,\n api: options.api,\n docs: options.docs,\n routes,\n };\n return http;\n};\n\nexport const isHttp = (u: unknown): u is Any =>\n Predicate.hasProperty(u, TypeId) && u[TypeId] === TypeId;\n\nexport type Owner = { readonly kind: \"app\" } | { readonly kind: \"docs\" };\n\nexport interface Route {\n readonly method: string;\n readonly path: string;\n readonly owner: Owner;\n}\n\nexport class RouteUnderMountPrefix extends Data.TaggedError(\n \"RouteUnderMountPrefix\",\n)<{\n readonly method: string;\n readonly path: string;\n readonly mount: string;\n readonly httpPrefix: string;\n}> {\n override get message(): string {\n return `The app route ${this.method} ${this.path} is under the HTTP prefix ${this.httpPrefix} of the mount \"${this.mount}\". Convex would let it shadow the component's routes; move it or change the prefix.`;\n }\n}\n\nexport class DuplicateRoute extends Data.TaggedError(\"DuplicateRoute\")<{\n readonly method: string;\n readonly path: string;\n readonly first: Owner;\n readonly second: Owner;\n}> {\n override get message(): string {\n return `${this.method} ${this.path} is declared twice (${this.first.kind} and ${this.second.kind}).`;\n }\n}\n\nexport class OverlappingMountPrefixes extends Data.TaggedError(\n \"OverlappingMountPrefixes\",\n)<{\n readonly first: { readonly mount: string; readonly httpPrefix: string };\n readonly second: { readonly mount: string; readonly httpPrefix: string };\n}> {\n override get message(): string {\n return `The mounts \"${this.first.mount}\" (${this.first.httpPrefix}) and \"${this.second.mount}\" (${this.second.httpPrefix}) have overlapping HTTP prefixes.`;\n }\n}\n\nexport type RouteError =\n | RouteUnderMountPrefix\n | DuplicateRoute\n | OverlappingMountPrefixes;\n\nconst trimSlash = (prefix: string): string =>\n prefix.length > 1 && prefix.endsWith(\"/\") ? prefix.slice(0, -1) : prefix;\n\nconst isUnder = (path: string, prefix: string): boolean =>\n prefix === \"/\" ||\n path === prefix ||\n path === `${prefix}/` ||\n path.startsWith(`${prefix}/`);\n\n/**\n * The parameter names an endpoint declares. As in Effect's router, a colon\n * segment is a parameter only when its name is declared; otherwise it is\n * literal text.\n */\nconst paramNames = (params: Schema.Top | undefined): ReadonlySet<string> => {\n if (params === undefined) return new Set();\n let ast = params.ast;\n while (ast.encoding !== undefined) {\n ast = ast.encoding[ast.encoding.length - 1].to;\n }\n return SchemaAST.isObjects(ast)\n ? new Set(ast.propertySignatures.map(({ name }) => String(name)))\n : new Set();\n};\n\ninterface KeyedRoute {\n readonly route: Route;\n /**\n * Method and path with declared parameter names erased.\n */\n readonly key: string;\n}\n\nconst apiRoutes = (api: App.Api, owner: Owner): ReadonlyArray<KeyedRoute> =>\n Object.values<HttpApiGroup.Top>(api.groups).flatMap((group) =>\n Object.values(group.endpoints).map((endpoint) => {\n const path = endpoint.path;\n const declared = paramNames(endpoint.params);\n return {\n route: { method: endpoint.method, path, owner },\n key: `${endpoint.method} ${path.replaceAll(/:(\\w+)/g, (param, name: string) => (declared.has(name) ? \":\" : param))}`,\n };\n }),\n );\n\n/**\n * The backend's own HTTP routes and docs page. Fails when a route is at or\n * under a mount's prefix (Convex accepts that and lets the app route silently\n * shadow the component's), when two routes share a method and path, or when two\n * mount prefixes overlap.\n */\nexport const routes = (\n app: App.Any,\n http?: Any,\n): Result.Result<ReadonlyArray<Route>, RouteError> => {\n const mounts = App.mounts(app).flatMap(({ name, httpPrefix }) =>\n httpPrefix === undefined\n ? []\n : [{ name, httpPrefix: trimSlash(httpPrefix) }],\n );\n\n for (const [index, first] of mounts.entries()) {\n for (const second of mounts.slice(index + 1)) {\n if (\n isUnder(second.httpPrefix, first.httpPrefix) ||\n isUnder(first.httpPrefix, second.httpPrefix)\n ) {\n return Result.fail(\n new OverlappingMountPrefixes({\n first: { mount: first.name, httpPrefix: first.httpPrefix },\n second: { mount: second.name, httpPrefix: second.httpPrefix },\n }),\n );\n }\n }\n }\n\n const own: ReadonlyArray<KeyedRoute> =\n http === undefined\n ? []\n : [\n ...apiRoutes(http.api, { kind: \"app\" }),\n ...(http.docs === undefined\n ? []\n : [\n {\n route: {\n method: \"GET\",\n path: http.docs,\n owner: { kind: \"docs\" } as const,\n },\n key: `GET ${http.docs}`,\n },\n ]),\n ];\n\n for (const { route } of own) {\n const mount = mounts.find(({ httpPrefix }) =>\n isUnder(route.path, httpPrefix),\n );\n if (mount !== undefined) {\n return Result.fail(\n new RouteUnderMountPrefix({\n method: route.method,\n path: route.path,\n mount: mount.name,\n httpPrefix: mount.httpPrefix,\n }),\n );\n }\n }\n\n const seen = new Map<string, Route>();\n for (const { route, key } of own) {\n const previous = seen.get(key);\n if (previous !== undefined) {\n return Result.fail(\n new DuplicateRoute({\n method: route.method,\n path: route.path,\n first: previous.owner,\n second: route.owner,\n }),\n );\n }\n seen.set(key, route);\n }\n return Result.succeed(own.map(({ route }) => route));\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gaganref/confect-core",
3
- "version": "10.3.1-fork.65",
3
+ "version": "10.3.1-fork.67",
4
4
  "peerDependencies": {
5
5
  "convex": "^1.49.0",
6
6
  "effect": ">=4.0.0 <4.1.0"
package/src/App.ts CHANGED
@@ -45,9 +45,7 @@ export type Bindings<E extends EnvDefinition> = {
45
45
  readonly [K in Exclude<keyof E, RequiredKeys<E>>]?: Slot<E[K]>;
46
46
  };
47
47
 
48
- type HttpOptions =
49
- | { readonly httpPrefix?: never; readonly api?: never }
50
- | { readonly httpPrefix: HttpPrefix; readonly api?: Api };
48
+ type HttpOptions = { readonly httpPrefix?: HttpPrefix };
51
49
 
52
50
  export type Options<D extends Definition> = HttpOptions & {
53
51
  /**
@@ -61,9 +59,7 @@ export type Options<D extends Definition> = HttpOptions & {
61
59
  : { readonly env: Bindings<EnvOf<D>> });
62
60
 
63
61
  type Exact<D extends Definition, O> = {
64
- readonly [
65
- K in Exclude<keyof O, "env" | "httpPrefix" | "api" | "testing">
66
- ]: never;
62
+ readonly [K in Exclude<keyof O, "env" | "httpPrefix" | "testing">]: never;
67
63
  } & (O extends { readonly env: infer B }
68
64
  ? {
69
65
  readonly env: { readonly [K in Exclude<keyof B, keyof EnvOf<D>>]: never };
@@ -73,7 +69,6 @@ type Exact<D extends Definition, O> = {
73
69
  export interface MountData {
74
70
  readonly definition: Definition;
75
71
  readonly httpPrefix: HttpPrefix | undefined;
76
- readonly api: Api | undefined;
77
72
  readonly env: Readonly<Record<string, string | Env.AnyEntry | undefined>>;
78
73
  readonly testing: string | undefined;
79
74
  }
@@ -98,7 +93,7 @@ export type AnyMount = Mount<Definition, unknown>;
98
93
  * official or Confect-authored. `env` is typed against the component's own
99
94
  * `defineComponent({ env })` declaration, so a missing required binding, an
100
95
  * optional entry in a required slot, a wrong literal and an unknown slot fail
101
- * to typecheck. `api` is the component's `HttpApi`, for route checks.
96
+ * to typecheck.
102
97
  */
103
98
  export function mount<const D extends Definition>(
104
99
  definition: D &
@@ -114,7 +109,6 @@ export function mount(
114
109
  definition: Definition,
115
110
  options?: {
116
111
  readonly httpPrefix?: HttpPrefix;
117
- readonly api?: Api;
118
112
  readonly env?: MountData["env"];
119
113
  readonly testing?: string;
120
114
  },
@@ -123,7 +117,6 @@ export function mount(
123
117
  [MountTypeId]: { definition, options },
124
118
  definition,
125
119
  httpPrefix: options?.httpPrefix,
126
- api: options?.api,
127
120
  env: options?.env ?? {},
128
121
  testing: options?.testing,
129
122
  // The overloads above carry the precise types; this body serves both.
@@ -220,7 +213,6 @@ export const mounts = (
220
213
  name,
221
214
  definition: installed.definition,
222
215
  httpPrefix: installed.httpPrefix,
223
- api: installed.api,
224
216
  env: installed.env,
225
217
  testing: installed.testing,
226
218
  }));
package/src/Http.ts CHANGED
@@ -70,10 +70,7 @@ export const make = <
70
70
  export const isHttp = (u: unknown): u is Any =>
71
71
  Predicate.hasProperty(u, TypeId) && u[TypeId] === TypeId;
72
72
 
73
- export type Owner =
74
- | { readonly kind: "app" }
75
- | { readonly kind: "docs" }
76
- | { readonly kind: "mount"; readonly mount: string };
73
+ export type Owner = { readonly kind: "app" } | { readonly kind: "docs" };
77
74
 
78
75
  export interface Route {
79
76
  readonly method: string;
@@ -101,7 +98,7 @@ export class DuplicateRoute extends Data.TaggedError("DuplicateRoute")<{
101
98
  readonly second: Owner;
102
99
  }> {
103
100
  override get message(): string {
104
- return `${this.method} ${this.path} is declared twice (${ownerLabel(this.first)} and ${ownerLabel(this.second)}).`;
101
+ return `${this.method} ${this.path} is declared twice (${this.first.kind} and ${this.second.kind}).`;
105
102
  }
106
103
  }
107
104
 
@@ -121,9 +118,6 @@ export type RouteError =
121
118
  | DuplicateRoute
122
119
  | OverlappingMountPrefixes;
123
120
 
124
- const ownerLabel = (owner: Owner): string =>
125
- owner.kind === "mount" ? `mount "${owner.mount}"` : owner.kind;
126
-
127
121
  const trimSlash = (prefix: string): string =>
128
122
  prefix.length > 1 && prefix.endsWith("/") ? prefix.slice(0, -1) : prefix;
129
123
 
@@ -157,14 +151,10 @@ interface KeyedRoute {
157
151
  readonly key: string;
158
152
  }
159
153
 
160
- const apiRoutes = (
161
- api: App.Api,
162
- prefix: string,
163
- owner: Owner,
164
- ): ReadonlyArray<KeyedRoute> =>
154
+ const apiRoutes = (api: App.Api, owner: Owner): ReadonlyArray<KeyedRoute> =>
165
155
  Object.values<HttpApiGroup.Top>(api.groups).flatMap((group) =>
166
156
  Object.values(group.endpoints).map((endpoint) => {
167
- const path = prefix + endpoint.path;
157
+ const path = endpoint.path;
168
158
  const declared = paramNames(endpoint.params);
169
159
  return {
170
160
  route: { method: endpoint.method, path, owner },
@@ -174,20 +164,19 @@ const apiRoutes = (
174
164
  );
175
165
 
176
166
  /**
177
- * Every HTTP route the backend serves: the app's api, its docs page and each
178
- * mount's api under its prefix. Fails when an app route or the docs page is at
179
- * or under a mount's prefix (Convex accepts that and lets the app route
180
- * silently shadow the component's), when two routes share a method and path, or
181
- * when two mount prefixes overlap.
167
+ * The backend's own HTTP routes and docs page. Fails when a route is at or
168
+ * under a mount's prefix (Convex accepts that and lets the app route silently
169
+ * shadow the component's), when two routes share a method and path, or when two
170
+ * mount prefixes overlap.
182
171
  */
183
172
  export const routes = (
184
173
  app: App.Any,
185
174
  http?: Any,
186
175
  ): Result.Result<ReadonlyArray<Route>, RouteError> => {
187
- const mounts = App.mounts(app).flatMap(({ name, httpPrefix, api }) =>
176
+ const mounts = App.mounts(app).flatMap(({ name, httpPrefix }) =>
188
177
  httpPrefix === undefined
189
178
  ? []
190
- : [{ name, httpPrefix: trimSlash(httpPrefix), api }],
179
+ : [{ name, httpPrefix: trimSlash(httpPrefix) }],
191
180
  );
192
181
 
193
182
  for (const [index, first] of mounts.entries()) {
@@ -210,7 +199,7 @@ export const routes = (
210
199
  http === undefined
211
200
  ? []
212
201
  : [
213
- ...apiRoutes(http.api, "", { kind: "app" }),
202
+ ...apiRoutes(http.api, { kind: "app" }),
214
203
  ...(http.docs === undefined
215
204
  ? []
216
205
  : [
@@ -241,16 +230,8 @@ export const routes = (
241
230
  }
242
231
  }
243
232
 
244
- const all = [
245
- ...own,
246
- ...mounts.flatMap(({ name, httpPrefix, api }) =>
247
- api === undefined
248
- ? []
249
- : apiRoutes(api, httpPrefix, { kind: "mount", mount: name }),
250
- ),
251
- ];
252
233
  const seen = new Map<string, Route>();
253
- for (const { route, key } of all) {
234
+ for (const { route, key } of own) {
254
235
  const previous = seen.get(key);
255
236
  if (previous !== undefined) {
256
237
  return Result.fail(
@@ -264,5 +245,5 @@ export const routes = (
264
245
  }
265
246
  seen.set(key, route);
266
247
  }
267
- return Result.succeed(all.map(({ route }) => route));
248
+ return Result.succeed(own.map(({ route }) => route));
268
249
  };