appflare 0.2.25 → 0.2.27
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/Documentation.md +758 -758
- package/cli/commands/index.ts +238 -238
- package/cli/generate.ts +178 -178
- package/cli/index.ts +120 -120
- package/cli/load-config.ts +184 -184
- package/cli/schema-compiler.ts +1183 -1183
- package/cli/templates/auth/README.md +156 -156
- package/cli/templates/auth/config.ts +61 -61
- package/cli/templates/auth/route-config.ts +1 -1
- package/cli/templates/auth/route-handler.ts +1 -1
- package/cli/templates/auth/route-request-utils.ts +5 -5
- package/cli/templates/auth/route.config.ts +18 -18
- package/cli/templates/auth/route.handler.ts +18 -18
- package/cli/templates/auth/route.request-utils.ts +55 -55
- package/cli/templates/auth/route.ts +14 -14
- package/cli/templates/core/README.md +266 -266
- package/cli/templates/core/app-creation.ts +19 -19
- package/cli/templates/core/client/appflare.ts +112 -112
- package/cli/templates/core/client/handlers/index.ts +748 -748
- package/cli/templates/core/client/handlers.ts +1 -1
- package/cli/templates/core/client/index.ts +7 -7
- package/cli/templates/core/client/storage.ts +205 -180
- package/cli/templates/core/client/types.ts +186 -184
- package/cli/templates/core/client-modules/appflare.ts +1 -1
- package/cli/templates/core/client-modules/handlers.ts +1 -1
- package/cli/templates/core/client-modules/index.ts +1 -1
- package/cli/templates/core/client-modules/storage.ts +1 -1
- package/cli/templates/core/client-modules/types.ts +1 -1
- package/cli/templates/core/client.artifacts.ts +39 -39
- package/cli/templates/core/client.ts +4 -4
- package/cli/templates/core/drizzle.ts +15 -15
- package/cli/templates/core/export.ts +14 -14
- package/cli/templates/core/handlers.route.ts +24 -24
- package/cli/templates/core/handlers.ts +1 -1
- package/cli/templates/core/imports.ts +9 -9
- package/cli/templates/core/server.ts +38 -38
- package/cli/templates/core/types.ts +6 -6
- package/cli/templates/core/wrangler.ts +109 -109
- package/cli/templates/dashboard/builders/functions/index.ts +17 -17
- package/cli/templates/dashboard/builders/functions/render-page/header.ts +20 -20
- package/cli/templates/dashboard/builders/functions/render-page/index.ts +33 -33
- package/cli/templates/dashboard/builders/functions/render-page/request-panel.ts +171 -171
- package/cli/templates/dashboard/builders/functions/render-page/result-panel.ts +85 -85
- package/cli/templates/dashboard/builders/functions/render-page/scripts.ts +554 -554
- package/cli/templates/dashboard/builders/navigation.ts +122 -122
- package/cli/templates/dashboard/builders/storage/index.ts +13 -13
- package/cli/templates/dashboard/builders/storage/routes/create-directory-route.ts +29 -29
- package/cli/templates/dashboard/builders/storage/routes/delete-route.ts +18 -18
- package/cli/templates/dashboard/builders/storage/routes/download-route.ts +23 -23
- package/cli/templates/dashboard/builders/storage/routes/index.ts +22 -22
- package/cli/templates/dashboard/builders/storage/routes/list-route.ts +25 -25
- package/cli/templates/dashboard/builders/storage/routes/preview-route.ts +21 -21
- package/cli/templates/dashboard/builders/storage/routes/upload-route.ts +21 -21
- package/cli/templates/dashboard/builders/storage/runtime/helpers.ts +72 -72
- package/cli/templates/dashboard/builders/storage/runtime/storage-page.ts +130 -130
- package/cli/templates/dashboard/builders/table-routes/common/drawer-panel.ts +27 -27
- package/cli/templates/dashboard/builders/table-routes/common/pagination.ts +30 -30
- package/cli/templates/dashboard/builders/table-routes/common/search-bar.ts +23 -23
- package/cli/templates/dashboard/builders/table-routes/fragments.ts +217 -217
- package/cli/templates/dashboard/builders/table-routes/helpers.ts +45 -45
- package/cli/templates/dashboard/builders/table-routes/index.ts +8 -8
- package/cli/templates/dashboard/builders/table-routes/table/actions-cell.ts +71 -71
- package/cli/templates/dashboard/builders/table-routes/table/get-route.ts +291 -291
- package/cli/templates/dashboard/builders/table-routes/table/index.ts +80 -80
- package/cli/templates/dashboard/builders/table-routes/table/post-routes.ts +163 -163
- package/cli/templates/dashboard/builders/table-routes/table-route.ts +7 -7
- package/cli/templates/dashboard/builders/table-routes/users/get-route.ts +69 -69
- package/cli/templates/dashboard/builders/table-routes/users/html/modals.ts +57 -57
- package/cli/templates/dashboard/builders/table-routes/users/html/page.ts +27 -27
- package/cli/templates/dashboard/builders/table-routes/users/html/table.ts +128 -128
- package/cli/templates/dashboard/builders/table-routes/users/index.ts +32 -32
- package/cli/templates/dashboard/builders/table-routes/users/post-routes.ts +150 -150
- package/cli/templates/dashboard/builders/table-routes/users/redirect.ts +14 -14
- package/cli/templates/dashboard/builders/table-routes/users-route.ts +10 -10
- package/cli/templates/dashboard/components/dashboard-home.ts +23 -23
- package/cli/templates/dashboard/components/layout.ts +388 -388
- package/cli/templates/dashboard/components/login-page.ts +65 -65
- package/cli/templates/dashboard/index.ts +61 -61
- package/cli/templates/dashboard/types.ts +9 -9
- package/cli/templates/handlers/README.md +353 -353
- package/cli/templates/handlers/auth.ts +37 -37
- package/cli/templates/handlers/execution.ts +42 -42
- package/cli/templates/handlers/generators/context/context-creation.ts +101 -101
- package/cli/templates/handlers/generators/context/error-helpers.ts +11 -11
- package/cli/templates/handlers/generators/context/scheduler.ts +24 -24
- package/cli/templates/handlers/generators/context/storage-api.ts +82 -112
- package/cli/templates/handlers/generators/context/storage-helpers.ts +59 -59
- package/cli/templates/handlers/generators/context/types.ts +18 -18
- package/cli/templates/handlers/generators/context.ts +43 -43
- package/cli/templates/handlers/generators/execution.ts +15 -15
- package/cli/templates/handlers/generators/handlers.ts +13 -13
- package/cli/templates/handlers/generators/registration/modules/cron.ts +26 -26
- package/cli/templates/handlers/generators/registration/modules/realtime/auth.ts +75 -75
- package/cli/templates/handlers/generators/registration/modules/realtime/durable-object.ts +144 -144
- package/cli/templates/handlers/generators/registration/modules/realtime/index.ts +14 -14
- package/cli/templates/handlers/generators/registration/modules/realtime/publisher.ts +102 -102
- package/cli/templates/handlers/generators/registration/modules/realtime/routes.ts +164 -164
- package/cli/templates/handlers/generators/registration/modules/realtime/types.ts +30 -30
- package/cli/templates/handlers/generators/registration/modules/realtime/utils.ts +516 -516
- package/cli/templates/handlers/generators/registration/modules/scheduler.ts +56 -56
- package/cli/templates/handlers/generators/registration/modules/storage.ts +192 -194
- package/cli/templates/handlers/generators/registration/sections.ts +210 -210
- package/cli/templates/handlers/generators/types/context.ts +67 -66
- package/cli/templates/handlers/generators/types/core.ts +106 -106
- package/cli/templates/handlers/generators/types/operations.ts +135 -135
- package/cli/templates/handlers/generators/types/query-definitions/filter-and-where-types.ts +259 -259
- package/cli/templates/handlers/generators/types/query-definitions/query-api-types.ts +135 -135
- package/cli/templates/handlers/generators/types/query-definitions/query-helper-functions.ts +1031 -1031
- package/cli/templates/handlers/generators/types/query-definitions/schema-and-table-types.ts +246 -246
- package/cli/templates/handlers/generators/types/query-definitions.ts +13 -13
- package/cli/templates/handlers/generators/types/query-runtime/handled-error.ts +13 -13
- package/cli/templates/handlers/generators/types/query-runtime/runtime-aggregate-and-footer.ts +174 -174
- package/cli/templates/handlers/generators/types/query-runtime/runtime-read.ts +121 -121
- package/cli/templates/handlers/generators/types/query-runtime/runtime-setup.ts +45 -45
- package/cli/templates/handlers/generators/types/query-runtime/runtime-write.ts +676 -676
- package/cli/templates/handlers/generators/types/query-runtime.ts +15 -15
- package/cli/templates/handlers/index.ts +43 -43
- package/cli/templates/handlers/operations.ts +116 -116
- package/cli/templates/handlers/registration.ts +91 -91
- package/cli/templates/handlers/types.ts +15 -15
- package/cli/templates/handlers/utils.ts +48 -48
- package/cli/types.ts +110 -110
- package/cli/utils/handler-discovery.ts +466 -466
- package/cli/utils/json-utils.ts +24 -24
- package/cli/utils/path-utils.ts +19 -19
- package/cli/utils/schema-discovery.ts +399 -399
- package/dist/cli/index.js +95 -99
- package/dist/cli/index.mjs +95 -99
- package/index.ts +18 -18
- package/package.json +58 -58
- package/react/index.ts +5 -5
- package/react/use-infinite-query.ts +252 -252
- package/react/use-mutation.ts +89 -89
- package/react/use-query.ts +207 -207
- package/schema.ts +415 -415
- package/test-better-auth-hash.ts +2 -2
- package/tsconfig.json +6 -6
- package/tsup.config.ts +82 -82
- package/dist/cli/index.d.mts +0 -2
- package/dist/cli/index.d.ts +0 -2
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
export function generateAuth(): string {
|
|
2
|
-
return `
|
|
3
|
-
|
|
4
|
-
import { getHeaders } from "./server";
|
|
5
|
-
export async function resolveSession(
|
|
6
|
-
\trequest: Request,
|
|
7
|
-
\tdatabase: D1Database,
|
|
8
|
-
\tkvNamespace?: KVNamespace,
|
|
9
|
-
\tcf?: IncomingRequestCfProperties,
|
|
10
|
-
): Promise<{ user: unknown; session: unknown }> {
|
|
11
|
-
\tconst auth = createAuth(
|
|
12
|
-
\t\t{
|
|
13
|
-
\t\t\tDATABASE: database,
|
|
14
|
-
\t\t\tKV: kvNamespace,
|
|
15
|
-
\t\t},
|
|
16
|
-
\t\tcf,
|
|
17
|
-
\t);
|
|
18
|
-
|
|
19
|
-
\ttry {
|
|
20
|
-
\t\tconst session = await auth.api.getSession({
|
|
21
|
-
\t\t\theaders: getHeaders(request.headers),
|
|
22
|
-
\t\t});
|
|
23
|
-
|
|
24
|
-
\t\treturn {
|
|
25
|
-
\t\t\tuser: (session as any)?.user ?? null,
|
|
26
|
-
\t\t\tsession: (session as any)?.session ?? null,
|
|
27
|
-
\t\t};
|
|
28
|
-
\t} catch {
|
|
29
|
-
\t\treturn {
|
|
30
|
-
\t\t\tuser: null,
|
|
31
|
-
\t\t\tsession: null,
|
|
32
|
-
\t\t};
|
|
33
|
-
\t}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
`;
|
|
37
|
-
}
|
|
1
|
+
export function generateAuth(): string {
|
|
2
|
+
return `
|
|
3
|
+
|
|
4
|
+
import { getHeaders } from "./server";
|
|
5
|
+
export async function resolveSession(
|
|
6
|
+
\trequest: Request,
|
|
7
|
+
\tdatabase: D1Database,
|
|
8
|
+
\tkvNamespace?: KVNamespace,
|
|
9
|
+
\tcf?: IncomingRequestCfProperties,
|
|
10
|
+
): Promise<{ user: unknown; session: unknown }> {
|
|
11
|
+
\tconst auth = createAuth(
|
|
12
|
+
\t\t{
|
|
13
|
+
\t\t\tDATABASE: database,
|
|
14
|
+
\t\t\tKV: kvNamespace,
|
|
15
|
+
\t\t},
|
|
16
|
+
\t\tcf,
|
|
17
|
+
\t);
|
|
18
|
+
|
|
19
|
+
\ttry {
|
|
20
|
+
\t\tconst session = await auth.api.getSession({
|
|
21
|
+
\t\t\theaders: getHeaders(request.headers),
|
|
22
|
+
\t\t});
|
|
23
|
+
|
|
24
|
+
\t\treturn {
|
|
25
|
+
\t\t\tuser: (session as any)?.user ?? null,
|
|
26
|
+
\t\t\tsession: (session as any)?.session ?? null,
|
|
27
|
+
\t\t};
|
|
28
|
+
\t} catch {
|
|
29
|
+
\t\treturn {
|
|
30
|
+
\t\t\tuser: null,
|
|
31
|
+
\t\t\tsession: null,
|
|
32
|
+
\t\t};
|
|
33
|
+
\t}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
`;
|
|
37
|
+
}
|
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
export function generateExecution(): string {
|
|
2
|
-
return `
|
|
3
|
-
export async function executeOperation<
|
|
4
|
-
TShape extends ZodRawShape,
|
|
5
|
-
TResult,
|
|
6
|
-
>(
|
|
7
|
-
c: Context<WorkerEnv>,
|
|
8
|
-
operation: RegisteredOperation<TShape, TResult>,
|
|
9
|
-
args: unknown,
|
|
10
|
-
\tctx: AppflareContext,
|
|
11
|
-
): Promise<Response> {
|
|
12
|
-
if (operation.definition.authRequired && !ctx.user) {
|
|
13
|
-
ctx.error(401, "Unauthorized");
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (operation.definition.middleware) {
|
|
17
|
-
await operation.definition.middleware(ctx, args as never, c.req.raw);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const result = await operation.definition.handler(ctx, args as never);
|
|
21
|
-
|
|
22
|
-
\treturn c.json(result, 200);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function handleOperationError(
|
|
26
|
-
c: Context<WorkerEnv>,
|
|
27
|
-
error: unknown,
|
|
28
|
-
validationMessage: string,
|
|
29
|
-
): Response {
|
|
30
|
-
if (error instanceof AppflareHandledError) {
|
|
31
|
-
return c.json(error.payload, error.status as any);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (error instanceof ZodError) {
|
|
35
|
-
return c.json({ message: validationMessage, issues: error.issues }, 400);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return c.json({ message: (error as Error).message ?? "Unknown error" }, 500);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
`;
|
|
42
|
-
}
|
|
1
|
+
export function generateExecution(): string {
|
|
2
|
+
return `
|
|
3
|
+
export async function executeOperation<
|
|
4
|
+
TShape extends ZodRawShape,
|
|
5
|
+
TResult,
|
|
6
|
+
>(
|
|
7
|
+
c: Context<WorkerEnv>,
|
|
8
|
+
operation: RegisteredOperation<TShape, TResult>,
|
|
9
|
+
args: unknown,
|
|
10
|
+
\tctx: AppflareContext,
|
|
11
|
+
): Promise<Response> {
|
|
12
|
+
if (operation.definition.authRequired && !ctx.user) {
|
|
13
|
+
ctx.error(401, "Unauthorized");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (operation.definition.middleware) {
|
|
17
|
+
await operation.definition.middleware(ctx, args as never, c.req.raw);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const result = await operation.definition.handler(ctx, args as never);
|
|
21
|
+
|
|
22
|
+
\treturn c.json(result, 200);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function handleOperationError(
|
|
26
|
+
c: Context<WorkerEnv>,
|
|
27
|
+
error: unknown,
|
|
28
|
+
validationMessage: string,
|
|
29
|
+
): Response {
|
|
30
|
+
if (error instanceof AppflareHandledError) {
|
|
31
|
+
return c.json(error.payload, error.status as any);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (error instanceof ZodError) {
|
|
35
|
+
return c.json({ message: validationMessage, issues: error.issues }, 400);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return c.json({ message: (error as Error).message ?? "Unknown error" }, 500);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
`;
|
|
42
|
+
}
|
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
export function generateContextCreation(defaultR2Binding?: string): string {
|
|
2
|
-
return `
|
|
3
|
-
export async function createSchedulerExecutionContext(
|
|
4
|
-
env: Record<string, unknown>,
|
|
5
|
-
options: RegisterHandlersOptions,
|
|
6
|
-
): Promise<AppflareContext> {
|
|
7
|
-
const database = env[options.databaseBinding] as D1Database;
|
|
8
|
-
const r2Binding = options.r2Binding ?? ${JSON.stringify(defaultR2Binding ?? "")};
|
|
9
|
-
const storageBucket = r2Binding
|
|
10
|
-
? (env[r2Binding] as R2BucketBinding | undefined)
|
|
11
|
-
: undefined;
|
|
12
|
-
const db = createDb(database);
|
|
13
|
-
const mutationEvents = [] as AppflareContext["mutationEvents"];
|
|
14
|
-
const kvNamespace = options.kvBinding
|
|
15
|
-
? (env[options.kvBinding] as KVNamespace)
|
|
16
|
-
: undefined;
|
|
17
|
-
const schedulerBinding = options.schedulerBinding ?? "APPFLARE_SCHEDULER_QUEUE";
|
|
18
|
-
const schedulerQueue = env[schedulerBinding] as SchedulerQueueBinding | undefined;
|
|
19
|
-
const helpers = createContextErrorHelpers();
|
|
20
|
-
const auth = createAuth({
|
|
21
|
-
DATABASE: database,
|
|
22
|
-
KV: kvNamespace,
|
|
23
|
-
});
|
|
24
|
-
const authAdapter = (await auth.$context).internalAdapter;
|
|
25
|
-
const schedulerContext = {
|
|
26
|
-
env: env as WorkerEnv["Bindings"],
|
|
27
|
-
} as unknown as Context<WorkerEnv>;
|
|
28
|
-
const ctx = {
|
|
29
|
-
$db: db,
|
|
30
|
-
db: createQueryDb(db, {
|
|
31
|
-
onMutation: (event) => {
|
|
32
|
-
mutationEvents.push(event);
|
|
33
|
-
},
|
|
34
|
-
}),
|
|
35
|
-
mutationEvents,
|
|
36
|
-
user: null as never,
|
|
37
|
-
session: null as never,
|
|
38
|
-
auth: authAdapter,
|
|
39
|
-
context: schedulerContext,
|
|
40
|
-
scheduler: createScheduler(schedulerQueue),
|
|
41
|
-
storage: null as never,
|
|
42
|
-
...helpers,
|
|
43
|
-
} as AppflareContext;
|
|
44
|
-
|
|
45
|
-
ctx.storage = createStorageApi(ctx, storageBucket);
|
|
46
|
-
return ctx;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export async function createExecutionContext(
|
|
50
|
-
c: Context<WorkerEnv>,
|
|
51
|
-
options: RegisterHandlersOptions,
|
|
52
|
-
): Promise<AppflareContext> {
|
|
53
|
-
const database = c.env[options.databaseBinding] as D1Database;
|
|
54
|
-
const r2Binding = options.r2Binding ?? ${JSON.stringify(defaultR2Binding ?? "")};
|
|
55
|
-
const storageBucket = r2Binding
|
|
56
|
-
? (c.env[r2Binding] as R2BucketBinding | undefined)
|
|
57
|
-
: undefined;
|
|
58
|
-
const kvNamespace = options.kvBinding
|
|
59
|
-
? (c.env[options.kvBinding] as KVNamespace)
|
|
60
|
-
: undefined;
|
|
61
|
-
const db = createDb(database);
|
|
62
|
-
const mutationEvents = [] as AppflareContext["mutationEvents"];
|
|
63
|
-
const { user, session } = await resolveSession(
|
|
64
|
-
c.req.raw,
|
|
65
|
-
database,
|
|
66
|
-
kvNamespace,
|
|
67
|
-
c.req.raw.cf as IncomingRequestCfProperties | undefined,
|
|
68
|
-
);
|
|
69
|
-
const schedulerBinding = options.schedulerBinding ?? "APPFLARE_SCHEDULER_QUEUE";
|
|
70
|
-
const schedulerQueue = c.env[schedulerBinding] as SchedulerQueueBinding | undefined;
|
|
71
|
-
const helpers = createContextErrorHelpers();
|
|
72
|
-
const auth = createAuth(
|
|
73
|
-
{
|
|
74
|
-
DATABASE: database,
|
|
75
|
-
KV: kvNamespace,
|
|
76
|
-
},
|
|
77
|
-
c.req.raw.cf as IncomingRequestCfProperties | undefined,
|
|
78
|
-
);
|
|
79
|
-
const authAdapter = (await auth.$context).internalAdapter;
|
|
80
|
-
const ctx = {
|
|
81
|
-
$db: db,
|
|
82
|
-
db: createQueryDb(db, {
|
|
83
|
-
onMutation: (event) => {
|
|
84
|
-
mutationEvents.push(event);
|
|
85
|
-
},
|
|
86
|
-
}),
|
|
87
|
-
mutationEvents,
|
|
88
|
-
user,
|
|
89
|
-
session,
|
|
90
|
-
auth: authAdapter,
|
|
91
|
-
context: c,
|
|
92
|
-
scheduler: createScheduler(schedulerQueue),
|
|
93
|
-
storage: null as never,
|
|
94
|
-
...helpers,
|
|
95
|
-
} as AppflareContext;
|
|
96
|
-
|
|
97
|
-
ctx.storage = createStorageApi(ctx, storageBucket);
|
|
98
|
-
return ctx;
|
|
99
|
-
}
|
|
100
|
-
`;
|
|
101
|
-
}
|
|
1
|
+
export function generateContextCreation(defaultR2Binding?: string): string {
|
|
2
|
+
return `
|
|
3
|
+
export async function createSchedulerExecutionContext(
|
|
4
|
+
env: Record<string, unknown>,
|
|
5
|
+
options: RegisterHandlersOptions,
|
|
6
|
+
): Promise<AppflareContext> {
|
|
7
|
+
const database = env[options.databaseBinding] as D1Database;
|
|
8
|
+
const r2Binding = options.r2Binding ?? ${JSON.stringify(defaultR2Binding ?? "")};
|
|
9
|
+
const storageBucket = r2Binding
|
|
10
|
+
? (env[r2Binding] as R2BucketBinding | undefined)
|
|
11
|
+
: undefined;
|
|
12
|
+
const db = createDb(database);
|
|
13
|
+
const mutationEvents = [] as AppflareContext["mutationEvents"];
|
|
14
|
+
const kvNamespace = options.kvBinding
|
|
15
|
+
? (env[options.kvBinding] as KVNamespace)
|
|
16
|
+
: undefined;
|
|
17
|
+
const schedulerBinding = options.schedulerBinding ?? "APPFLARE_SCHEDULER_QUEUE";
|
|
18
|
+
const schedulerQueue = env[schedulerBinding] as SchedulerQueueBinding | undefined;
|
|
19
|
+
const helpers = createContextErrorHelpers();
|
|
20
|
+
const auth = createAuth({
|
|
21
|
+
DATABASE: database,
|
|
22
|
+
KV: kvNamespace,
|
|
23
|
+
});
|
|
24
|
+
const authAdapter = (await auth.$context).internalAdapter;
|
|
25
|
+
const schedulerContext = {
|
|
26
|
+
env: env as WorkerEnv["Bindings"],
|
|
27
|
+
} as unknown as Context<WorkerEnv>;
|
|
28
|
+
const ctx = {
|
|
29
|
+
$db: db,
|
|
30
|
+
db: createQueryDb(db, {
|
|
31
|
+
onMutation: (event) => {
|
|
32
|
+
mutationEvents.push(event);
|
|
33
|
+
},
|
|
34
|
+
}),
|
|
35
|
+
mutationEvents,
|
|
36
|
+
user: null as never,
|
|
37
|
+
session: null as never,
|
|
38
|
+
auth: authAdapter,
|
|
39
|
+
context: schedulerContext,
|
|
40
|
+
scheduler: createScheduler(schedulerQueue),
|
|
41
|
+
storage: null as never,
|
|
42
|
+
...helpers,
|
|
43
|
+
} as AppflareContext;
|
|
44
|
+
|
|
45
|
+
ctx.storage = createStorageApi(ctx, storageBucket);
|
|
46
|
+
return ctx;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function createExecutionContext(
|
|
50
|
+
c: Context<WorkerEnv>,
|
|
51
|
+
options: RegisterHandlersOptions,
|
|
52
|
+
): Promise<AppflareContext> {
|
|
53
|
+
const database = c.env[options.databaseBinding] as D1Database;
|
|
54
|
+
const r2Binding = options.r2Binding ?? ${JSON.stringify(defaultR2Binding ?? "")};
|
|
55
|
+
const storageBucket = r2Binding
|
|
56
|
+
? (c.env[r2Binding] as R2BucketBinding | undefined)
|
|
57
|
+
: undefined;
|
|
58
|
+
const kvNamespace = options.kvBinding
|
|
59
|
+
? (c.env[options.kvBinding] as KVNamespace)
|
|
60
|
+
: undefined;
|
|
61
|
+
const db = createDb(database);
|
|
62
|
+
const mutationEvents = [] as AppflareContext["mutationEvents"];
|
|
63
|
+
const { user, session } = await resolveSession(
|
|
64
|
+
c.req.raw,
|
|
65
|
+
database,
|
|
66
|
+
kvNamespace,
|
|
67
|
+
c.req.raw.cf as IncomingRequestCfProperties | undefined,
|
|
68
|
+
);
|
|
69
|
+
const schedulerBinding = options.schedulerBinding ?? "APPFLARE_SCHEDULER_QUEUE";
|
|
70
|
+
const schedulerQueue = c.env[schedulerBinding] as SchedulerQueueBinding | undefined;
|
|
71
|
+
const helpers = createContextErrorHelpers();
|
|
72
|
+
const auth = createAuth(
|
|
73
|
+
{
|
|
74
|
+
DATABASE: database,
|
|
75
|
+
KV: kvNamespace,
|
|
76
|
+
},
|
|
77
|
+
c.req.raw.cf as IncomingRequestCfProperties | undefined,
|
|
78
|
+
);
|
|
79
|
+
const authAdapter = (await auth.$context).internalAdapter;
|
|
80
|
+
const ctx = {
|
|
81
|
+
$db: db,
|
|
82
|
+
db: createQueryDb(db, {
|
|
83
|
+
onMutation: (event) => {
|
|
84
|
+
mutationEvents.push(event);
|
|
85
|
+
},
|
|
86
|
+
}),
|
|
87
|
+
mutationEvents,
|
|
88
|
+
user,
|
|
89
|
+
session,
|
|
90
|
+
auth: authAdapter,
|
|
91
|
+
context: c,
|
|
92
|
+
scheduler: createScheduler(schedulerQueue),
|
|
93
|
+
storage: null as never,
|
|
94
|
+
...helpers,
|
|
95
|
+
} as AppflareContext;
|
|
96
|
+
|
|
97
|
+
ctx.storage = createStorageApi(ctx, storageBucket);
|
|
98
|
+
return ctx;
|
|
99
|
+
}
|
|
100
|
+
`;
|
|
101
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export function generateErrorHelpers(): string {
|
|
2
|
-
return `
|
|
3
|
-
function createContextErrorHelpers() {
|
|
4
|
-
return {
|
|
5
|
-
error: (status: number, message: string, details?: unknown) => {
|
|
6
|
-
throw new AppflareHandledError(status, { message, details });
|
|
7
|
-
},
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
`;
|
|
11
|
-
}
|
|
1
|
+
export function generateErrorHelpers(): string {
|
|
2
|
+
return `
|
|
3
|
+
function createContextErrorHelpers() {
|
|
4
|
+
return {
|
|
5
|
+
error: (status: number, message: string, details?: unknown) => {
|
|
6
|
+
throw new AppflareHandledError(status, { message, details });
|
|
7
|
+
},
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
`;
|
|
11
|
+
}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
export function generateSchedulerFunctions(): string {
|
|
2
|
-
return `
|
|
3
|
-
export function createScheduler(
|
|
4
|
-
queue?: SchedulerQueueBinding,
|
|
5
|
-
): Scheduler {
|
|
6
|
-
return {
|
|
7
|
-
enqueue: async (task, ...args) => {
|
|
8
|
-
const [payload, options] = args as [unknown, SchedulerEnqueueOptions | undefined];
|
|
9
|
-
if (!queue) {
|
|
10
|
-
throw new Error("Scheduler queue binding is not configured");
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
await queue.send(
|
|
14
|
-
{
|
|
15
|
-
task,
|
|
16
|
-
payload,
|
|
17
|
-
},
|
|
18
|
-
options,
|
|
19
|
-
);
|
|
20
|
-
},
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
`;
|
|
24
|
-
}
|
|
1
|
+
export function generateSchedulerFunctions(): string {
|
|
2
|
+
return `
|
|
3
|
+
export function createScheduler(
|
|
4
|
+
queue?: SchedulerQueueBinding,
|
|
5
|
+
): Scheduler {
|
|
6
|
+
return {
|
|
7
|
+
enqueue: async (task, ...args) => {
|
|
8
|
+
const [payload, options] = args as [unknown, SchedulerEnqueueOptions | undefined];
|
|
9
|
+
if (!queue) {
|
|
10
|
+
throw new Error("Scheduler queue binding is not configured");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
await queue.send(
|
|
14
|
+
{
|
|
15
|
+
task,
|
|
16
|
+
payload,
|
|
17
|
+
},
|
|
18
|
+
options,
|
|
19
|
+
);
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
`;
|
|
24
|
+
}
|
|
@@ -1,112 +1,82 @@
|
|
|
1
|
-
export function generateStorageApi(): string {
|
|
2
|
-
return `
|
|
3
|
-
function createStorageApi(
|
|
4
|
-
ctx: AppflareContext,
|
|
5
|
-
bucket: R2BucketBinding | undefined,
|
|
6
|
-
): AppflareStorage {
|
|
7
|
-
const assertAuthorized = async (args: StorageAuthorizationArgs): Promise<void> => {
|
|
8
|
-
const allowed = await isStorageAllowed(ctx, args);
|
|
9
|
-
if (!allowed) {
|
|
10
|
-
ctx.error(403, "Storage access denied", {
|
|
11
|
-
path: args.path,
|
|
12
|
-
method: args.method,
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const requireBucket = (): R2BucketBinding => {
|
|
18
|
-
if (!bucket) {
|
|
19
|
-
throw new Error(
|
|
20
|
-
"R2 binding is not configured. Set r2 in appflare.config.ts and regenerate artifacts.",
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
return bucket;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
put: async (args) => {
|
|
28
|
-
const path = normalizeStoragePath(args.path);
|
|
29
|
-
await assertAuthorized({
|
|
30
|
-
path: "/" + path,
|
|
31
|
-
method: "put",
|
|
32
|
-
contentType: args.contentType,
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
return requireBucket().put(path, args.body, {
|
|
36
|
-
httpMetadata: {
|
|
37
|
-
...(args.httpMetadata ?? {}),
|
|
38
|
-
...(args.contentType ? { contentType: args.contentType } : {}),
|
|
39
|
-
},
|
|
40
|
-
customMetadata: args.customMetadata,
|
|
41
|
-
});
|
|
42
|
-
},
|
|
43
|
-
get: async (args) => {
|
|
44
|
-
const path = normalizeStoragePath(args.path);
|
|
45
|
-
const method = normalizeStorageMethod(args.method);
|
|
46
|
-
await assertAuthorized({
|
|
47
|
-
path: "/" + path,
|
|
48
|
-
method,
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
return requireBucket().get(path, {
|
|
52
|
-
onlyIf: args.onlyIf,
|
|
53
|
-
range: args.range,
|
|
54
|
-
});
|
|
55
|
-
},
|
|
56
|
-
delete: async (args) => {
|
|
57
|
-
const path = normalizeStoragePath(args.path);
|
|
58
|
-
await assertAuthorized({
|
|
59
|
-
path: "/" + path,
|
|
60
|
-
method: "delete",
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
await requireBucket().delete(path);
|
|
64
|
-
},
|
|
65
|
-
list: async (args = {}) => {
|
|
66
|
-
await assertAuthorized({
|
|
67
|
-
path: "/" + (args.prefix ?? ""),
|
|
68
|
-
method: args.method ?? "list",
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
return requireBucket().list({
|
|
72
|
-
prefix: args.prefix,
|
|
73
|
-
cursor: args.cursor,
|
|
74
|
-
limit: args.limit,
|
|
75
|
-
delimiter: args.delimiter,
|
|
76
|
-
include: args.include,
|
|
77
|
-
});
|
|
78
|
-
},
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
requestMethod === "PUT"
|
|
84
|
-
? "put"
|
|
85
|
-
: requestMethod === "DELETE"
|
|
86
|
-
? "delete"
|
|
87
|
-
: args.downloadAsAttachment === false
|
|
88
|
-
? "preview"
|
|
89
|
-
: "download";
|
|
90
|
-
|
|
91
|
-
await assertAuthorized({
|
|
92
|
-
path: "/" + path,
|
|
93
|
-
method,
|
|
94
|
-
contentType: args.contentType,
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
const currentBucket = requireBucket();
|
|
98
|
-
if (typeof currentBucket.createPresignedUrl !== "function") {
|
|
99
|
-
throw new Error("R2 createPresignedUrl is unavailable for this runtime binding");
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const signedRequest = buildSignedRequest(args, path);
|
|
103
|
-
const signedUrl = await currentBucket.createPresignedUrl(signedRequest, {
|
|
104
|
-
expiresIn: args.expiresIn ?? 60 * 5,
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
return signedUrl.toString();
|
|
108
|
-
},
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
`;
|
|
112
|
-
}
|
|
1
|
+
export function generateStorageApi(): string {
|
|
2
|
+
return `
|
|
3
|
+
function createStorageApi(
|
|
4
|
+
ctx: AppflareContext,
|
|
5
|
+
bucket: R2BucketBinding | undefined,
|
|
6
|
+
): AppflareStorage {
|
|
7
|
+
const assertAuthorized = async (args: StorageAuthorizationArgs): Promise<void> => {
|
|
8
|
+
const allowed = await isStorageAllowed(ctx, args);
|
|
9
|
+
if (!allowed) {
|
|
10
|
+
ctx.error(403, "Storage access denied", {
|
|
11
|
+
path: args.path,
|
|
12
|
+
method: args.method,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const requireBucket = (): R2BucketBinding => {
|
|
18
|
+
if (!bucket) {
|
|
19
|
+
throw new Error(
|
|
20
|
+
"R2 binding is not configured. Set r2 in appflare.config.ts and regenerate artifacts.",
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
return bucket;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
put: async (args) => {
|
|
28
|
+
const path = normalizeStoragePath(args.path);
|
|
29
|
+
await assertAuthorized({
|
|
30
|
+
path: "/" + path,
|
|
31
|
+
method: "put",
|
|
32
|
+
contentType: args.contentType,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
return requireBucket().put(path, args.body, {
|
|
36
|
+
httpMetadata: {
|
|
37
|
+
...(args.httpMetadata ?? {}),
|
|
38
|
+
...(args.contentType ? { contentType: args.contentType } : {}),
|
|
39
|
+
},
|
|
40
|
+
customMetadata: args.customMetadata,
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
get: async (args) => {
|
|
44
|
+
const path = normalizeStoragePath(args.path);
|
|
45
|
+
const method = normalizeStorageMethod(args.method);
|
|
46
|
+
await assertAuthorized({
|
|
47
|
+
path: "/" + path,
|
|
48
|
+
method,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return requireBucket().get(path, {
|
|
52
|
+
onlyIf: args.onlyIf,
|
|
53
|
+
range: args.range,
|
|
54
|
+
});
|
|
55
|
+
},
|
|
56
|
+
delete: async (args) => {
|
|
57
|
+
const path = normalizeStoragePath(args.path);
|
|
58
|
+
await assertAuthorized({
|
|
59
|
+
path: "/" + path,
|
|
60
|
+
method: "delete",
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
await requireBucket().delete(path);
|
|
64
|
+
},
|
|
65
|
+
list: async (args = {}) => {
|
|
66
|
+
await assertAuthorized({
|
|
67
|
+
path: "/" + (args.prefix ?? ""),
|
|
68
|
+
method: args.method ?? "list",
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
return requireBucket().list({
|
|
72
|
+
prefix: args.prefix,
|
|
73
|
+
cursor: args.cursor,
|
|
74
|
+
limit: args.limit,
|
|
75
|
+
delimiter: args.delimiter,
|
|
76
|
+
include: args.include,
|
|
77
|
+
});
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
`;
|
|
82
|
+
}
|