appflare 0.2.38 → 0.2.40
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/cli/generate.ts +47 -0
- package/cli/templates/auth/config.ts +2 -2
- package/cli/templates/handlers/generators/handlers.ts +3 -2
- package/cli/templates/handlers/generators/types/context.ts +30 -7
- package/cli/templates/handlers/index.ts +4 -1
- package/cli/templates/handlers/types.ts +4 -2
- package/dist/cli/index.js +83 -74
- package/dist/cli/index.mjs +83 -74
- package/package.json +1 -1
package/cli/generate.ts
CHANGED
|
@@ -36,6 +36,46 @@ function extractRolesFromConfig(config: LoadedAppflareConfig["config"]): string[
|
|
|
36
36
|
return [];
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
type AdditionalField = { name: string; tsType: string };
|
|
40
|
+
|
|
41
|
+
function extractAdditionalFields(config: LoadedAppflareConfig["config"]): AdditionalField[] {
|
|
42
|
+
const options = config.auth.options as Record<string, unknown> | undefined;
|
|
43
|
+
const userSection = options?.user as Record<string, unknown> | undefined;
|
|
44
|
+
const raw = userSection?.additionalFields as Record<string, { type: string }> | undefined;
|
|
45
|
+
if (!raw || typeof raw !== "object") return [];
|
|
46
|
+
|
|
47
|
+
const typeMap: Record<string, string> = {
|
|
48
|
+
string: "string",
|
|
49
|
+
number: "number",
|
|
50
|
+
boolean: "boolean",
|
|
51
|
+
date: "Date",
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
return Object.entries(raw)
|
|
55
|
+
.filter(([, v]) => v && typeof v === "object" && "type" in v)
|
|
56
|
+
.map(([name, v]) => ({
|
|
57
|
+
name,
|
|
58
|
+
tsType: typeMap[(v as { type: string }).type] || "unknown",
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function patchAuthSchemaRole(schemaPath: string, roles: string[]): Promise<void> {
|
|
63
|
+
const content = await Bun.file(schemaPath).text();
|
|
64
|
+
const roleType = roles.map((r) => `"${r}"`).join(" | ");
|
|
65
|
+
|
|
66
|
+
const updated = content
|
|
67
|
+
.replace(
|
|
68
|
+
/(import.*?from\s+["']drizzle-orm\/sqlite-core["'])/,
|
|
69
|
+
"$1\nimport { customType } from \"drizzle-orm/sqlite-core\"",
|
|
70
|
+
)
|
|
71
|
+
.replace(
|
|
72
|
+
/role:\s*text\(["']role["']\)/,
|
|
73
|
+
`role: customType<{ data: ${roleType}; dataNotNull: ${roleType} }>({ dataType: () => "text" })("role")`,
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
await Bun.write(schemaPath, updated);
|
|
77
|
+
}
|
|
78
|
+
|
|
39
79
|
function toConfigRelativePath(configDir: string, absolutePath: string): string {
|
|
40
80
|
const relativePath = relative(configDir, absolutePath).replace(/\\/g, "/");
|
|
41
81
|
return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
@@ -96,6 +136,7 @@ export async function generateArtifacts(
|
|
|
96
136
|
);
|
|
97
137
|
|
|
98
138
|
const roles = extractRolesFromConfig(config);
|
|
139
|
+
const additionalFields = extractAdditionalFields(config);
|
|
99
140
|
|
|
100
141
|
const serverSource = generateServerSource(
|
|
101
142
|
config.auth.basePath,
|
|
@@ -118,6 +159,7 @@ export async function generateArtifacts(
|
|
|
118
159
|
discoveredHandlers,
|
|
119
160
|
config.r2[0]?.binding,
|
|
120
161
|
roles,
|
|
162
|
+
additionalFields,
|
|
121
163
|
);
|
|
122
164
|
const authConfigSource = generateAuthConfigSource(configImport);
|
|
123
165
|
const drizzleSchemaPaths = compiledSchema
|
|
@@ -201,6 +243,11 @@ export async function generateArtifacts(
|
|
|
201
243
|
}
|
|
202
244
|
process.stdout.write(`🔐 Auth schema (${(performance.now() - t0).toFixed(0)}ms)\n`);
|
|
203
245
|
|
|
246
|
+
if (roles.length > 0) {
|
|
247
|
+
await patchAuthSchemaRole(authSchemaPath, roles);
|
|
248
|
+
process.stdout.write(`🔧 Patched role type (${(performance.now() - t0).toFixed(0)}ms)\n`);
|
|
249
|
+
}
|
|
250
|
+
|
|
204
251
|
function generatedTsconfig(overrides: Record<string, unknown> = {}) {
|
|
205
252
|
return {
|
|
206
253
|
compilerOptions: {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { generateTypes } from "../types";
|
|
2
|
+
import type { AdditionalField } from "../types";
|
|
2
3
|
|
|
3
|
-
export function generateHandlersSource(schemaImportPath: string, roles: string[] = []): string {
|
|
4
|
+
export function generateHandlersSource(schemaImportPath: string, roles: string[] = [], additionalFields: AdditionalField[] = []): string {
|
|
4
5
|
return `import type { Context } from "hono";
|
|
5
6
|
import type { D1Database } from "@cloudflare/workers-types";
|
|
6
7
|
import { drizzle } from "drizzle-orm/d1";
|
|
@@ -8,6 +9,6 @@ import { z, type ZodRawShape } from "zod";
|
|
|
8
9
|
import * as authSchema from "./auth.schema";
|
|
9
10
|
import * as schema from "${schemaImportPath}";
|
|
10
11
|
|
|
11
|
-
${generateTypes(roles)}
|
|
12
|
+
${generateTypes(roles, additionalFields)}
|
|
12
13
|
`;
|
|
13
14
|
}
|
|
@@ -1,13 +1,36 @@
|
|
|
1
|
-
export function generateTypesContextSection(
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
export function generateTypesContextSection(
|
|
2
|
+
roles: string[] = [],
|
|
3
|
+
additionalFields: Array<{ name: string; tsType: string }> = [],
|
|
4
|
+
): string {
|
|
5
|
+
const additionalFieldLines = additionalFields.map(
|
|
6
|
+
(f) => `\t${f.name}?: ${f.tsType} | null;`,
|
|
7
|
+
).join("\n");
|
|
8
|
+
|
|
9
|
+
const adminFieldLines = roles.length > 0
|
|
10
|
+
? [
|
|
11
|
+
"\trole: UserRole;",
|
|
12
|
+
"\tbanned: boolean | null;",
|
|
13
|
+
"\tbanReason?: string | null | undefined;",
|
|
14
|
+
"\tbanExpires?: Date | null | undefined;",
|
|
15
|
+
].join("\n")
|
|
16
|
+
: "";
|
|
17
|
+
|
|
18
|
+
const userFields = [adminFieldLines, additionalFieldLines].filter(Boolean).join("\n");
|
|
19
|
+
|
|
20
|
+
const userType = roles.length > 0
|
|
21
|
+
? `export type UserRole = ${roles.map((r) => `"${r}"`).join(" | ")};
|
|
22
|
+
type User = import("better-auth").User & {
|
|
23
|
+
${userFields}
|
|
24
|
+
};`
|
|
25
|
+
: additionalFields.length > 0
|
|
26
|
+
? `type User = import("better-auth").User & {
|
|
27
|
+
${userFields}
|
|
28
|
+
};`
|
|
29
|
+
: "type User = import(\"better-auth\").User;";
|
|
7
30
|
|
|
8
31
|
return `type AuthSession = typeof auth.$Infer.Session;
|
|
9
32
|
type AuthAdapter = Awaited<typeof auth.$context>["internalAdapter"];
|
|
10
|
-
${
|
|
33
|
+
${userType}
|
|
11
34
|
type Session = AuthSession['session']
|
|
12
35
|
|
|
13
36
|
export type StoragePutArgs = {
|
|
@@ -4,6 +4,8 @@ import { generateExecutionSource } from "./generators/execution";
|
|
|
4
4
|
import { generateHandlersSource } from "./generators/handlers";
|
|
5
5
|
import { generateRegistration } from "./registration";
|
|
6
6
|
|
|
7
|
+
export type AdditionalField = { name: string; tsType: string };
|
|
8
|
+
|
|
7
9
|
export type GeneratedHandlerArtifact = {
|
|
8
10
|
relativePath: string;
|
|
9
11
|
source: string;
|
|
@@ -14,8 +16,9 @@ export function generateHandlersArtifacts(
|
|
|
14
16
|
operations: DiscoveredHandlerOperation[],
|
|
15
17
|
defaultR2Binding?: string,
|
|
16
18
|
roles: string[] = [],
|
|
19
|
+
additionalFields: AdditionalField[] = [],
|
|
17
20
|
): GeneratedHandlerArtifact[] {
|
|
18
|
-
const handlersSource = generateHandlersSource(schemaImportPath, roles);
|
|
21
|
+
const handlersSource = generateHandlersSource(schemaImportPath, roles, additionalFields);
|
|
19
22
|
|
|
20
23
|
const contextSource = generateContextSource(defaultR2Binding);
|
|
21
24
|
|
|
@@ -4,12 +4,14 @@ import { generateTypesQueryRuntimeSection } from "./generators/types/query-runti
|
|
|
4
4
|
import { generateTypesContextSection } from "./generators/types/context";
|
|
5
5
|
import { generateTypesOperationsSection } from "./generators/types/operations";
|
|
6
6
|
|
|
7
|
-
export
|
|
7
|
+
export type AdditionalField = { name: string; tsType: string };
|
|
8
|
+
|
|
9
|
+
export function generateTypes(roles: string[] = [], additionalFields: AdditionalField[] = []): string {
|
|
8
10
|
return [
|
|
9
11
|
generateTypesCoreSection(),
|
|
10
12
|
generateTypesQueryDefinitionsSection(),
|
|
11
13
|
generateTypesQueryRuntimeSection(),
|
|
12
|
-
generateTypesContextSection(roles),
|
|
14
|
+
generateTypesContextSection(roles, additionalFields),
|
|
13
15
|
generateTypesOperationsSection(),
|
|
14
16
|
].join("\n\n");
|
|
15
17
|
}
|