@cfast/core 0.0.1 → 0.1.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/llms.txt +167 -0
- package/package.json +20 -12
- package/LICENSE +0 -21
- package/dist/types-B3KP3EKS.d.ts +0 -49
- package/dist/types-C7BT5Gwe.d.ts +0 -49
- package/dist/types-CcpyQoE6.d.ts +0 -123
package/llms.txt
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# @cfast/core
|
|
2
|
+
|
|
3
|
+
> The app object that wires @cfast/* packages together with a typed plugin system.
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
Use `@cfast/core` when you want multiple cfast packages (auth, db, storage, etc.) to share a single per-request context without repeating initialization boilerplate in every route. It is optional -- individual packages remain fully usable standalone.
|
|
8
|
+
|
|
9
|
+
## Key concepts
|
|
10
|
+
|
|
11
|
+
- **Plugin chain**: Plugins run in registration order via `.use()`. Each plugin's `setup()` receives everything prior plugins provided, plus `request` and `env`.
|
|
12
|
+
- **Namespaced context**: Each plugin's return value is nested under its `name` key (e.g., `ctx.auth.user`, `ctx.db.client`). No flat merging, no collisions.
|
|
13
|
+
- **Compile-time dependencies**: Dependent plugins declare requirements via `definePlugin<TRequires>()` (curried form). TypeScript catches missing dependencies at the `.use()` call site.
|
|
14
|
+
- **Client provider composition**: `<app.Provider>` nests all plugin React providers in registration order. `useApp()` accesses client-side plugin exports.
|
|
15
|
+
|
|
16
|
+
## API Reference
|
|
17
|
+
|
|
18
|
+
### Server (`@cfast/core`)
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { createApp, definePlugin, CfastPluginError, CfastConfigError } from "@cfast/core";
|
|
22
|
+
|
|
23
|
+
// Create the app
|
|
24
|
+
createApp(config: { env: TSchema; permissions: TPermissions }): App
|
|
25
|
+
|
|
26
|
+
// App methods
|
|
27
|
+
app.init(rawEnv: Record<string, unknown>): void // validate env (call once in Workers entry)
|
|
28
|
+
app.env(): ParsedEnv<TSchema> // typed validated environment
|
|
29
|
+
app.context(request, context?): Promise<AppContext> // build per-request context
|
|
30
|
+
app.loader(fn: (ctx, args) => T): (args) => Promise<T> // convenience route wrapper
|
|
31
|
+
app.action(fn: (ctx, args) => T): (args) => Promise<T> // convenience route wrapper
|
|
32
|
+
app.use(plugin): App // register a plugin (chainable)
|
|
33
|
+
app.Provider: ComponentType<{ children: ReactNode }> // composed React provider
|
|
34
|
+
app.permissions: TPermissions // permissions config
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Plugin definition
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
// Leaf plugin (no dependencies) -- direct form, full inference
|
|
41
|
+
definePlugin({
|
|
42
|
+
name: "analytics",
|
|
43
|
+
setup(ctx) { return { track: (event: string) => {} }; },
|
|
44
|
+
Provider?: ComponentType<{ children: ReactNode }>,
|
|
45
|
+
client?: { /* client-side values for useApp() */ },
|
|
46
|
+
}): CfastPlugin
|
|
47
|
+
|
|
48
|
+
// Dependent plugin -- curried form, specify TRequires explicitly
|
|
49
|
+
definePlugin<AuthPluginProvides>()({
|
|
50
|
+
name: "db",
|
|
51
|
+
setup(ctx) {
|
|
52
|
+
ctx.auth.user; // typed from AuthPluginProvides
|
|
53
|
+
return { client: createDb({}) };
|
|
54
|
+
},
|
|
55
|
+
}): CfastPlugin
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Plugin type token
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
// Each package exports a type token for dependents:
|
|
62
|
+
export type AuthPluginProvides = PluginProvides<typeof authPlugin>;
|
|
63
|
+
// Resolves to: { auth: { user: AuthUser | null; grants: Grant[]; instance: AuthInstance } }
|
|
64
|
+
|
|
65
|
+
// Multiple dependencies -- intersect type tokens:
|
|
66
|
+
definePlugin<AuthPluginProvides & DbPluginProvides>()({ ... })
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Client (`@cfast/core/client`)
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import { useApp } from "@cfast/core/client";
|
|
73
|
+
import { CoreContext, createCoreProvider } from "@cfast/core/client";
|
|
74
|
+
|
|
75
|
+
useApp<T>(): T // typed access to all plugins' client exports (throws outside <app.Provider>)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Error classes
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
CfastPluginError // thrown when plugin setup() fails; has .pluginName and .cause
|
|
82
|
+
CfastConfigError // thrown at startup for config issues (e.g., duplicate plugin names)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Usage Examples
|
|
86
|
+
|
|
87
|
+
### App setup
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
// app/cfast.ts
|
|
91
|
+
import { createApp } from "@cfast/core";
|
|
92
|
+
import { authPlugin } from "@cfast/auth";
|
|
93
|
+
import { dbPlugin } from "@cfast/db";
|
|
94
|
+
import { storagePlugin } from "@cfast/storage";
|
|
95
|
+
|
|
96
|
+
export const app = createApp({ env: envSchema, permissions })
|
|
97
|
+
.use(authPlugin({ magicLink: { sendMagicLink: async ({ email, url }) => {} } }))
|
|
98
|
+
.use(dbPlugin({ schema }))
|
|
99
|
+
.use(storagePlugin(storageSchema));
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Workers entry
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
// workers/app.ts
|
|
106
|
+
import { app } from "~/cfast";
|
|
107
|
+
export default {
|
|
108
|
+
async fetch(request, rawEnv, ctx) {
|
|
109
|
+
app.init(rawEnv);
|
|
110
|
+
return requestHandler(request, { cloudflare: { env: app.env(), ctx } });
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Route loader
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
// Using app.context() directly:
|
|
119
|
+
export async function loader({ request, context }: Route.LoaderArgs) {
|
|
120
|
+
const ctx = await app.context(request, context);
|
|
121
|
+
return ctx.db.client.query(posts).findMany().run({});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Using convenience wrapper:
|
|
125
|
+
export const loader = app.loader(async (ctx, { params }) => {
|
|
126
|
+
return ctx.db.client.query(posts).findMany().run({});
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Client provider
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
// app/root.tsx
|
|
134
|
+
export function Layout({ children }: { children: React.ReactNode }) {
|
|
135
|
+
return (
|
|
136
|
+
<html><body>
|
|
137
|
+
<app.Provider>{children}</app.Provider>
|
|
138
|
+
</body></html>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Wiring with @cfast/actions
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
export const { createAction, composeActions } = createActions({
|
|
147
|
+
getContext: async ({ request, context }) => {
|
|
148
|
+
const ctx = await app.context(request, context);
|
|
149
|
+
return { db: ctx.db.client, user: ctx.auth.user, grants: ctx.auth.grants };
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Integration
|
|
155
|
+
|
|
156
|
+
- **@cfast/env** -- `createApp({ env: schema })` delegates to `defineEnv()`. `app.init()` calls `env.init()`, `app.env()` calls `env.get()`.
|
|
157
|
+
- **@cfast/permissions** -- Accepted directly in `createApp()`. Available to all plugins.
|
|
158
|
+
- **@cfast/auth, @cfast/db, @cfast/storage** -- Each ships an optional plugin for core. The plugin wraps their standalone factory and registers with `.use()`.
|
|
159
|
+
- **@cfast/actions** -- Not wrapped by core. Actions have their own context mechanism. Use `app.context()` inside `createActions({ getContext })`.
|
|
160
|
+
|
|
161
|
+
## Common Mistakes
|
|
162
|
+
|
|
163
|
+
- Registering plugins in the wrong order -- `dbPlugin` depends on `authPlugin`, so auth must be `.use()`'d first. TypeScript catches this at compile time.
|
|
164
|
+
- Calling `app.context()` before `app.init()` -- env is not validated yet, will throw.
|
|
165
|
+
- Calling `useApp()` outside `<app.Provider>` -- throws a context error.
|
|
166
|
+
- Registering two plugins with the same `name` -- throws `CfastConfigError` at import time.
|
|
167
|
+
- Doing expensive work in `setup()` -- it runs on every request. Move one-time init to the plugin factory (outer function).
|
package/package.json
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cfast/core",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "App composition layer with plugin system for @cfast/* packages",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"cfast",
|
|
7
|
+
"cloudflare-workers",
|
|
8
|
+
"plugin",
|
|
9
|
+
"composition",
|
|
10
|
+
"framework"
|
|
11
|
+
],
|
|
5
12
|
"license": "MIT",
|
|
6
13
|
"repository": {
|
|
7
14
|
"type": "git",
|
|
@@ -22,15 +29,23 @@
|
|
|
22
29
|
}
|
|
23
30
|
},
|
|
24
31
|
"files": [
|
|
25
|
-
"dist"
|
|
32
|
+
"dist",
|
|
33
|
+
"llms.txt"
|
|
26
34
|
],
|
|
27
35
|
"sideEffects": false,
|
|
28
36
|
"publishConfig": {
|
|
29
37
|
"access": "public"
|
|
30
38
|
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsup src/index.ts src/client/index.ts --format esm --dts",
|
|
41
|
+
"dev": "tsup src/index.ts src/client/index.ts --format esm --dts --watch",
|
|
42
|
+
"typecheck": "tsc --noEmit",
|
|
43
|
+
"lint": "eslint src/",
|
|
44
|
+
"test": "vitest run --passWithNoTests"
|
|
45
|
+
},
|
|
31
46
|
"dependencies": {
|
|
32
|
-
"@cfast/
|
|
33
|
-
"@cfast/
|
|
47
|
+
"@cfast/env": "workspace:*",
|
|
48
|
+
"@cfast/permissions": "workspace:*"
|
|
34
49
|
},
|
|
35
50
|
"peerDependencies": {
|
|
36
51
|
"react": ">=18"
|
|
@@ -48,12 +63,5 @@
|
|
|
48
63
|
"tsup": "^8",
|
|
49
64
|
"typescript": "^5.7",
|
|
50
65
|
"vitest": "^4.1.0"
|
|
51
|
-
},
|
|
52
|
-
"scripts": {
|
|
53
|
-
"build": "tsup src/index.ts src/client/index.ts --format esm --dts",
|
|
54
|
-
"dev": "tsup src/index.ts src/client/index.ts --format esm --dts --watch",
|
|
55
|
-
"typecheck": "tsc --noEmit",
|
|
56
|
-
"lint": "eslint src/",
|
|
57
|
-
"test": "vitest run --passWithNoTests"
|
|
58
66
|
}
|
|
59
|
-
}
|
|
67
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Daniel Schmidt
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/dist/types-B3KP3EKS.d.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { Schema, ParsedEnv } from '@cfast/env';
|
|
2
|
-
import { Permissions } from '@cfast/permissions';
|
|
3
|
-
import { ComponentType, ReactNode } from 'react';
|
|
4
|
-
|
|
5
|
-
type CreateAppConfig<TSchema extends Schema, TPermissions extends Permissions> = {
|
|
6
|
-
env: TSchema;
|
|
7
|
-
permissions: TPermissions;
|
|
8
|
-
};
|
|
9
|
-
type PluginSetupContext<TRequires> = {
|
|
10
|
-
request: Request;
|
|
11
|
-
env: Record<string, unknown>;
|
|
12
|
-
} & TRequires;
|
|
13
|
-
type CfastPlugin<TName extends string = string, TProvides = unknown, TRequires = {}, TClient = {}> = {
|
|
14
|
-
name: TName;
|
|
15
|
-
setup: (ctx: PluginSetupContext<TRequires>) => TProvides | Promise<TProvides>;
|
|
16
|
-
Provider?: ComponentType<{
|
|
17
|
-
children: ReactNode;
|
|
18
|
-
}>;
|
|
19
|
-
client?: TClient;
|
|
20
|
-
};
|
|
21
|
-
type PluginProvides<T> = T extends CfastPlugin<infer N, infer P, unknown, unknown> ? {
|
|
22
|
-
[K in N]: P;
|
|
23
|
-
} : never;
|
|
24
|
-
type AppContext<TSchema extends Schema, TPluginContext> = {
|
|
25
|
-
env: ParsedEnv<TSchema>;
|
|
26
|
-
} & TPluginContext;
|
|
27
|
-
type RouteArgs = {
|
|
28
|
-
request: Request;
|
|
29
|
-
params: Record<string, string | undefined>;
|
|
30
|
-
context: unknown;
|
|
31
|
-
};
|
|
32
|
-
type App<TSchema extends Schema, TPermissions extends Permissions, TPluginContext, TClientContext> = {
|
|
33
|
-
init(rawEnv: Record<string, unknown>): void;
|
|
34
|
-
env(): ParsedEnv<TSchema>;
|
|
35
|
-
context(request: Request, context?: unknown): Promise<AppContext<TSchema, TPluginContext>>;
|
|
36
|
-
loader<T>(fn: (ctx: AppContext<TSchema, TPluginContext>, args: RouteArgs) => T | Promise<T>): (args: RouteArgs) => Promise<T>;
|
|
37
|
-
action<T>(fn: (ctx: AppContext<TSchema, TPluginContext>, args: RouteArgs) => T | Promise<T>): (args: RouteArgs) => Promise<T>;
|
|
38
|
-
use<TName extends string, TProvides, TClient>(plugin: CfastPlugin<TName, TProvides, TPluginContext, TClient>): App<TSchema, TPermissions, TPluginContext & {
|
|
39
|
-
[K in TName]: TProvides;
|
|
40
|
-
}, TClientContext & (TClient extends {} ? {
|
|
41
|
-
[K in TName]: TClient;
|
|
42
|
-
} : {})>;
|
|
43
|
-
Provider: ComponentType<{
|
|
44
|
-
children: ReactNode;
|
|
45
|
-
}>;
|
|
46
|
-
permissions: TPermissions;
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export type { App as A, CreateAppConfig as C, PluginSetupContext as P, RouteArgs as R, CfastPlugin as a, AppContext as b, PluginProvides as c };
|
package/dist/types-C7BT5Gwe.d.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { Schema, ParsedEnv } from '@cfast/env';
|
|
2
|
-
import { Permissions } from '@cfast/permissions';
|
|
3
|
-
import { ComponentType, ReactNode } from 'react';
|
|
4
|
-
|
|
5
|
-
type CreateAppConfig<TSchema extends Schema, TPermissions extends Permissions> = {
|
|
6
|
-
env: TSchema;
|
|
7
|
-
permissions: TPermissions;
|
|
8
|
-
};
|
|
9
|
-
type PluginSetupContext<TRequires> = {
|
|
10
|
-
request: Request;
|
|
11
|
-
env: Record<string, unknown>;
|
|
12
|
-
} & TRequires;
|
|
13
|
-
type CfastPlugin<TName extends string = string, TProvides = unknown, TRequires = unknown, TClient = unknown> = {
|
|
14
|
-
name: TName;
|
|
15
|
-
setup: (ctx: PluginSetupContext<TRequires>) => TProvides | Promise<TProvides>;
|
|
16
|
-
Provider?: ComponentType<{
|
|
17
|
-
children: ReactNode;
|
|
18
|
-
}>;
|
|
19
|
-
client?: TClient;
|
|
20
|
-
};
|
|
21
|
-
type PluginProvides<T> = T extends CfastPlugin<infer N, infer P, unknown, unknown> ? {
|
|
22
|
-
[K in N]: P;
|
|
23
|
-
} : never;
|
|
24
|
-
type AppContext<TSchema extends Schema, TPluginContext> = {
|
|
25
|
-
env: ParsedEnv<TSchema>;
|
|
26
|
-
} & TPluginContext;
|
|
27
|
-
type RouteArgs = {
|
|
28
|
-
request: Request;
|
|
29
|
-
params: Record<string, string | undefined>;
|
|
30
|
-
context: unknown;
|
|
31
|
-
};
|
|
32
|
-
type App<TSchema extends Schema, TPermissions extends Permissions, TPluginContext, TClientContext> = {
|
|
33
|
-
init(rawEnv: Record<string, unknown>): void;
|
|
34
|
-
env(): ParsedEnv<TSchema>;
|
|
35
|
-
context(request: Request, context?: unknown): Promise<AppContext<TSchema, TPluginContext>>;
|
|
36
|
-
loader<T>(fn: (ctx: AppContext<TSchema, TPluginContext>, args: RouteArgs) => T | Promise<T>): (args: RouteArgs) => Promise<T>;
|
|
37
|
-
action<T>(fn: (ctx: AppContext<TSchema, TPluginContext>, args: RouteArgs) => T | Promise<T>): (args: RouteArgs) => Promise<T>;
|
|
38
|
-
use<TName extends string, TProvides, TClient>(plugin: CfastPlugin<TName, TProvides, TPluginContext, TClient>): App<TSchema, TPermissions, TPluginContext & {
|
|
39
|
-
[K in TName]: TProvides;
|
|
40
|
-
}, TClientContext & (TClient extends object ? {
|
|
41
|
-
[K in TName]: TClient;
|
|
42
|
-
} : unknown)>;
|
|
43
|
-
Provider: ComponentType<{
|
|
44
|
-
children: ReactNode;
|
|
45
|
-
}>;
|
|
46
|
-
permissions: TPermissions;
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export type { App as A, CreateAppConfig as C, PluginSetupContext as P, RouteArgs as R, CfastPlugin as a, AppContext as b, PluginProvides as c };
|
package/dist/types-CcpyQoE6.d.ts
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import { Schema, ParsedEnv } from '@cfast/env';
|
|
2
|
-
import { Permissions } from '@cfast/permissions';
|
|
3
|
-
import { ComponentType, ReactNode } from 'react';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Configuration object for {@link createApp}.
|
|
7
|
-
*
|
|
8
|
-
* @typeParam TSchema - The env schema type from `@cfast/env`.
|
|
9
|
-
* @typeParam TPermissions - The permissions definition from `@cfast/permissions`.
|
|
10
|
-
*/
|
|
11
|
-
type CreateAppConfig<TSchema extends Schema, TPermissions extends Permissions> = {
|
|
12
|
-
/** The environment variable schema. Validated at `app.init()` time via `@cfast/env`. */
|
|
13
|
-
env: TSchema;
|
|
14
|
-
/** The permissions config from `definePermissions()`. Made available to all plugins. */
|
|
15
|
-
permissions: TPermissions;
|
|
16
|
-
};
|
|
17
|
-
/**
|
|
18
|
-
* The context object passed to a plugin's `setup()` function.
|
|
19
|
-
*
|
|
20
|
-
* Contains the current request, validated env, and all values provided by prior plugins
|
|
21
|
-
* (typed via `TRequires`).
|
|
22
|
-
*
|
|
23
|
-
* @typeParam TRequires - Intersection of prior plugin provides (e.g., `AuthPluginProvides`).
|
|
24
|
-
*/
|
|
25
|
-
type PluginSetupContext<TRequires> = {
|
|
26
|
-
/** The incoming HTTP request for the current invocation. */
|
|
27
|
-
request: Request;
|
|
28
|
-
/** The validated environment bindings. */
|
|
29
|
-
env: Record<string, unknown>;
|
|
30
|
-
} & TRequires;
|
|
31
|
-
/**
|
|
32
|
-
* A cfast plugin definition created by {@link definePlugin}.
|
|
33
|
-
*
|
|
34
|
-
* Plugins provide server-side context values via `setup()`, optional client-side React providers,
|
|
35
|
-
* and optional client-side values accessible via `useApp()`.
|
|
36
|
-
*
|
|
37
|
-
* @typeParam TName - The unique plugin name, used as the namespace key in `AppContext`.
|
|
38
|
-
* @typeParam TProvides - The type returned by `setup()`, accessible as `ctx[name]`.
|
|
39
|
-
* @typeParam TRequires - The context shape this plugin depends on from prior plugins.
|
|
40
|
-
* @typeParam TClient - Client-side values exposed via `useApp()`.
|
|
41
|
-
*/
|
|
42
|
-
type CfastPlugin<TName extends string = string, TProvides = unknown, TRequires = unknown, TClient = unknown> = {
|
|
43
|
-
/** Unique identifier used as the namespace key in the app context. */
|
|
44
|
-
name: TName;
|
|
45
|
-
/** Called per-request to produce the values this plugin provides. */
|
|
46
|
-
setup: (ctx: PluginSetupContext<TRequires>) => TProvides | Promise<TProvides>;
|
|
47
|
-
/** Optional client-side React provider, composed into `app.Provider`. */
|
|
48
|
-
Provider?: ComponentType<{
|
|
49
|
-
children: ReactNode;
|
|
50
|
-
}>;
|
|
51
|
-
/** Optional client-side values exposed via `useApp()`. */
|
|
52
|
-
client?: TClient;
|
|
53
|
-
};
|
|
54
|
-
/**
|
|
55
|
-
* Utility type that extracts `{ [name]: ReturnType<setup> }` from a plugin definition.
|
|
56
|
-
*
|
|
57
|
-
* Use this to create a type token that dependent plugins can reference via `definePlugin<TRequires>()`.
|
|
58
|
-
*
|
|
59
|
-
* @typeParam T - A `CfastPlugin` type to extract provides from.
|
|
60
|
-
*/
|
|
61
|
-
type PluginProvides<T> = T extends CfastPlugin<infer N, infer P, unknown, unknown> ? {
|
|
62
|
-
[K in N]: P;
|
|
63
|
-
} : never;
|
|
64
|
-
/**
|
|
65
|
-
* The accumulated per-request context after all plugins have run.
|
|
66
|
-
*
|
|
67
|
-
* Contains the validated env plus each plugin's namespaced values.
|
|
68
|
-
*
|
|
69
|
-
* @typeParam TSchema - The env schema type.
|
|
70
|
-
* @typeParam TPluginContext - The intersection of all registered plugins' provides.
|
|
71
|
-
*/
|
|
72
|
-
type AppContext<TSchema extends Schema, TPluginContext> = {
|
|
73
|
-
/** The validated environment bindings. */
|
|
74
|
-
env: ParsedEnv<TSchema>;
|
|
75
|
-
} & TPluginContext;
|
|
76
|
-
/**
|
|
77
|
-
* Route handler arguments passed through from React Router loaders and actions.
|
|
78
|
-
*/
|
|
79
|
-
type RouteArgs = {
|
|
80
|
-
/** The incoming HTTP request. */
|
|
81
|
-
request: Request;
|
|
82
|
-
/** URL route parameters (e.g., `{ postId: "abc" }`). */
|
|
83
|
-
params: Record<string, string | undefined>;
|
|
84
|
-
/** The React Router context object (contains `cloudflare.env`, etc.). */
|
|
85
|
-
context: unknown;
|
|
86
|
-
};
|
|
87
|
-
/**
|
|
88
|
-
* The app object returned by `createApp()` and extended by `.use()` calls.
|
|
89
|
-
*
|
|
90
|
-
* Provides methods for environment initialization, per-request context creation,
|
|
91
|
-
* route handler wrappers, plugin registration, and a composed React provider.
|
|
92
|
-
*
|
|
93
|
-
* @typeParam TSchema - The env schema type.
|
|
94
|
-
* @typeParam TPermissions - The permissions definition type.
|
|
95
|
-
* @typeParam TPluginContext - The accumulated plugin context type.
|
|
96
|
-
* @typeParam TClientContext - The accumulated client-side context type.
|
|
97
|
-
*/
|
|
98
|
-
type App<TSchema extends Schema, TPermissions extends Permissions, TPluginContext, TClientContext> = {
|
|
99
|
-
/** Validates and initializes environment bindings. Call once in the Workers entry point. */
|
|
100
|
-
init(rawEnv: Record<string, unknown>): void;
|
|
101
|
-
/** Returns the typed, validated environment. */
|
|
102
|
-
env(): ParsedEnv<TSchema>;
|
|
103
|
-
/** Builds the per-request context by running each plugin's `setup()` in order. */
|
|
104
|
-
context(request: Request, context?: unknown): Promise<AppContext<TSchema, TPluginContext>>;
|
|
105
|
-
/** Convenience wrapper for React Router loaders that auto-creates the app context. */
|
|
106
|
-
loader<T>(fn: (ctx: AppContext<TSchema, TPluginContext>, args: RouteArgs) => T | Promise<T>): (args: RouteArgs) => Promise<T>;
|
|
107
|
-
/** Convenience wrapper for React Router actions that auto-creates the app context. */
|
|
108
|
-
action<T>(fn: (ctx: AppContext<TSchema, TPluginContext>, args: RouteArgs) => T | Promise<T>): (args: RouteArgs) => Promise<T>;
|
|
109
|
-
/** Registers a plugin, extending the app's context type. Throws on duplicate names. */
|
|
110
|
-
use<TName extends string, TProvides, TClient>(plugin: CfastPlugin<TName, TProvides, TPluginContext, TClient>): App<TSchema, TPermissions, TPluginContext & {
|
|
111
|
-
[K in TName]: TProvides;
|
|
112
|
-
}, TClientContext & (TClient extends object ? {
|
|
113
|
-
[K in TName]: TClient;
|
|
114
|
-
} : unknown)>;
|
|
115
|
-
/** Composed React provider tree from all registered plugins. */
|
|
116
|
-
Provider: ComponentType<{
|
|
117
|
-
children: ReactNode;
|
|
118
|
-
}>;
|
|
119
|
-
/** The permissions config passed to `createApp()`. */
|
|
120
|
-
permissions: TPermissions;
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
export type { App as A, CreateAppConfig as C, PluginSetupContext as P, RouteArgs as R, CfastPlugin as a, AppContext as b, PluginProvides as c };
|