@gaganref/confect-core 10.3.1-fork.8 → 10.3.1-fork.81
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/ActionCall.d.ts +18 -0
- package/dist/ActionCall.d.ts.map +1 -0
- package/dist/ActionCall.js +21 -0
- package/dist/ActionCall.js.map +1 -0
- package/dist/App.d.ts +30 -93
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +24 -38
- package/dist/App.js.map +1 -1
- package/dist/Auth.d.ts +33 -9
- package/dist/Auth.d.ts.map +1 -1
- package/dist/Auth.js +17 -2
- package/dist/Auth.js.map +1 -1
- package/dist/Callback.d.ts +7 -2
- package/dist/Callback.d.ts.map +1 -1
- package/dist/Callback.js +11 -6
- package/dist/Callback.js.map +1 -1
- package/dist/Component.d.ts +98 -2
- package/dist/Component.d.ts.map +1 -1
- package/dist/Component.js +44 -18
- package/dist/Component.js.map +1 -1
- package/dist/FunctionSpec.d.ts +365 -2
- package/dist/FunctionSpec.d.ts.map +1 -1
- package/dist/FunctionSpec.js +66 -3
- package/dist/FunctionSpec.js.map +1 -1
- package/dist/GenericId.js +2 -2
- package/dist/GroupSpec.js +1 -1
- package/dist/Http.d.ts +4 -8
- package/dist/Http.d.ts.map +1 -1
- package/dist/Http.js +15 -22
- package/dist/Http.js.map +1 -1
- package/dist/ManifestSection.d.ts +70 -0
- package/dist/ManifestSection.d.ts.map +1 -0
- package/dist/ManifestSection.js +7 -0
- package/dist/ManifestSection.js.map +1 -0
- package/dist/Mount.d.ts +200 -0
- package/dist/Mount.d.ts.map +1 -0
- package/dist/Mount.js +116 -0
- package/dist/Mount.js.map +1 -0
- package/dist/PaginationError.js +1 -1
- package/dist/Profile.d.ts +95 -0
- package/dist/Profile.d.ts.map +1 -0
- package/dist/Profile.js +15 -0
- package/dist/Profile.js.map +1 -0
- package/dist/Ref.d.ts +4 -3
- package/dist/Ref.d.ts.map +1 -1
- package/dist/Ref.js +13 -19
- package/dist/Ref.js.map +1 -1
- package/dist/RefInternal.d.ts +3 -0
- package/dist/RefInternal.d.ts.map +1 -0
- package/dist/RefInternal.js +16 -0
- package/dist/RefInternal.js.map +1 -0
- package/dist/SchemaToValidator.d.ts +11 -2
- package/dist/SchemaToValidator.d.ts.map +1 -1
- package/dist/SchemaToValidator.js +43 -14
- package/dist/SchemaToValidator.js.map +1 -1
- package/dist/SystemFields.js +3 -3
- package/dist/Table.d.ts +48 -9
- package/dist/Table.d.ts.map +1 -1
- package/dist/Table.js +41 -13
- package/dist/Table.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -6
- package/dist/internal/annotations.d.ts +2 -0
- package/dist/internal/annotations.d.ts.map +1 -0
- package/dist/internal/annotations.js +6 -0
- package/dist/internal/annotations.js.map +1 -0
- package/dist/internal/scalarDocs.d.ts +5 -0
- package/dist/internal/scalarDocs.d.ts.map +1 -0
- package/dist/internal/scalarDocs.js +43 -0
- package/dist/internal/scalarDocs.js.map +1 -0
- package/package.json +3 -3
- package/src/ActionCall.ts +25 -0
- package/src/App.ts +36 -136
- package/src/Auth.ts +54 -11
- package/src/Callback.ts +17 -4
- package/src/Component.ts +196 -11
- package/src/FunctionSpec.ts +566 -5
- package/src/Http.ts +15 -37
- package/src/ManifestSection.ts +78 -0
- package/src/Mount.ts +401 -0
- package/src/Profile.ts +141 -0
- package/src/Ref.ts +19 -26
- package/src/RefInternal.ts +26 -0
- package/src/SchemaToValidator.ts +47 -5
- package/src/Table.ts +157 -23
- package/src/index.ts +4 -0
- package/src/internal/annotations.ts +1 -0
- package/src/internal/scalarDocs.ts +72 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as HttpRouter from "effect/http/HttpRouter";
|
|
3
|
+
import * as HttpServerResponse from "effect/http/HttpServerResponse";
|
|
4
|
+
import * as OpenApi from "effect/http-api/OpenApi";
|
|
5
|
+
//#region src/internal/scalarDocs.ts
|
|
6
|
+
const escape = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
7
|
+
const escapeAttribute = (value) => escape(value).replaceAll("\"", """).replaceAll("'", "'");
|
|
8
|
+
const escapeJson = (value) => JSON.stringify(value).replaceAll("<", "\\u003c").replaceAll("\u2028", "\\u2028").replaceAll("\u2029", "\\u2029");
|
|
9
|
+
const scalarDocs = (api, path) => HttpRouter.use((router) => {
|
|
10
|
+
let response;
|
|
11
|
+
return router.add("GET", path, Effect.sync(() => {
|
|
12
|
+
if (response !== void 0) return response;
|
|
13
|
+
const spec = OpenApi.fromApi(api);
|
|
14
|
+
const description = (tag) => !spec.info.description ? "" : `<meta name="${tag}" content="${escapeAttribute(spec.info.description)}"/>`;
|
|
15
|
+
response = HttpServerResponse.html(`<!doctype html>
|
|
16
|
+
<html>
|
|
17
|
+
<head>
|
|
18
|
+
<meta charset="utf-8" />
|
|
19
|
+
<title>${escape(spec.info.title)}</title>
|
|
20
|
+
${description("description")}
|
|
21
|
+
${description("og:description")}
|
|
22
|
+
<meta
|
|
23
|
+
name="viewport"
|
|
24
|
+
content="width=device-width, initial-scale=1" />
|
|
25
|
+
</head>
|
|
26
|
+
<body>
|
|
27
|
+
<div id="api-reference-container"></div>
|
|
28
|
+
<script src="${escapeAttribute("https://cdn.jsdelivr.net/npm/@scalar/api-reference@latest/dist/browser/standalone.min.js")}" crossorigin><\/script>
|
|
29
|
+
<script>
|
|
30
|
+
window.Scalar.createApiReference(document.getElementById('api-reference-container'), {
|
|
31
|
+
...${escapeJson({ _integration: "html" })},
|
|
32
|
+
content: ${escapeJson(spec)}
|
|
33
|
+
})
|
|
34
|
+
<\/script>
|
|
35
|
+
</body>
|
|
36
|
+
</html>`);
|
|
37
|
+
return response;
|
|
38
|
+
}));
|
|
39
|
+
});
|
|
40
|
+
//#endregion
|
|
41
|
+
export { scalarDocs };
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=scalarDocs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scalarDocs.js","names":[],"sources":["../../src/internal/scalarDocs.ts"],"sourcesContent":["import * as Effect from \"effect/Effect\";\nimport * as HttpRouter from \"effect/http/HttpRouter\";\nimport * as HttpServerResponse from \"effect/http/HttpServerResponse\";\nimport type * as HttpApi from \"effect/http-api/HttpApi\";\nimport type * as HttpApiGroup from \"effect/http-api/HttpApiGroup\";\nimport * as OpenApi from \"effect/http-api/OpenApi\";\n\nconst escape = (value: string) =>\n value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\");\n\nconst escapeAttribute = (value: string) =>\n escape(value).replaceAll('\"', \""\").replaceAll(\"'\", \"'\");\n\nconst escapeJson = (value: unknown) =>\n JSON.stringify(value)\n .replaceAll(\"<\", \"\\\\u003c\")\n .replaceAll(\"\\u2028\", \"\\\\u2028\")\n .replaceAll(\"\\u2029\", \"\\\\u2029\");\n\n// WORKAROUND: Effect 4.0.6's HttpApiScalar module imports its inline Scalar\n// script dynamically, and Convex's bundler then splits a schema that reaches it\n// into an imported chunk, which Convex refuses. This copies `layerCdn`'s page\n// byte for byte. Remove when `checkSchemaBundle.mjs` passes with\n// `HttpApiScalar.layerCdn` restored.\nexport const scalarDocs = <\n Id extends string,\n Groups extends HttpApiGroup.Constraint,\n>(\n api: HttpApi.HttpApi<Id, Groups>,\n path: `/${string}`,\n) =>\n HttpRouter.use((router) => {\n let response: HttpServerResponse.HttpServerResponse | undefined;\n return router.add(\n \"GET\",\n path,\n Effect.sync(() => {\n if (response !== undefined) return response;\n const spec = OpenApi.fromApi(api);\n const description = (tag: string) =>\n !spec.info.description\n ? \"\"\n : `<meta name=\"${tag}\" content=\"${escapeAttribute(spec.info.description)}\"/>`;\n response = HttpServerResponse.html(`<!doctype html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <title>${escape(spec.info.title)}</title>\n ${description(\"description\")}\n ${description(\"og:description\")}\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1\" />\n </head>\n <body>\n <div id=\"api-reference-container\"></div>\n <script src=\"${escapeAttribute(\"https://cdn.jsdelivr.net/npm/@scalar/api-reference@latest/dist/browser/standalone.min.js\")}\" crossorigin></script>\n <script>\n window.Scalar.createApiReference(document.getElementById('api-reference-container'), {\n ...${escapeJson({ _integration: \"html\" })},\n content: ${escapeJson(spec)}\n })\n </script>\n </body>\n</html>`);\n return response;\n }),\n );\n });\n"],"mappings":";;;;;AAOA,MAAM,UAAU,UACd,MACG,WAAW,KAAK,OAAO,CAAC,CACxB,WAAW,KAAK,MAAM,CAAC,CACvB,WAAW,KAAK,MAAM;AAE3B,MAAM,mBAAmB,UACvB,OAAO,KAAK,CAAC,CAAC,WAAW,MAAK,QAAQ,CAAC,CAAC,WAAW,KAAK,OAAO;AAEjE,MAAM,cAAc,UAClB,KAAK,UAAU,KAAK,CAAC,CAClB,WAAW,KAAK,SAAS,CAAC,CAC1B,WAAW,UAAU,SAAS,CAAC,CAC/B,WAAW,UAAU,SAAS;AAOnC,MAAa,cAIX,KACA,SAEA,WAAW,KAAK,WAAW;CACzB,IAAI;CACJ,OAAO,OAAO,IACZ,OACA,MACA,OAAO,WAAW;EAChB,IAAI,aAAa,KAAA,GAAW,OAAO;EACnC,MAAM,OAAO,QAAQ,QAAQ,GAAG;EAChC,MAAM,eAAe,QACnB,CAAC,KAAK,KAAK,cACP,KACA,eAAe,IAAI,aAAa,gBAAgB,KAAK,KAAK,WAAW,EAAE;EAC7E,WAAW,mBAAmB,KAAK;;;;aAI9B,OAAO,KAAK,KAAK,KAAK,EAAE;MAC/B,YAAY,aAAa,EAAE;MAC3B,YAAY,gBAAgB,EAAE;;;;;;;mBAOjB,gBAAgB,0FAA0F,EAAE;;;aAGlH,WAAW,EAAE,cAAc,OAAO,CAAC,EAAE;mBAC/B,WAAW,IAAI,EAAE;;;;QAI5B;EACA,OAAO;CACT,CAAC,CACH;AACF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gaganref/confect-core",
|
|
3
|
-
"version": "10.3.1-fork.
|
|
3
|
+
"version": "10.3.1-fork.81",
|
|
4
4
|
"peerDependencies": {
|
|
5
|
-
"convex": "^1.
|
|
6
|
-
"effect": "
|
|
5
|
+
"convex": "^1.49.0",
|
|
6
|
+
"effect": ">=4.0.0 <4.1.0"
|
|
7
7
|
},
|
|
8
8
|
"description": "Shared specs and schemas used by all Confect packages",
|
|
9
9
|
"author": "RJ Dellecese",
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as Context from "effect/Context";
|
|
2
|
+
import type * as Effect from "effect/Effect";
|
|
3
|
+
import type * as Schema from "effect/Schema";
|
|
4
|
+
import * as FunctionSpec from "./FunctionSpec.js";
|
|
5
|
+
import * as MiddlewareSpec from "./MiddlewareSpec.js";
|
|
6
|
+
import type * as Ref from "./Ref.js";
|
|
7
|
+
|
|
8
|
+
export interface Call {
|
|
9
|
+
<Target extends Ref.AnyQuery | Ref.AnyMutation>(
|
|
10
|
+
target: Target,
|
|
11
|
+
...args: Ref.OptionalArgs<NoInfer<Target>>
|
|
12
|
+
): Effect.Effect<Ref.Returns<Target>, Ref.Error<Target> | Schema.SchemaError>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class ActionCall extends Context.Service<ActionCall, Call>()(
|
|
16
|
+
"@confect/core/ActionCall",
|
|
17
|
+
) {}
|
|
18
|
+
export class Middleware extends MiddlewareSpec.MiddlewareSpec<
|
|
19
|
+
Middleware,
|
|
20
|
+
{ provides: ActionCall }
|
|
21
|
+
>()("@confect/core/ActionCall/Middleware", {
|
|
22
|
+
functionTypes: { query: false, mutation: false, action: true },
|
|
23
|
+
}) {}
|
|
24
|
+
|
|
25
|
+
export const profile = FunctionSpec.extend()({ middleware: [Middleware] });
|
package/src/App.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { ComponentDefinition
|
|
2
|
-
import type { Infer, Validator } from "convex/values";
|
|
1
|
+
import type { ComponentDefinition } from "convex/server";
|
|
3
2
|
import type * as HttpApi from "effect/http-api/HttpApi";
|
|
4
3
|
import * as Predicate from "effect/Predicate";
|
|
5
4
|
import type * as Env from "./Env.js";
|
|
5
|
+
import type * as MiddlewareSpec from "./MiddlewareSpec.js";
|
|
6
|
+
import * as Mount from "./Mount.js";
|
|
6
7
|
|
|
7
8
|
const TypeId = "~@confect/core/App";
|
|
8
|
-
const MountTypeId = "~@confect/core/App/Mount";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* The default export of a Convex component's `convex.config` module.
|
|
@@ -19,112 +19,11 @@ export type HttpPrefix = `/${string}`;
|
|
|
19
19
|
*/
|
|
20
20
|
export type Api = HttpApi.HttpApi<string, any>;
|
|
21
21
|
|
|
22
|
-
type EnvOf<D extends Definition> = D["__env"];
|
|
23
|
-
|
|
24
|
-
type IsOptional<V> = V extends Validator<any, "optional", any> ? true : false;
|
|
25
|
-
|
|
26
|
-
type RequiredKeys<E extends EnvDefinition> = {
|
|
27
|
-
[K in keyof E]: IsOptional<E[K]> extends true ? never : K;
|
|
28
|
-
}[keyof E];
|
|
29
|
-
|
|
30
|
-
type SlotValue<V extends Validator<any, any, any>> = Extract<Infer<V>, string>;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* What one component env slot accepts: a constant, or an entry whose Convex
|
|
34
|
-
* value fits. A required slot takes only a required entry.
|
|
35
|
-
*/
|
|
36
|
-
type Slot<V extends Validator<any, any, any>> =
|
|
37
|
-
IsOptional<V> extends true
|
|
38
|
-
? SlotValue<V> | undefined | Env.Entry<string, any, SlotValue<V>, boolean>
|
|
39
|
-
: SlotValue<V> | Env.Entry<string, any, SlotValue<V>, false>;
|
|
40
|
-
|
|
41
|
-
export type Bindings<E extends EnvDefinition> = {
|
|
42
|
-
readonly [K in RequiredKeys<E>]: Slot<E[K]>;
|
|
43
|
-
} & {
|
|
44
|
-
readonly [K in Exclude<keyof E, RequiredKeys<E>>]?: Slot<E[K]>;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
type HttpOptions =
|
|
48
|
-
| { readonly httpPrefix?: never; readonly api?: never }
|
|
49
|
-
| { readonly httpPrefix: HttpPrefix; readonly api?: Api };
|
|
50
|
-
|
|
51
|
-
export type Options<D extends Definition> = HttpOptions &
|
|
52
|
-
([RequiredKeys<EnvOf<D>>] extends [never]
|
|
53
|
-
? { readonly env?: Bindings<EnvOf<D>> }
|
|
54
|
-
: { readonly env: Bindings<EnvOf<D>> });
|
|
55
|
-
|
|
56
|
-
type Exact<D extends Definition, O> = {
|
|
57
|
-
readonly [K in Exclude<keyof O, "env" | "httpPrefix" | "api">]: never;
|
|
58
|
-
} & (O extends { readonly env: infer B }
|
|
59
|
-
? {
|
|
60
|
-
readonly env: { readonly [K in Exclude<keyof B, keyof EnvOf<D>>]: never };
|
|
61
|
-
}
|
|
62
|
-
: unknown);
|
|
63
|
-
|
|
64
|
-
export interface MountData {
|
|
65
|
-
readonly definition: Definition;
|
|
66
|
-
readonly httpPrefix: HttpPrefix | undefined;
|
|
67
|
-
readonly api: Api | undefined;
|
|
68
|
-
readonly env: Readonly<Record<string, string | Env.AnyEntry | undefined>>;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* A mounted Convex component. `O` keeps the options as written, so {@link make}
|
|
73
|
-
* can see which backends the bound entries come from.
|
|
74
|
-
*/
|
|
75
|
-
export interface Mount<out D extends Definition, out O> extends MountData {
|
|
76
|
-
readonly [MountTypeId]: { readonly definition: D; readonly options: O };
|
|
77
|
-
readonly httpPrefix: O extends {
|
|
78
|
-
readonly httpPrefix: infer P extends HttpPrefix;
|
|
79
|
-
}
|
|
80
|
-
? P
|
|
81
|
-
: undefined;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export type AnyMount = Mount<Definition, unknown>;
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Mount a Convex component: the default export of its `convex.config` module,
|
|
88
|
-
* official or Confect-authored. `env` is typed against the component's own
|
|
89
|
-
* `defineComponent({ env })` declaration, so a missing required binding, an
|
|
90
|
-
* optional entry in a required slot, a wrong literal and an unknown slot fail
|
|
91
|
-
* to typecheck. `api` is the component's `HttpApi`, for route checks.
|
|
92
|
-
*/
|
|
93
|
-
export function mount<const D extends Definition>(
|
|
94
|
-
definition: D &
|
|
95
|
-
([RequiredKeys<EnvOf<D>>] extends [never]
|
|
96
|
-
? unknown
|
|
97
|
-
: "App.mount: this component declares required env; pass { env }"),
|
|
98
|
-
): Mount<D, {}>;
|
|
99
|
-
export function mount<const D extends Definition, const O extends Options<D>>(
|
|
100
|
-
definition: D,
|
|
101
|
-
options: O & Exact<NoInfer<D>, NoInfer<O>>,
|
|
102
|
-
): Mount<D, O>;
|
|
103
|
-
export function mount(
|
|
104
|
-
definition: Definition,
|
|
105
|
-
options?: {
|
|
106
|
-
readonly httpPrefix?: HttpPrefix;
|
|
107
|
-
readonly api?: Api;
|
|
108
|
-
readonly env?: MountData["env"];
|
|
109
|
-
},
|
|
110
|
-
): AnyMount {
|
|
111
|
-
return {
|
|
112
|
-
[MountTypeId]: { definition, options },
|
|
113
|
-
definition,
|
|
114
|
-
httpPrefix: options?.httpPrefix,
|
|
115
|
-
api: options?.api,
|
|
116
|
-
env: options?.env ?? {},
|
|
117
|
-
// The overloads above carry the precise types; this body serves both.
|
|
118
|
-
} as AnyMount;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
22
|
type OwnerOf<V> = V extends Env.Entry<infer N, any, any, any> ? N : never;
|
|
122
23
|
|
|
123
24
|
type Owners<M> =
|
|
124
|
-
M extends Mount<
|
|
125
|
-
?
|
|
126
|
-
? { [K in keyof B]: OwnerOf<B[K]> }[keyof B]
|
|
127
|
-
: never
|
|
25
|
+
M extends Mount.Mount<any, any, Mount.Declared<any, infer B>>
|
|
26
|
+
? { [K in keyof B]: OwnerOf<B[K]> }[keyof B]
|
|
128
27
|
: never;
|
|
129
28
|
|
|
130
29
|
type OwnedBy<N extends string, M> = {
|
|
@@ -137,51 +36,57 @@ export type Kind = "app" | "component";
|
|
|
137
36
|
|
|
138
37
|
export interface App<
|
|
139
38
|
E extends Env.Any,
|
|
140
|
-
M extends
|
|
39
|
+
M extends ReadonlyArray<Mount.Any>,
|
|
141
40
|
K extends Kind = Kind,
|
|
142
41
|
> {
|
|
143
42
|
readonly [TypeId]: typeof TypeId;
|
|
144
43
|
readonly kind: K;
|
|
145
44
|
readonly env: E;
|
|
45
|
+
readonly components: ReadonlyArray<Definition>;
|
|
146
46
|
readonly mounts: M;
|
|
47
|
+
readonly requiresMiddleware: ReadonlyArray<MiddlewareSpec.AnyMiddlewareSpec>;
|
|
147
48
|
}
|
|
148
49
|
|
|
149
|
-
export type Any = App<Env.Any,
|
|
50
|
+
export type Any = App<Env.Any, ReadonlyArray<Mount.Any>>;
|
|
150
51
|
|
|
151
52
|
/**
|
|
152
|
-
* Declare a backend, in `confect/app.ts`: its env
|
|
153
|
-
* components
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
53
|
+
* Declare a backend, in `confect/app.ts`: its env, the `convex.config`
|
|
54
|
+
* definitions of the Convex components it mounts, and its mounts. Set `kind:
|
|
55
|
+
* "component"` when declaring a component; the default is `"app"`. Codegen
|
|
56
|
+
* rejects a kind that differs from its target, and writes
|
|
57
|
+
* `convex/convex.config.ts` with one `app.use` per mount, in list order, using
|
|
58
|
+
* the definition whose `defineComponent` name is the mount's component name. A
|
|
59
|
+
* mount that binds another backend's env entry fails to typecheck.
|
|
157
60
|
*
|
|
158
61
|
* ```ts
|
|
62
|
+
* import email from "@acme/email/convex.config";
|
|
63
|
+
* import workpool from "@convex-dev/workpool/convex.config";
|
|
64
|
+
*
|
|
159
65
|
* export default App.make({
|
|
160
66
|
* env,
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
* httpPrefix: "/email",
|
|
164
|
-
* env: { FROM: env.EMAIL_FROM, KEY: env.RESEND_API_KEY },
|
|
165
|
-
* }),
|
|
166
|
-
* importsPool: App.mount(workpool),
|
|
167
|
-
* },
|
|
67
|
+
* components: [email, workpool],
|
|
68
|
+
* mounts: [BulkEmail, TransactionalEmail, ImportsPool],
|
|
168
69
|
* });
|
|
169
70
|
* ```
|
|
170
71
|
*/
|
|
171
72
|
export const make = <
|
|
172
73
|
const E extends Env.Any,
|
|
173
|
-
const M extends
|
|
74
|
+
const M extends ReadonlyArray<Mount.Any> = [],
|
|
174
75
|
const K extends Kind = "app",
|
|
175
76
|
>(
|
|
176
77
|
options: {
|
|
177
78
|
readonly env: E;
|
|
79
|
+
readonly requiresMiddleware?: ReadonlyArray<MiddlewareSpec.AnyMiddlewareSpec>;
|
|
80
|
+
readonly components?: ReadonlyArray<Definition>;
|
|
178
81
|
readonly mounts?: M & OwnedBy<NoInfer<Env.Name<E>>, NoInfer<M>>;
|
|
179
82
|
} & ([K] extends ["app"] ? { readonly kind?: K } : { readonly kind: K }),
|
|
180
83
|
): App<E, M, K> => ({
|
|
181
84
|
[TypeId]: TypeId,
|
|
182
85
|
kind: options.kind ?? ("app" as K),
|
|
183
86
|
env: options.env,
|
|
184
|
-
|
|
87
|
+
components: options.components ?? [],
|
|
88
|
+
mounts: options.mounts ?? ([] as unknown as M),
|
|
89
|
+
requiresMiddleware: options.requiresMiddleware ?? [],
|
|
185
90
|
});
|
|
186
91
|
|
|
187
92
|
export const isApp = (u: unknown): u is Any =>
|
|
@@ -190,21 +95,16 @@ export const isApp = (u: unknown): u is Any =>
|
|
|
190
95
|
Predicate.hasProperty(u, "kind") &&
|
|
191
96
|
(u.kind === "app" || u.kind === "component");
|
|
192
97
|
|
|
193
|
-
export const isMount = (u: unknown): u is AnyMount =>
|
|
194
|
-
Predicate.hasProperty(u, MountTypeId);
|
|
195
|
-
|
|
196
98
|
export const env = <A extends Any>(app: A): A["env"] => app.env;
|
|
197
99
|
|
|
198
100
|
/**
|
|
199
|
-
*
|
|
101
|
+
* The `convex.config` definitions the backend lists, in list order.
|
|
102
|
+
*/
|
|
103
|
+
export const components = (app: Any): ReadonlyArray<Definition> =>
|
|
104
|
+
app.components;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* What each mount was declared with, in list order.
|
|
200
108
|
*/
|
|
201
|
-
export const mounts = (
|
|
202
|
-
app
|
|
203
|
-
): ReadonlyArray<MountData & { readonly name: string }> =>
|
|
204
|
-
Object.entries(app.mounts).map(([name, installed]) => ({
|
|
205
|
-
name,
|
|
206
|
-
definition: installed.definition,
|
|
207
|
-
httpPrefix: installed.httpPrefix,
|
|
208
|
-
api: installed.api,
|
|
209
|
-
env: installed.env,
|
|
210
|
-
}));
|
|
109
|
+
export const mounts = (app: Any): ReadonlyArray<Mount.Data> =>
|
|
110
|
+
app.mounts.map(Mount.data);
|
package/src/Auth.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type { AuthProvider } from "convex/server";
|
|
2
2
|
import * as Predicate from "effect/Predicate";
|
|
3
3
|
import type * as App from "./App.js";
|
|
4
|
+
import type * as Env from "./Env.js";
|
|
5
|
+
import * as Mount from "./Mount.js";
|
|
4
6
|
import type { TypeError } from "./Types.js";
|
|
5
7
|
|
|
6
8
|
const TypeId = "~@confect/core/Auth";
|
|
9
|
+
const CloudUrlTypeId = "~@confect/core/Auth/CloudUrl";
|
|
7
10
|
const SiteUrlTypeId = "~@confect/core/Auth/SiteUrl";
|
|
8
11
|
|
|
9
12
|
/**
|
|
@@ -15,19 +18,59 @@ export interface SiteUrl {
|
|
|
15
18
|
readonly path: string;
|
|
16
19
|
}
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
/**
|
|
22
|
+
* The deployment's cloud URL (`CONVEX_CLOUD_URL`) plus a path.
|
|
23
|
+
*/
|
|
24
|
+
export interface CloudUrl {
|
|
25
|
+
readonly [CloudUrlTypeId]: typeof CloudUrlTypeId;
|
|
26
|
+
readonly path: string;
|
|
27
|
+
}
|
|
19
28
|
|
|
20
|
-
type
|
|
29
|
+
type Url =
|
|
30
|
+
| string
|
|
31
|
+
| SiteUrl
|
|
32
|
+
| CloudUrl
|
|
33
|
+
| Env.Entry<string, string, string, false>;
|
|
34
|
+
|
|
35
|
+
type WithUrls<P> = P extends unknown
|
|
21
36
|
? {
|
|
22
|
-
[K in keyof P]: K extends "domain" | "issuer" | "jwks"
|
|
37
|
+
[K in keyof P]: K extends "domain" | "issuer" | "jwks" | "applicationID"
|
|
38
|
+
? Url
|
|
39
|
+
: P[K];
|
|
23
40
|
}
|
|
24
41
|
: never;
|
|
25
42
|
|
|
26
43
|
/**
|
|
27
|
-
* Convex's
|
|
28
|
-
|
|
44
|
+
* Convex's provider list with deployment URLs and required, public env strings.
|
|
45
|
+
*/
|
|
46
|
+
export type Provider = WithUrls<AuthProvider> & {
|
|
47
|
+
/**
|
|
48
|
+
* Application-defined token family, copied to the runtime provider data.
|
|
49
|
+
*/
|
|
50
|
+
readonly family?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Application-defined issuer name, for example a trusted service.
|
|
53
|
+
*/
|
|
54
|
+
readonly name?: string;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The cloud URL, or a path under it, resolved when Convex loads auth config.
|
|
29
59
|
*/
|
|
30
|
-
export
|
|
60
|
+
export const cloudUrl = (path: `/${string}` | "" = ""): CloudUrl => ({
|
|
61
|
+
[CloudUrlTypeId]: CloudUrlTypeId,
|
|
62
|
+
path,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The path of a cloud URL placeholder, or `undefined` for another value.
|
|
67
|
+
*/
|
|
68
|
+
export const cloudUrlPath = (u: unknown): string | undefined =>
|
|
69
|
+
Predicate.hasProperty(u, CloudUrlTypeId) &&
|
|
70
|
+
Predicate.hasProperty(u, "path") &&
|
|
71
|
+
typeof u.path === "string"
|
|
72
|
+
? u.path
|
|
73
|
+
: undefined;
|
|
31
74
|
|
|
32
75
|
export interface Auth<A extends App.Any> {
|
|
33
76
|
readonly [TypeId]: typeof TypeId;
|
|
@@ -43,19 +86,19 @@ export type Any = Auth<App.Any>;
|
|
|
43
86
|
*/
|
|
44
87
|
export function siteUrl(path?: `/${string}`): SiteUrl;
|
|
45
88
|
export function siteUrl(
|
|
46
|
-
mount:
|
|
89
|
+
mount: Mount.Mount<any, string, Mount.Declared<App.HttpPrefix>>,
|
|
47
90
|
path?: `/${string}`,
|
|
48
91
|
): SiteUrl;
|
|
49
92
|
export function siteUrl(
|
|
50
|
-
pathOrMount?: `/${string}` |
|
|
93
|
+
pathOrMount?: `/${string}` | Mount.Any,
|
|
51
94
|
path: string = "",
|
|
52
95
|
): SiteUrl {
|
|
53
96
|
return {
|
|
54
97
|
[SiteUrlTypeId]: SiteUrlTypeId,
|
|
55
98
|
path:
|
|
56
|
-
typeof pathOrMount === "
|
|
57
|
-
? pathOrMount
|
|
58
|
-
: (pathOrMount ?? ""),
|
|
99
|
+
typeof pathOrMount === "string" || pathOrMount === undefined
|
|
100
|
+
? (pathOrMount ?? "")
|
|
101
|
+
: (Mount.data(pathOrMount).httpPrefix ?? "").replace(/\/+$/, "") + path,
|
|
59
102
|
};
|
|
60
103
|
}
|
|
61
104
|
|
package/src/Callback.ts
CHANGED
|
@@ -8,6 +8,8 @@ import * as Schema from "effect/Schema";
|
|
|
8
8
|
import * as SchemaGetter from "effect/SchemaGetter";
|
|
9
9
|
import * as FunctionProvenance from "./FunctionProvenance.js";
|
|
10
10
|
import * as Ref from "./Ref.js";
|
|
11
|
+
import { getFunctionReference } from "./RefInternal.js";
|
|
12
|
+
import { CallbackContract } from "./internal/annotations.js";
|
|
11
13
|
import type * as RuntimeAndFunctionType from "./RuntimeAndFunctionType.js";
|
|
12
14
|
|
|
13
15
|
export const TypeId = "~@confect/core/Callback";
|
|
@@ -137,6 +139,7 @@ const isHandleOf =
|
|
|
137
139
|
const fromText = <Contract_ extends Any>(
|
|
138
140
|
contract: Contract_,
|
|
139
141
|
text: string,
|
|
142
|
+
reservedArgument?: string,
|
|
140
143
|
): Handle<Contract_> =>
|
|
141
144
|
Object.assign(
|
|
142
145
|
Ref.fromProvenance(
|
|
@@ -145,25 +148,35 @@ const fromText = <Contract_ extends Any>(
|
|
|
145
148
|
[],
|
|
146
149
|
// Convex types a handle as a string that is also a function reference.
|
|
147
150
|
text as unknown as FunctionReference<any, any>,
|
|
151
|
+
contract.functionType,
|
|
152
|
+
contract.functionType === "query" ? undefined : reservedArgument,
|
|
148
153
|
),
|
|
149
154
|
{ [HandleTypeId]: contract.id },
|
|
150
155
|
) as unknown as Handle<Contract_>;
|
|
151
156
|
|
|
152
157
|
/**
|
|
153
158
|
* The schema of a handle for `contract`: a string on the wire, a runnable ref
|
|
154
|
-
* once decoded. Use it in a component's function args or tables.
|
|
159
|
+
* once decoded. Use it in a component's function args or tables. It lowers to
|
|
160
|
+
* Convex's `v.function` with the contract's encoded args and returns.
|
|
161
|
+
* `reservedArgument` opts mutation and action handles into context forwarding.
|
|
162
|
+
* The host target must reserve the same argument name.
|
|
155
163
|
*/
|
|
156
164
|
export const handle = <Contract_ extends Any>(
|
|
157
165
|
contract: Contract_,
|
|
166
|
+
options?: {
|
|
167
|
+
readonly reservedArgument?: Contract_["functionType"] extends "query"
|
|
168
|
+
? never
|
|
169
|
+
: string;
|
|
170
|
+
},
|
|
158
171
|
): Schema.Codec<Handle<Contract_>, string> =>
|
|
159
|
-
Schema.String.pipe(
|
|
172
|
+
Schema.String.annotate({ [CallbackContract]: contract }).pipe(
|
|
160
173
|
Schema.decodeTo(
|
|
161
174
|
Schema.declare(isHandleOf(contract), {
|
|
162
175
|
identifier: `Callback.Handle<${contract.id}>`,
|
|
163
176
|
}),
|
|
164
177
|
{
|
|
165
178
|
decode: SchemaGetter.transform((text: string) =>
|
|
166
|
-
fromText(contract, text),
|
|
179
|
+
fromText(contract, text, options?.reservedArgument),
|
|
167
180
|
),
|
|
168
181
|
encode: SchemaGetter.transform(
|
|
169
182
|
(ref: Handle<Contract_>) => ref.convexFunctionName,
|
|
@@ -301,4 +314,4 @@ export const toFuture = <Ref_ extends Ref.Any>(
|
|
|
301
314
|
Ref.GetFunctionVisibility<Ref_>,
|
|
302
315
|
EncodedArgs<Ref_>,
|
|
303
316
|
EncodedReturns<Ref_>
|
|
304
|
-
> =>
|
|
317
|
+
> => getFunctionReference(ref) as never;
|