appflare 0.2.15 → 0.2.17
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 +27 -0
- package/cli/schema-compiler.ts +432 -2
- package/cli/templates/dashboard/builders/table-routes/fragments.ts +8 -5
- package/cli/templates/dashboard/builders/table-routes/table/index.ts +1 -1
- package/cli/templates/dashboard/builders/table-routes/users/html/table.ts +3 -2
- package/cli/templates/handlers/generators/types/query-definitions/filter-and-where-types.ts +98 -7
- package/cli/templates/handlers/generators/types/query-definitions/query-api-types.ts +4 -2
- package/cli/templates/handlers/generators/types/query-definitions/query-helper-functions.ts +360 -11
- package/cli/templates/handlers/generators/types/query-definitions/schema-and-table-types.ts +170 -25
- package/cli/templates/handlers/generators/types/query-runtime/runtime-aggregate-and-footer.ts +14 -4
- package/cli/templates/handlers/generators/types/query-runtime/runtime-read.ts +52 -16
- package/cli/templates/handlers/generators/types/query-runtime/runtime-write.ts +546 -7
- package/dist/cli/index.js +1609 -393
- package/dist/cli/index.mjs +1609 -393
- package/dist/index.d.mts +27 -1
- package/dist/index.d.ts +27 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/schema.ts +57 -1
- package/dist/cli/index.d.mts +0 -2
- package/dist/cli/index.d.ts +0 -2
package/dist/cli/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import {Command}from'commander';import
|
|
2
|
+
import {Command}from'commander';import na from'chokidar';import {existsSync}from'fs';import {resolve,isAbsolute,dirname,relative,extname}from'path';import {mkdir,readdir}from'fs/promises';import {pathToFileURL}from'url';import*as g from'typescript';import {z as z$1}from'zod';function te(e){return `import { betterAuth } from "better-auth";
|
|
3
3
|
import { withCloudflare } from "better-auth-cloudflare";
|
|
4
4
|
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
5
5
|
import { drizzle } from "drizzle-orm/d1";
|
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
KVNamespace,
|
|
10
10
|
} from "@cloudflare/workers-types";
|
|
11
11
|
import * as Schema from "./auth.schema";
|
|
12
|
-
import config from "${
|
|
12
|
+
import config from "${e}";
|
|
13
13
|
|
|
14
14
|
type CloudflareBindings = {
|
|
15
15
|
DATABASE: D1Database;
|
|
@@ -55,7 +55,7 @@ export const createAuth = (
|
|
|
55
55
|
});
|
|
56
56
|
};
|
|
57
57
|
export const auth = createAuth();
|
|
58
|
-
`}function
|
|
58
|
+
`}function ne(){return `import { createAuthClient, type BetterAuthClientOptions } from "better-auth/client";
|
|
59
59
|
import type {
|
|
60
60
|
AppflareAuth,
|
|
61
61
|
AppflareAuthTokenResolver,
|
|
@@ -164,22 +164,22 @@ export function createAppflare<Options extends BetterAuthClientOptions = Inferre
|
|
|
164
164
|
): Appflare<Options> {
|
|
165
165
|
return new Appflare(options);
|
|
166
166
|
}
|
|
167
|
-
`}function
|
|
168
|
-
`)}function
|
|
167
|
+
`}function Cn(e){let t=e.replace(/[^A-Za-z0-9_]/g,"_");return /^[0-9]/.test(t)?`_${t}`:t||"_route"}function re(e){return e.split(/[^A-Za-z0-9]+/).filter(Boolean).map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join("")}function Pn(e){return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)?e:JSON.stringify(e)}function ae(e){let t={children:new Map};for(let n of e){let r=t;for(let a of n.segments){let o=r.children.get(a);o||(o={children:new Map},r.children.set(a,o)),r=o;}r.operation=n;}return t}function V(e,t=1){let n=" ".repeat(t),r=" ".repeat(t+1),a=Array.from(e.children.entries()).sort(([i],[s])=>i.localeCompare(s));if(a.length===0)return e.operation?`${e.operation.alias}Route(runtime)`:"{}";let o=["{"];for(let[i,s]of a)o.push(`${r}${Pn(i)}: ${V(s,t+1)},`);return e.operation&&(o.push(`${r}run: ${e.operation.alias}Route(runtime).run,`),o.push(`${r}schema: ${e.operation.alias}Route(runtime).schema,`),e.operation.kind==="query"&&o.push(`${r}subscribe: ${e.operation.alias}Route(runtime).subscribe,`)),o.push(`${n}}`),o.join(`
|
|
168
|
+
`)}function Dn(e,t){if(e.kind!=="query"&&e.kind!=="mutation")return null;let n=e.clientSegments&&e.clientSegments.length>0?e.clientSegments:e.routePath.replace(/^\//,"").split("/").filter(Boolean).slice(1);if(n.length===0)return null;let r=Cn(`op_${t}_${e.kind}_${n.join("_")}`);return {kind:e.kind,routePath:e.routePath,queryName:e.handlerName??n.join("/"),segments:n,importPath:e.clientImportPath,exportName:e.exportName,alias:r,schemaConst:`${r}Schema`,typeBase:`${re(e.kind)}${re(n.join("_"))}`}}function Fn(e){let t=`${e.typeBase}Input`,n=`${e.typeBase}Output`,r=`${e.typeBase}Schema`,a=e.kind==="query"?"GET":"POST";return e.kind==="query"?`const ${e.alias}Route = (
|
|
169
169
|
runtime: RequestRuntime,
|
|
170
|
-
): AppflareQueryRouteClient<typeof ${
|
|
171
|
-
const run: AppflareQueryRouteClient<typeof ${
|
|
172
|
-
...params: AppflareRunParams<${
|
|
170
|
+
): AppflareQueryRouteClient<typeof ${e.schemaConst}, ${n}> => {
|
|
171
|
+
const run: AppflareQueryRouteClient<typeof ${e.schemaConst}, ${n}>["run"] = async (
|
|
172
|
+
...params: AppflareRunParams<${t}>
|
|
173
173
|
) => {
|
|
174
|
-
const { args, options } = resolveRunParams<${
|
|
174
|
+
const { args, options } = resolveRunParams<${t}>(params);
|
|
175
175
|
const mergedOptions = mergeRouteOptions(runtime.options, options);
|
|
176
176
|
const resultOptions: AppflareRouteCallOptions<"return"> = {
|
|
177
177
|
...(mergedOptions ?? {}),
|
|
178
178
|
errorMode: "return",
|
|
179
179
|
};
|
|
180
|
-
const parsed = ${
|
|
180
|
+
const parsed = ${e.schemaConst}.parse(args);
|
|
181
181
|
return requestRoute<${n}>(runtime.endpoint, {
|
|
182
|
-
route: ${JSON.stringify(
|
|
182
|
+
route: ${JSON.stringify(e.routePath)},
|
|
183
183
|
method: ${JSON.stringify(a)},
|
|
184
184
|
input: parsed,
|
|
185
185
|
options: resultOptions,
|
|
@@ -193,9 +193,9 @@ export function createAppflare<Options extends BetterAuthClientOptions = Inferre
|
|
|
193
193
|
args,
|
|
194
194
|
requestOptions,
|
|
195
195
|
signal,
|
|
196
|
-
}: AppflareQuerySubscribeOptions<${
|
|
196
|
+
}: AppflareQuerySubscribeOptions<${t}, ${n}>): AppflareRealtimeSubscription => {
|
|
197
197
|
const mergedOptions = mergeRouteOptions(runtime.options, requestOptions);
|
|
198
|
-
const parsedArgs = ${
|
|
198
|
+
const parsedArgs = ${e.schemaConst}.parse(normalizeRouteInput(args));
|
|
199
199
|
const requestAuthToken = resolveRealtimeAuthToken(authToken, mergedOptions?.headers);
|
|
200
200
|
|
|
201
201
|
let removed = false;
|
|
@@ -254,7 +254,7 @@ export function createAppflare<Options extends BetterAuthClientOptions = Inferre
|
|
|
254
254
|
route: "/realtime/subscribe",
|
|
255
255
|
method: "POST",
|
|
256
256
|
input: {
|
|
257
|
-
queryName: ${JSON.stringify(
|
|
257
|
+
queryName: ${JSON.stringify(e.queryName)},
|
|
258
258
|
args: parsedArgs,
|
|
259
259
|
authToken: resolvedAuthToken,
|
|
260
260
|
},
|
|
@@ -325,21 +325,21 @@ export function createAppflare<Options extends BetterAuthClientOptions = Inferre
|
|
|
325
325
|
run,
|
|
326
326
|
subscribe,
|
|
327
327
|
};
|
|
328
|
-
};`:`const ${
|
|
328
|
+
};`:`const ${e.alias}Route = (
|
|
329
329
|
runtime: RequestRuntime,
|
|
330
|
-
): AppflareRouteClient<typeof ${
|
|
331
|
-
const run: AppflareRouteClient<typeof ${
|
|
332
|
-
...params: AppflareRunParams<${
|
|
330
|
+
): AppflareRouteClient<typeof ${e.schemaConst}, ${n}> => {
|
|
331
|
+
const run: AppflareRouteClient<typeof ${e.schemaConst}, ${n}>["run"] = async (
|
|
332
|
+
...params: AppflareRunParams<${t}>
|
|
333
333
|
) => {
|
|
334
|
-
const { args, options } = resolveRunParams<${
|
|
334
|
+
const { args, options } = resolveRunParams<${t}>(params);
|
|
335
335
|
const mergedOptions = mergeRouteOptions(runtime.options, options);
|
|
336
336
|
const resultOptions: AppflareRouteCallOptions<"return"> = {
|
|
337
337
|
...(mergedOptions ?? {}),
|
|
338
338
|
errorMode: "return",
|
|
339
339
|
};
|
|
340
|
-
const parsed = ${
|
|
340
|
+
const parsed = ${e.schemaConst}.parse(args);
|
|
341
341
|
return requestRoute<${n}>(runtime.endpoint, {
|
|
342
|
-
route: ${JSON.stringify(
|
|
342
|
+
route: ${JSON.stringify(e.routePath)},
|
|
343
343
|
method: ${JSON.stringify(a)},
|
|
344
344
|
input: parsed,
|
|
345
345
|
options: resultOptions,
|
|
@@ -351,15 +351,15 @@ export function createAppflare<Options extends BetterAuthClientOptions = Inferre
|
|
|
351
351
|
schema: ${r},
|
|
352
352
|
run,
|
|
353
353
|
};
|
|
354
|
-
};`}function
|
|
355
|
-
`),o=
|
|
356
|
-
export type ${
|
|
357
|
-
export type ${
|
|
358
|
-
export const ${
|
|
354
|
+
};`}function B(e){let t=e.map((u,c)=>Dn(u,c)).filter(u=>u!==null),n=t.filter(u=>u.kind==="query"),r=t.filter(u=>u.kind==="mutation"),a=t.map(u=>`import { ${u.exportName} as ${u.alias} } from "${u.importPath}";`).join(`
|
|
355
|
+
`),o=t.map(u=>{let c=`${u.typeBase}Input`,f=`${u.typeBase}Output`,d=`${u.typeBase}Schema`;return `const ${u.schemaConst} = z.object(${u.alias}.definition.args);
|
|
356
|
+
export type ${c} = z.input<typeof ${u.schemaConst}>;
|
|
357
|
+
export type ${f} = Awaited<ReturnType<typeof ${u.alias}.definition.handler>>;
|
|
358
|
+
export const ${d} = ${u.schemaConst};`}).join(`
|
|
359
359
|
|
|
360
|
-
`),i=
|
|
360
|
+
`),i=t.map(u=>Fn(u)).join(`
|
|
361
361
|
|
|
362
|
-
`),s=
|
|
362
|
+
`),s=V(ae(n)),l=V(ae(r));return `import betterFetch from "better-fetch";
|
|
363
363
|
import { z } from "zod";
|
|
364
364
|
import type {
|
|
365
365
|
AppflareErrorMode,
|
|
@@ -736,11 +736,11 @@ export function createMutationsClient(
|
|
|
736
736
|
|
|
737
737
|
export type QueriesClient = ReturnType<typeof createQueriesClient>;
|
|
738
738
|
export type MutationsClient = ReturnType<typeof createMutationsClient>;
|
|
739
|
-
`}function
|
|
739
|
+
`}function oe(){return `export * from "./types";
|
|
740
740
|
export * from "./appflare";
|
|
741
741
|
export * from "./storage";
|
|
742
742
|
export * from "./handlers";
|
|
743
|
-
`}function
|
|
743
|
+
`}function ie(){return `import type { StorageClient, StorageSignedUrlResponse, StorageListResponse } from "./types";
|
|
744
744
|
|
|
745
745
|
type AuthTokenResolver = (() => string | Promise<string>) | undefined;
|
|
746
746
|
|
|
@@ -917,8 +917,8 @@ export function createStorageClient(
|
|
|
917
917
|
},
|
|
918
918
|
};
|
|
919
919
|
}
|
|
920
|
-
`}function
|
|
921
|
-
import type appflareConfig from "${
|
|
920
|
+
`}function se(e){return `import { createAuthClient, type BetterAuthClientOptions } from "better-auth/client";
|
|
921
|
+
import type appflareConfig from "${e}";
|
|
922
922
|
|
|
923
923
|
export type AppflareConfig = typeof appflareConfig;
|
|
924
924
|
export type InferredAuthOptions = AppflareConfig["auth"]["clientOptions"];
|
|
@@ -1098,11 +1098,11 @@ export type RealtimeSubscriptionResponse = {
|
|
|
1098
1098
|
};
|
|
1099
1099
|
};
|
|
1100
1100
|
};
|
|
1101
|
-
`}function
|
|
1101
|
+
`}function le(e,t){return [{relativePath:"client/index.ts",source:oe()},{relativePath:"client/types.ts",source:se(e)},{relativePath:"client/storage.ts",source:ie()},{relativePath:"client/handlers.ts",source:B(t)},{relativePath:"client/appflare.ts",source:ne()}]}function ce(e){return `import { defineConfig } from "drizzle-kit";
|
|
1102
1102
|
|
|
1103
1103
|
export default defineConfig({
|
|
1104
1104
|
dialect: "sqlite",
|
|
1105
|
-
schema: ${JSON.stringify(
|
|
1105
|
+
schema: ${JSON.stringify(e)},
|
|
1106
1106
|
driver: "d1-http",
|
|
1107
1107
|
dbCredentials: {
|
|
1108
1108
|
accountId: "accountId",
|
|
@@ -1110,7 +1110,7 @@ export default defineConfig({
|
|
|
1110
1110
|
token: "token",
|
|
1111
1111
|
},
|
|
1112
1112
|
});
|
|
1113
|
-
`}function
|
|
1113
|
+
`}function ue(){return `
|
|
1114
1114
|
|
|
1115
1115
|
import { getHeaders } from "./server";
|
|
1116
1116
|
export async function resolveSession(
|
|
@@ -1144,7 +1144,7 @@ export async function resolveSession(
|
|
|
1144
1144
|
}
|
|
1145
1145
|
}
|
|
1146
1146
|
|
|
1147
|
-
`}function
|
|
1147
|
+
`}function de(){return `
|
|
1148
1148
|
type SchedulerQueueBinding = {
|
|
1149
1149
|
send: (body: unknown, options?: SchedulerEnqueueOptions) => Promise<void>;
|
|
1150
1150
|
};
|
|
@@ -1159,7 +1159,7 @@ type R2BucketBinding = {
|
|
|
1159
1159
|
options?: { expiresIn?: number },
|
|
1160
1160
|
) => Promise<URL>;
|
|
1161
1161
|
};
|
|
1162
|
-
`}function
|
|
1162
|
+
`}function pe(){return `
|
|
1163
1163
|
export function createScheduler(
|
|
1164
1164
|
queue?: SchedulerQueueBinding,
|
|
1165
1165
|
): Scheduler {
|
|
@@ -1180,7 +1180,7 @@ export function createScheduler(
|
|
|
1180
1180
|
},
|
|
1181
1181
|
};
|
|
1182
1182
|
}
|
|
1183
|
-
`}function
|
|
1183
|
+
`}function me(){return `
|
|
1184
1184
|
function createContextErrorHelpers() {
|
|
1185
1185
|
return {
|
|
1186
1186
|
error: (status: number, message: string, details?: unknown) => {
|
|
@@ -1188,7 +1188,7 @@ function createContextErrorHelpers() {
|
|
|
1188
1188
|
},
|
|
1189
1189
|
};
|
|
1190
1190
|
}
|
|
1191
|
-
`}function
|
|
1191
|
+
`}function ge(){return `
|
|
1192
1192
|
function normalizeStoragePath(path: string): string {
|
|
1193
1193
|
const trimmed = path.trim();
|
|
1194
1194
|
if (trimmed.length === 0) {
|
|
@@ -1244,7 +1244,7 @@ function buildSignedRequest(
|
|
|
1244
1244
|
headers,
|
|
1245
1245
|
});
|
|
1246
1246
|
}
|
|
1247
|
-
`}function
|
|
1247
|
+
`}function fe(){return `
|
|
1248
1248
|
function createStorageApi(
|
|
1249
1249
|
ctx: AppflareContext,
|
|
1250
1250
|
bucket: R2BucketBinding | undefined,
|
|
@@ -1353,13 +1353,13 @@ function createStorageApi(
|
|
|
1353
1353
|
},
|
|
1354
1354
|
};
|
|
1355
1355
|
}
|
|
1356
|
-
`}function
|
|
1356
|
+
`}function he(e){return `
|
|
1357
1357
|
export function createSchedulerExecutionContext(
|
|
1358
1358
|
env: Record<string, unknown>,
|
|
1359
1359
|
options: RegisterHandlersOptions,
|
|
1360
1360
|
): AppflareContext {
|
|
1361
1361
|
const database = env[options.databaseBinding] as D1Database;
|
|
1362
|
-
const r2Binding = options.r2Binding ?? ${JSON.stringify(
|
|
1362
|
+
const r2Binding = options.r2Binding ?? ${JSON.stringify(e??"")};
|
|
1363
1363
|
const storageBucket = r2Binding
|
|
1364
1364
|
? (env[r2Binding] as R2BucketBinding | undefined)
|
|
1365
1365
|
: undefined;
|
|
@@ -1393,7 +1393,7 @@ export async function createExecutionContext(
|
|
|
1393
1393
|
options: RegisterHandlersOptions,
|
|
1394
1394
|
): Promise<AppflareContext> {
|
|
1395
1395
|
const database = c.env[options.databaseBinding] as D1Database;
|
|
1396
|
-
const r2Binding = options.r2Binding ?? ${JSON.stringify(
|
|
1396
|
+
const r2Binding = options.r2Binding ?? ${JSON.stringify(e??"")};
|
|
1397
1397
|
const storageBucket = r2Binding
|
|
1398
1398
|
? (c.env[r2Binding] as R2BucketBinding | undefined)
|
|
1399
1399
|
: undefined;
|
|
@@ -1430,7 +1430,7 @@ export async function createExecutionContext(
|
|
|
1430
1430
|
ctx.storage = createStorageApi(ctx, storageBucket);
|
|
1431
1431
|
return ctx;
|
|
1432
1432
|
}
|
|
1433
|
-
`}function
|
|
1433
|
+
`}function be(e){return `import type { Context } from "hono";
|
|
1434
1434
|
import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@cloudflare/workers-types";
|
|
1435
1435
|
import { createAuth } from "./auth.config";
|
|
1436
1436
|
import {
|
|
@@ -1449,20 +1449,20 @@ import {
|
|
|
1449
1449
|
createQueryDb,
|
|
1450
1450
|
} from "./handlers";
|
|
1451
1451
|
|
|
1452
|
-
${
|
|
1452
|
+
${de()}
|
|
1453
1453
|
|
|
1454
|
-
${
|
|
1454
|
+
${ue()}
|
|
1455
1455
|
|
|
1456
|
-
${
|
|
1456
|
+
${pe()}
|
|
1457
1457
|
|
|
1458
|
-
${
|
|
1458
|
+
${me()}
|
|
1459
1459
|
|
|
1460
|
-
${
|
|
1460
|
+
${ge()}
|
|
1461
1461
|
|
|
1462
|
-
${
|
|
1462
|
+
${fe()}
|
|
1463
1463
|
|
|
1464
|
-
${
|
|
1465
|
-
`}function
|
|
1464
|
+
${he(e)}
|
|
1465
|
+
`}function ye(){return `
|
|
1466
1466
|
export async function executeOperation(
|
|
1467
1467
|
c: Context<WorkerEnv>,
|
|
1468
1468
|
operation: RegisteredOperation<ZodRawShape, unknown>,
|
|
@@ -1498,7 +1498,7 @@ export function handleOperationError(
|
|
|
1498
1498
|
return c.json({ message: (error as Error).message ?? "Unknown error" }, 500);
|
|
1499
1499
|
}
|
|
1500
1500
|
|
|
1501
|
-
`}function
|
|
1501
|
+
`}function we(){return `import type { Context } from "hono";
|
|
1502
1502
|
import { ZodError, type ZodRawShape } from "zod";
|
|
1503
1503
|
import {
|
|
1504
1504
|
type AppflareContext,
|
|
@@ -1507,8 +1507,8 @@ import {
|
|
|
1507
1507
|
type WorkerEnv,
|
|
1508
1508
|
} from "./handlers";
|
|
1509
1509
|
|
|
1510
|
-
${
|
|
1511
|
-
`}function
|
|
1510
|
+
${ye()}
|
|
1511
|
+
`}function xe(){return `import { betterAuth } from "better-auth";
|
|
1512
1512
|
import { auth } from "./auth.config";
|
|
1513
1513
|
import {
|
|
1514
1514
|
and,
|
|
@@ -1611,7 +1611,7 @@ export async function isStorageAllowed(
|
|
|
1611
1611
|
|
|
1612
1612
|
return false;
|
|
1613
1613
|
}
|
|
1614
|
-
`}function
|
|
1614
|
+
`}function ve(){return `type Primitive = string | number | boolean | Date;
|
|
1615
1615
|
type NonNil<T> = Exclude<T, null | undefined>;
|
|
1616
1616
|
type Friendly<T> = T extends Date ? Date | number : T;
|
|
1617
1617
|
type Comparable<T> = Friendly<Extract<NonNil<T>, Primitive>>;
|
|
@@ -1726,7 +1726,7 @@ type RelationAggregateSelectionInput<TModel extends Record<string, unknown>> = {
|
|
|
1726
1726
|
_avg?: RelationAvgSelectionInput<TModel>;
|
|
1727
1727
|
};
|
|
1728
1728
|
|
|
1729
|
-
type
|
|
1729
|
+
type QueryNativeWithRelationInput<TEntry> =
|
|
1730
1730
|
| (Extract<TEntry, true> extends never ? never : true)
|
|
1731
1731
|
| (Extract<TEntry, Record<string, unknown>> extends infer TRelation
|
|
1732
1732
|
? TRelation extends Record<string, unknown>
|
|
@@ -1734,24 +1734,57 @@ type QueryWithRelationInput<TEntry> =
|
|
|
1734
1734
|
RelationAggregateSelectionInput<RelationModelFromConfig<TRelation>> & {
|
|
1735
1735
|
where?: WhereInput<RelationModelFromConfig<TRelation>>;
|
|
1736
1736
|
with?: TRelation extends { with?: infer TNestedWith }
|
|
1737
|
-
?
|
|
1737
|
+
? QueryWithInputForTable<TableName, TNestedWith>
|
|
1738
1738
|
: never;
|
|
1739
1739
|
}
|
|
1740
1740
|
: never
|
|
1741
1741
|
: never);
|
|
1742
1742
|
|
|
1743
|
-
type
|
|
1743
|
+
type QueryManyToManyWithRelationInput<TTargetTable extends TableName> =
|
|
1744
|
+
| true
|
|
1745
|
+
| (Omit<NonNullable<TableFindManyArgs<TTargetTable>>, "where" | "with"> &
|
|
1746
|
+
RelationAggregateSelectionInput<TableModel<TTargetTable>> & {
|
|
1747
|
+
where?: WhereInput<TableModel<TTargetTable>>;
|
|
1748
|
+
with?: QueryWithInputForTable<
|
|
1749
|
+
TTargetTable,
|
|
1750
|
+
NativeFindManyWith<TTargetTable>
|
|
1751
|
+
>;
|
|
1752
|
+
});
|
|
1753
|
+
|
|
1754
|
+
type QueryWithRelationInputForTable<
|
|
1755
|
+
TSourceTable extends TableName,
|
|
1756
|
+
TRelationName extends string,
|
|
1757
|
+
TEntry,
|
|
1758
|
+
> = [ManyToManyTargetTableName<TSourceTable, TRelationName>] extends [never]
|
|
1759
|
+
? QueryNativeWithRelationInput<TEntry>
|
|
1760
|
+
: QueryManyToManyWithRelationInput<
|
|
1761
|
+
Extract<ManyToManyTargetTableName<TSourceTable, TRelationName>, TableName>
|
|
1762
|
+
>;
|
|
1763
|
+
|
|
1764
|
+
type QueryWithInputForTable<
|
|
1765
|
+
TSourceTable extends TableName,
|
|
1766
|
+
TWith,
|
|
1767
|
+
> = TWith extends Record<string, unknown>
|
|
1744
1768
|
? {
|
|
1745
|
-
[K in keyof TWith]?:
|
|
1769
|
+
[K in keyof TWith]?: QueryWithRelationInputForTable<
|
|
1770
|
+
TSourceTable,
|
|
1771
|
+
Extract<K, string>,
|
|
1772
|
+
TWith[K]
|
|
1773
|
+
>;
|
|
1746
1774
|
}
|
|
1747
1775
|
: TWith;
|
|
1748
1776
|
|
|
1777
|
+
type QueryWithInput<TName extends TableName, TWith> = QueryWithInputForTable<
|
|
1778
|
+
TName,
|
|
1779
|
+
TWith
|
|
1780
|
+
>;
|
|
1781
|
+
|
|
1749
1782
|
export type QueryFindManyArgs<TName extends TableName> = Omit<
|
|
1750
1783
|
NonNullable<TableFindManyArgs<TName>>,
|
|
1751
1784
|
"where" | "with"
|
|
1752
1785
|
> & {
|
|
1753
1786
|
where?: WhereInput<TableModel<TName>>;
|
|
1754
|
-
with?: QueryWithInput<NativeFindManyWith<TName>>;
|
|
1787
|
+
with?: QueryWithInput<TName, NativeFindManyWith<TName>>;
|
|
1755
1788
|
};
|
|
1756
1789
|
|
|
1757
1790
|
export type QueryFindFirstArgs<TName extends TableName> = Omit<
|
|
@@ -1759,11 +1792,69 @@ export type QueryFindFirstArgs<TName extends TableName> = Omit<
|
|
|
1759
1792
|
"where" | "with"
|
|
1760
1793
|
> & {
|
|
1761
1794
|
where?: WhereInput<TableModel<TName>>;
|
|
1762
|
-
with?: QueryWithInput<NativeFindFirstWith<TName>>;
|
|
1795
|
+
with?: QueryWithInput<TName, NativeFindFirstWith<TName>>;
|
|
1796
|
+
};
|
|
1797
|
+
|
|
1798
|
+
type RelationInsertItem<TTargetTable extends TableName> =
|
|
1799
|
+
| TableModel<TTargetTable>
|
|
1800
|
+
| TableInsertModel<TTargetTable>
|
|
1801
|
+
| ("id" extends keyof TableModel<TTargetTable>
|
|
1802
|
+
? TableModel<TTargetTable>["id"]
|
|
1803
|
+
: never);
|
|
1804
|
+
|
|
1805
|
+
type RelationInsertValue<
|
|
1806
|
+
TSourceTable extends TableName,
|
|
1807
|
+
TRelationName extends RuntimeRelationName<TSourceTable>,
|
|
1808
|
+
> = RuntimeRelationTargetTable<TSourceTable, TRelationName> extends infer TTargetTable
|
|
1809
|
+
? TTargetTable extends TableName
|
|
1810
|
+
? RuntimeRelationKind<TSourceTable, TRelationName> extends "one"
|
|
1811
|
+
? RelationInsertItem<TTargetTable>
|
|
1812
|
+
: RelationInsertItem<TTargetTable> | Array<RelationInsertItem<TTargetTable>>
|
|
1813
|
+
: never
|
|
1814
|
+
: never;
|
|
1815
|
+
|
|
1816
|
+
type RelationInsertFields<TName extends TableName> = {
|
|
1817
|
+
[TRelationName in RuntimeRelationName<TName>]?: RelationInsertValue<
|
|
1818
|
+
TName,
|
|
1819
|
+
TRelationName
|
|
1820
|
+
>;
|
|
1821
|
+
};
|
|
1822
|
+
|
|
1823
|
+
type QueryInsertValue<TName extends TableName> = TableInsertScalarModel<TName> &
|
|
1824
|
+
RelationInsertFields<TName>;
|
|
1825
|
+
|
|
1826
|
+
type InsertItemValue<TArgs> = TArgs extends { values: infer TValue }
|
|
1827
|
+
? TValue extends Array<infer TItem>
|
|
1828
|
+
? TItem
|
|
1829
|
+
: TValue
|
|
1830
|
+
: never;
|
|
1831
|
+
|
|
1832
|
+
type InsertRelationNameFromArgs<
|
|
1833
|
+
TName extends TableName,
|
|
1834
|
+
TArgs,
|
|
1835
|
+
> = Extract<keyof InsertItemValue<TArgs>, RuntimeRelationName<TName>>;
|
|
1836
|
+
|
|
1837
|
+
type InsertRelationResultValue<
|
|
1838
|
+
TSourceTable extends TableName,
|
|
1839
|
+
TRelationName extends RuntimeRelationName<TSourceTable>,
|
|
1840
|
+
> = RuntimeRelationTargetTable<TSourceTable, TRelationName> extends infer TTargetTable
|
|
1841
|
+
? TTargetTable extends TableName
|
|
1842
|
+
? RuntimeRelationKind<TSourceTable, TRelationName> extends "one"
|
|
1843
|
+
? TableModel<TTargetTable> | null
|
|
1844
|
+
: Array<TableModel<TTargetTable>>
|
|
1845
|
+
: never
|
|
1846
|
+
: never;
|
|
1847
|
+
|
|
1848
|
+
export type QueryInsertResultRow<
|
|
1849
|
+
TName extends TableName,
|
|
1850
|
+
TArgs extends QueryInsertArgs<TName>,
|
|
1851
|
+
> = TableModel<TName> & {
|
|
1852
|
+
[TRelationName in InsertRelationNameFromArgs<TName, TArgs>]:
|
|
1853
|
+
InsertRelationResultValue<TName, TRelationName>;
|
|
1763
1854
|
};
|
|
1764
1855
|
|
|
1765
1856
|
export type QueryInsertArgs<TName extends TableName> = {
|
|
1766
|
-
values:
|
|
1857
|
+
values: QueryInsertValue<TName> | Array<QueryInsertValue<TName>>;
|
|
1767
1858
|
};
|
|
1768
1859
|
|
|
1769
1860
|
export type QueryUpdateArgs<TName extends TableName> = {
|
|
@@ -1776,8 +1867,8 @@ export type QueryDeleteArgs<TName extends TableName> = {
|
|
|
1776
1867
|
where?: WhereInput<TableModel<TName>>;
|
|
1777
1868
|
limit?: number;
|
|
1778
1869
|
};
|
|
1779
|
-
`}function
|
|
1780
|
-
QueryWithInput<NativeFindManyWith<TName>>;
|
|
1870
|
+
`}function Te(){return `type AggregateWithInput<TName extends TableName> =
|
|
1871
|
+
QueryWithInput<TName, NativeFindManyWith<TName>>;
|
|
1781
1872
|
|
|
1782
1873
|
type NumericFieldKey<TName extends TableName> = NumericModelFieldKey<
|
|
1783
1874
|
TableModel<TName>
|
|
@@ -1882,7 +1973,9 @@ export type QueryTableApi<TName extends TableName> = {
|
|
|
1882
1973
|
>(
|
|
1883
1974
|
args?: TArgs,
|
|
1884
1975
|
) => ApplyFindFirstWithAggregateResult<TableFindFirstResult<TName, TArgs>, TArgs>;
|
|
1885
|
-
insert:
|
|
1976
|
+
insert: <TArgs extends QueryInsertArgs<TName>>(
|
|
1977
|
+
args: TArgs,
|
|
1978
|
+
) => Promise<Array<QueryInsertResultRow<TName, TArgs>>>;
|
|
1886
1979
|
update: (args: QueryUpdateArgs<TName>) => Promise<Array<TableModel<TName>>>;
|
|
1887
1980
|
upsert: (args: QueryUpsertArgs<TName>) => Promise<Array<TableModel<TName>>>;
|
|
1888
1981
|
delete: (args?: QueryDeleteArgs<TName>) => Promise<Array<TableModel<TName>>>;
|
|
@@ -1906,7 +1999,7 @@ export type DbMutationEvent = {
|
|
|
1906
1999
|
export type QueryDbOptions = {
|
|
1907
2000
|
onMutation?: (event: DbMutationEvent) => void;
|
|
1908
2001
|
};
|
|
1909
|
-
`}function
|
|
2002
|
+
`}function Re(){return `function isRecord(value: unknown): value is Record<string, unknown> {
|
|
1910
2003
|
return typeof value === "object" && value !== null;
|
|
1911
2004
|
}
|
|
1912
2005
|
|
|
@@ -2186,8 +2279,292 @@ function buildWhereFilterFromFields(
|
|
|
2186
2279
|
return and(...filters);
|
|
2187
2280
|
}
|
|
2188
2281
|
|
|
2189
|
-
|
|
2190
|
-
|
|
2282
|
+
type ManyToManyRuntimeRelation = {
|
|
2283
|
+
targetTable: string;
|
|
2284
|
+
junctionTable: string;
|
|
2285
|
+
sourceField?: string;
|
|
2286
|
+
targetField?: string;
|
|
2287
|
+
referenceField?: string;
|
|
2288
|
+
targetReferenceField?: string;
|
|
2289
|
+
};
|
|
2290
|
+
|
|
2291
|
+
type RuntimeRelationOne = {
|
|
2292
|
+
kind: "one";
|
|
2293
|
+
targetTable: string;
|
|
2294
|
+
sourceField?: string;
|
|
2295
|
+
referenceField?: string;
|
|
2296
|
+
};
|
|
2297
|
+
|
|
2298
|
+
type RuntimeRelationMany = {
|
|
2299
|
+
kind: "many";
|
|
2300
|
+
targetTable: string;
|
|
2301
|
+
sourceField?: string;
|
|
2302
|
+
referenceField?: string;
|
|
2303
|
+
};
|
|
2304
|
+
|
|
2305
|
+
type RuntimeRelationManyToMany = ManyToManyRuntimeRelation & {
|
|
2306
|
+
kind: "manyToMany";
|
|
2307
|
+
};
|
|
2308
|
+
|
|
2309
|
+
type RuntimeRelation =
|
|
2310
|
+
| RuntimeRelationOne
|
|
2311
|
+
| RuntimeRelationMany
|
|
2312
|
+
| RuntimeRelationManyToMany;
|
|
2313
|
+
|
|
2314
|
+
type RuntimeRelationMap = Record<string, Record<string, RuntimeRelation>>;
|
|
2315
|
+
|
|
2316
|
+
function getRuntimeRelationMap(): RuntimeRelationMap {
|
|
2317
|
+
const rawValue = (mergedSchema as Record<string, unknown>)[
|
|
2318
|
+
"__appflareRelations"
|
|
2319
|
+
];
|
|
2320
|
+
if (!isRecord(rawValue)) {
|
|
2321
|
+
return {};
|
|
2322
|
+
}
|
|
2323
|
+
|
|
2324
|
+
const map: RuntimeRelationMap = {};
|
|
2325
|
+
for (const [tableName, tableValue] of Object.entries(rawValue)) {
|
|
2326
|
+
if (!isRecord(tableValue)) {
|
|
2327
|
+
continue;
|
|
2328
|
+
}
|
|
2329
|
+
|
|
2330
|
+
const relationMap: Record<string, RuntimeRelation> = {};
|
|
2331
|
+
for (const [relationName, relationValue] of Object.entries(tableValue)) {
|
|
2332
|
+
if (!isRecord(relationValue)) {
|
|
2333
|
+
continue;
|
|
2334
|
+
}
|
|
2335
|
+
|
|
2336
|
+
const kind = relationValue.kind;
|
|
2337
|
+
const targetTable = relationValue.targetTable;
|
|
2338
|
+
if (typeof kind !== "string" || typeof targetTable !== "string") {
|
|
2339
|
+
continue;
|
|
2340
|
+
}
|
|
2341
|
+
|
|
2342
|
+
const sourceField =
|
|
2343
|
+
typeof relationValue.sourceField === "string"
|
|
2344
|
+
? relationValue.sourceField
|
|
2345
|
+
: undefined;
|
|
2346
|
+
const referenceField =
|
|
2347
|
+
typeof relationValue.referenceField === "string"
|
|
2348
|
+
? relationValue.referenceField
|
|
2349
|
+
: undefined;
|
|
2350
|
+
|
|
2351
|
+
if (kind === "one") {
|
|
2352
|
+
relationMap[relationName] = {
|
|
2353
|
+
kind: "one",
|
|
2354
|
+
targetTable,
|
|
2355
|
+
sourceField,
|
|
2356
|
+
referenceField,
|
|
2357
|
+
};
|
|
2358
|
+
continue;
|
|
2359
|
+
}
|
|
2360
|
+
|
|
2361
|
+
if (kind === "many") {
|
|
2362
|
+
relationMap[relationName] = {
|
|
2363
|
+
kind: "many",
|
|
2364
|
+
targetTable,
|
|
2365
|
+
sourceField,
|
|
2366
|
+
referenceField,
|
|
2367
|
+
};
|
|
2368
|
+
continue;
|
|
2369
|
+
}
|
|
2370
|
+
|
|
2371
|
+
if (kind === "manyToMany") {
|
|
2372
|
+
const junctionTable = relationValue.junctionTable;
|
|
2373
|
+
if (typeof junctionTable !== "string") {
|
|
2374
|
+
continue;
|
|
2375
|
+
}
|
|
2376
|
+
|
|
2377
|
+
relationMap[relationName] = {
|
|
2378
|
+
kind: "manyToMany",
|
|
2379
|
+
targetTable,
|
|
2380
|
+
junctionTable,
|
|
2381
|
+
sourceField,
|
|
2382
|
+
targetField:
|
|
2383
|
+
typeof relationValue.targetField === "string"
|
|
2384
|
+
? relationValue.targetField
|
|
2385
|
+
: undefined,
|
|
2386
|
+
referenceField,
|
|
2387
|
+
targetReferenceField:
|
|
2388
|
+
typeof relationValue.targetReferenceField === "string"
|
|
2389
|
+
? relationValue.targetReferenceField
|
|
2390
|
+
: undefined,
|
|
2391
|
+
};
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
if (Object.keys(relationMap).length > 0) {
|
|
2396
|
+
map[tableName] = relationMap;
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2399
|
+
|
|
2400
|
+
return map;
|
|
2401
|
+
}
|
|
2402
|
+
|
|
2403
|
+
const runtimeRelationMap = getRuntimeRelationMap();
|
|
2404
|
+
|
|
2405
|
+
function getRuntimeRelation(
|
|
2406
|
+
tableName: string,
|
|
2407
|
+
relationName: string,
|
|
2408
|
+
): RuntimeRelation | undefined {
|
|
2409
|
+
return runtimeRelationMap[tableName]?.[relationName];
|
|
2410
|
+
}
|
|
2411
|
+
|
|
2412
|
+
type ManyToManyRuntimeMap = Record<
|
|
2413
|
+
string,
|
|
2414
|
+
Record<string, ManyToManyRuntimeRelation>
|
|
2415
|
+
>;
|
|
2416
|
+
|
|
2417
|
+
function getManyToManyRuntimeMap(): ManyToManyRuntimeMap {
|
|
2418
|
+
const rawValue = (mergedSchema as Record<string, unknown>)[
|
|
2419
|
+
"__appflareManyToMany"
|
|
2420
|
+
];
|
|
2421
|
+
if (!isRecord(rawValue)) {
|
|
2422
|
+
return {};
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
const map: ManyToManyRuntimeMap = {};
|
|
2426
|
+
for (const [tableName, tableValue] of Object.entries(rawValue)) {
|
|
2427
|
+
if (!isRecord(tableValue)) {
|
|
2428
|
+
continue;
|
|
2429
|
+
}
|
|
2430
|
+
|
|
2431
|
+
const relationMap: Record<string, ManyToManyRuntimeRelation> = {};
|
|
2432
|
+
for (const [relationName, relationValue] of Object.entries(tableValue)) {
|
|
2433
|
+
const runtimeRelation = getRuntimeRelation(tableName, relationName);
|
|
2434
|
+
if (!runtimeRelation || runtimeRelation.kind !== "manyToMany") {
|
|
2435
|
+
continue;
|
|
2436
|
+
}
|
|
2437
|
+
|
|
2438
|
+
relationMap[relationName] = {
|
|
2439
|
+
targetTable: runtimeRelation.targetTable,
|
|
2440
|
+
junctionTable: runtimeRelation.junctionTable,
|
|
2441
|
+
sourceField: runtimeRelation.sourceField,
|
|
2442
|
+
targetField: runtimeRelation.targetField,
|
|
2443
|
+
referenceField: runtimeRelation.referenceField,
|
|
2444
|
+
targetReferenceField: runtimeRelation.targetReferenceField,
|
|
2445
|
+
};
|
|
2446
|
+
}
|
|
2447
|
+
|
|
2448
|
+
if (Object.keys(relationMap).length > 0) {
|
|
2449
|
+
map[tableName] = relationMap;
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
|
|
2453
|
+
return map;
|
|
2454
|
+
}
|
|
2455
|
+
|
|
2456
|
+
const manyToManyRuntimeMap = getManyToManyRuntimeMap();
|
|
2457
|
+
|
|
2458
|
+
function getManyToManyRelation(
|
|
2459
|
+
tableName: string,
|
|
2460
|
+
relationName: string,
|
|
2461
|
+
): ManyToManyRuntimeRelation | undefined {
|
|
2462
|
+
return manyToManyRuntimeMap[tableName]?.[relationName];
|
|
2463
|
+
}
|
|
2464
|
+
|
|
2465
|
+
function hasManyToManyRelationsInWith(
|
|
2466
|
+
tableName: string,
|
|
2467
|
+
withValue: unknown,
|
|
2468
|
+
): boolean {
|
|
2469
|
+
if (!isRecord(withValue)) {
|
|
2470
|
+
return false;
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2473
|
+
for (const [relationName, relationValue] of Object.entries(withValue)) {
|
|
2474
|
+
const manyToMany = getManyToManyRelation(tableName, relationName);
|
|
2475
|
+
if (manyToMany) {
|
|
2476
|
+
return true;
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2479
|
+
if (!isRecord(relationValue)) {
|
|
2480
|
+
continue;
|
|
2481
|
+
}
|
|
2482
|
+
|
|
2483
|
+
const nestedWith = relationValue.with;
|
|
2484
|
+
if (
|
|
2485
|
+
hasManyToManyRelationsInWith(relationName, nestedWith) ||
|
|
2486
|
+
(manyToMany &&
|
|
2487
|
+
hasManyToManyRelationsInWith(manyToMany.targetTable, nestedWith))
|
|
2488
|
+
) {
|
|
2489
|
+
return true;
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
|
|
2493
|
+
return false;
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2496
|
+
function flattenManyToManyResult(
|
|
2497
|
+
tableName: string,
|
|
2498
|
+
result: unknown,
|
|
2499
|
+
withValue: unknown,
|
|
2500
|
+
): unknown {
|
|
2501
|
+
if (!isRecord(withValue)) {
|
|
2502
|
+
return result;
|
|
2503
|
+
}
|
|
2504
|
+
|
|
2505
|
+
if (Array.isArray(result)) {
|
|
2506
|
+
return result.map((entry) =>
|
|
2507
|
+
flattenManyToManyResult(tableName, entry, withValue),
|
|
2508
|
+
);
|
|
2509
|
+
}
|
|
2510
|
+
|
|
2511
|
+
if (!isRecord(result)) {
|
|
2512
|
+
return result;
|
|
2513
|
+
}
|
|
2514
|
+
|
|
2515
|
+
const nextRow: Record<string, unknown> = {
|
|
2516
|
+
...result,
|
|
2517
|
+
};
|
|
2518
|
+
|
|
2519
|
+
for (const [relationName, relationValue] of Object.entries(withValue)) {
|
|
2520
|
+
const manyToMany = getManyToManyRelation(tableName, relationName);
|
|
2521
|
+
const currentValue = nextRow[relationName];
|
|
2522
|
+
|
|
2523
|
+
if (manyToMany) {
|
|
2524
|
+
const relationEntries = Array.isArray(currentValue)
|
|
2525
|
+
? currentValue
|
|
2526
|
+
: currentValue === null || currentValue === undefined
|
|
2527
|
+
? []
|
|
2528
|
+
: [currentValue];
|
|
2529
|
+
|
|
2530
|
+
const nestedWith =
|
|
2531
|
+
isRecord(relationValue) && relationValue.with !== undefined
|
|
2532
|
+
? relationValue.with
|
|
2533
|
+
: undefined;
|
|
2534
|
+
|
|
2535
|
+
const flattened = relationEntries
|
|
2536
|
+
.map((entry) => {
|
|
2537
|
+
if (!isRecord(entry)) {
|
|
2538
|
+
return undefined;
|
|
2539
|
+
}
|
|
2540
|
+
|
|
2541
|
+
const targetValue = entry[manyToMany.targetTable];
|
|
2542
|
+
return flattenManyToManyResult(
|
|
2543
|
+
manyToMany.targetTable,
|
|
2544
|
+
targetValue,
|
|
2545
|
+
nestedWith,
|
|
2546
|
+
);
|
|
2547
|
+
})
|
|
2548
|
+
.filter((entry) => entry !== undefined && entry !== null);
|
|
2549
|
+
|
|
2550
|
+
nextRow[relationName] = flattened;
|
|
2551
|
+
continue;
|
|
2552
|
+
}
|
|
2553
|
+
|
|
2554
|
+
if (isRecord(relationValue) && relationValue.with !== undefined) {
|
|
2555
|
+
nextRow[relationName] = flattenManyToManyResult(
|
|
2556
|
+
relationName,
|
|
2557
|
+
currentValue,
|
|
2558
|
+
relationValue.with,
|
|
2559
|
+
);
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
|
|
2563
|
+
return nextRow;
|
|
2564
|
+
}
|
|
2565
|
+
|
|
2566
|
+
function transformWithRelations(withValue: unknown, tableName?: string): unknown {
|
|
2567
|
+
return transformWithRelationsAndExtractAggregates(withValue, tableName).with;
|
|
2191
2568
|
}
|
|
2192
2569
|
|
|
2193
2570
|
type RelationWithAggregatePlanEntry = {
|
|
@@ -2214,7 +2591,10 @@ function extractRelationAvgFieldNames(value: unknown): string[] {
|
|
|
2214
2591
|
.map(([fieldName]) => fieldName);
|
|
2215
2592
|
}
|
|
2216
2593
|
|
|
2217
|
-
function transformWithRelationsAndExtractAggregates(
|
|
2594
|
+
function transformWithRelationsAndExtractAggregates(
|
|
2595
|
+
withValue: unknown,
|
|
2596
|
+
tableName?: string,
|
|
2597
|
+
): {
|
|
2218
2598
|
with: unknown;
|
|
2219
2599
|
aggregatePlan: RelationWithAggregatePlan | undefined;
|
|
2220
2600
|
} {
|
|
@@ -2228,8 +2608,21 @@ function transformWithRelationsAndExtractAggregates(withValue: unknown): {
|
|
|
2228
2608
|
const transformed: Record<string, unknown> = {};
|
|
2229
2609
|
const aggregatePlan: RelationWithAggregatePlan = {};
|
|
2230
2610
|
for (const [relationName, relationValue] of Object.entries(withValue)) {
|
|
2611
|
+
const manyToMany =
|
|
2612
|
+
tableName === undefined
|
|
2613
|
+
? undefined
|
|
2614
|
+
: getManyToManyRelation(tableName, relationName);
|
|
2615
|
+
|
|
2231
2616
|
if (typeof relationValue === "boolean") {
|
|
2232
|
-
|
|
2617
|
+
if (manyToMany && relationValue) {
|
|
2618
|
+
transformed[relationName] = {
|
|
2619
|
+
with: {
|
|
2620
|
+
[manyToMany.targetTable]: true,
|
|
2621
|
+
},
|
|
2622
|
+
};
|
|
2623
|
+
} else {
|
|
2624
|
+
transformed[relationName] = relationValue;
|
|
2625
|
+
}
|
|
2233
2626
|
continue;
|
|
2234
2627
|
}
|
|
2235
2628
|
|
|
@@ -2238,13 +2631,19 @@ function transformWithRelationsAndExtractAggregates(withValue: unknown): {
|
|
|
2238
2631
|
continue;
|
|
2239
2632
|
}
|
|
2240
2633
|
|
|
2241
|
-
const
|
|
2634
|
+
const relationConfigInput: Record<string, unknown> = {
|
|
2242
2635
|
...relationValue,
|
|
2243
2636
|
};
|
|
2244
|
-
const countRequested =
|
|
2245
|
-
const avgFieldNames = extractRelationAvgFieldNames(
|
|
2246
|
-
delete
|
|
2247
|
-
delete
|
|
2637
|
+
const countRequested = relationConfigInput._count === true;
|
|
2638
|
+
const avgFieldNames = extractRelationAvgFieldNames(relationConfigInput._avg);
|
|
2639
|
+
delete relationConfigInput._count;
|
|
2640
|
+
delete relationConfigInput._avg;
|
|
2641
|
+
|
|
2642
|
+
const relationConfig: Record<string, unknown> = manyToMany
|
|
2643
|
+
? {
|
|
2644
|
+
...relationConfigInput,
|
|
2645
|
+
}
|
|
2646
|
+
: relationConfigInput;
|
|
2248
2647
|
|
|
2249
2648
|
let nestedAggregatePlan: RelationWithAggregatePlan | undefined;
|
|
2250
2649
|
|
|
@@ -2257,7 +2656,7 @@ function transformWithRelationsAndExtractAggregates(withValue: unknown): {
|
|
|
2257
2656
|
);
|
|
2258
2657
|
}
|
|
2259
2658
|
|
|
2260
|
-
if (isRecord(relationWhere)) {
|
|
2659
|
+
if (isRecord(relationWhere) && !manyToMany) {
|
|
2261
2660
|
relationConfig.where = (fields: Record<string, unknown>) => {
|
|
2262
2661
|
const filter = buildWhereFilterFromFields(
|
|
2263
2662
|
fields,
|
|
@@ -2272,9 +2671,52 @@ function transformWithRelationsAndExtractAggregates(withValue: unknown): {
|
|
|
2272
2671
|
};
|
|
2273
2672
|
}
|
|
2274
2673
|
|
|
2275
|
-
if (
|
|
2674
|
+
if (manyToMany) {
|
|
2675
|
+
const targetRelationConfig: Record<string, unknown> = {};
|
|
2676
|
+
for (const [configKey, configValue] of Object.entries(relationConfig)) {
|
|
2677
|
+
if (configKey === "with" || configKey === "where") {
|
|
2678
|
+
continue;
|
|
2679
|
+
}
|
|
2680
|
+
targetRelationConfig[configKey] = configValue;
|
|
2681
|
+
}
|
|
2682
|
+
|
|
2683
|
+
if (isRecord(relationWhere)) {
|
|
2684
|
+
targetRelationConfig.where = (fields: Record<string, unknown>) => {
|
|
2685
|
+
const filter = buildWhereFilterFromFields(
|
|
2686
|
+
fields,
|
|
2687
|
+
relationWhere,
|
|
2688
|
+
manyToMany.targetTable,
|
|
2689
|
+
);
|
|
2690
|
+
if (filter) {
|
|
2691
|
+
return filter;
|
|
2692
|
+
}
|
|
2693
|
+
|
|
2694
|
+
return sql\`1 = 1\`;
|
|
2695
|
+
};
|
|
2696
|
+
}
|
|
2697
|
+
|
|
2698
|
+
if (relationConfig.with !== undefined) {
|
|
2699
|
+
const nestedTransform = transformWithRelationsAndExtractAggregates(
|
|
2700
|
+
relationConfig.with,
|
|
2701
|
+
manyToMany.targetTable,
|
|
2702
|
+
);
|
|
2703
|
+
targetRelationConfig.with = nestedTransform.with;
|
|
2704
|
+
nestedAggregatePlan = nestedTransform.aggregatePlan;
|
|
2705
|
+
}
|
|
2706
|
+
|
|
2707
|
+
const targetConfigValue =
|
|
2708
|
+
Object.keys(targetRelationConfig).length === 0
|
|
2709
|
+
? true
|
|
2710
|
+
: targetRelationConfig;
|
|
2711
|
+
|
|
2712
|
+
relationConfig.with = {
|
|
2713
|
+
[manyToMany.targetTable]: targetConfigValue,
|
|
2714
|
+
};
|
|
2715
|
+
delete relationConfig.where;
|
|
2716
|
+
} else if (relationConfig.with !== undefined) {
|
|
2276
2717
|
const nestedTransform = transformWithRelationsAndExtractAggregates(
|
|
2277
2718
|
relationConfig.with,
|
|
2719
|
+
relationName,
|
|
2278
2720
|
);
|
|
2279
2721
|
relationConfig.with = nestedTransform.with;
|
|
2280
2722
|
nestedAggregatePlan = nestedTransform.aggregatePlan;
|
|
@@ -2589,7 +3031,7 @@ function inferConflictTarget(table: unknown): string[] {
|
|
|
2589
3031
|
|
|
2590
3032
|
return [];
|
|
2591
3033
|
}
|
|
2592
|
-
`}function
|
|
3034
|
+
`}function ke(){return `const mergedSchema = {
|
|
2593
3035
|
...authSchema,
|
|
2594
3036
|
...schema,
|
|
2595
3037
|
};
|
|
@@ -2617,7 +3059,13 @@ type ResolveNativeFindManyWith<
|
|
|
2617
3059
|
TName extends TableName,
|
|
2618
3060
|
TArgs extends QueryFindManyArgs<TName> | undefined,
|
|
2619
3061
|
> = TArgs extends { with?: infer TWith }
|
|
2620
|
-
? Extract<TWith, NativeFindManyWith<TName>>
|
|
3062
|
+
? Extract<TWith, NativeFindManyWith<TName>> extends infer TResolved
|
|
3063
|
+
? [TResolved] extends [never]
|
|
3064
|
+
? TWith extends Record<string, unknown>
|
|
3065
|
+
? NativeFindManyWith<TName>
|
|
3066
|
+
: never
|
|
3067
|
+
: TResolved
|
|
3068
|
+
: never
|
|
2621
3069
|
: never;
|
|
2622
3070
|
type ResolveTableFindManySelection<
|
|
2623
3071
|
TName extends TableName,
|
|
@@ -2631,35 +3079,170 @@ type ResolveTableFindManySelection<
|
|
|
2631
3079
|
type TableModel<TName extends TableName> = InferSelectModel<
|
|
2632
3080
|
(typeof mergedSchema)[TName]
|
|
2633
3081
|
>;
|
|
3082
|
+
type ManyToManySchemaMap = typeof schema extends {
|
|
3083
|
+
__appflareManyToMany: infer TMap extends Record<string, unknown>;
|
|
3084
|
+
}
|
|
3085
|
+
? TMap
|
|
3086
|
+
: {};
|
|
3087
|
+
type ManyToManySourceTableMap<TSourceTable extends TableName> =
|
|
3088
|
+
TSourceTable extends keyof ManyToManySchemaMap
|
|
3089
|
+
? ManyToManySchemaMap[TSourceTable] extends Record<string, unknown>
|
|
3090
|
+
? ManyToManySchemaMap[TSourceTable]
|
|
3091
|
+
: {}
|
|
3092
|
+
: {};
|
|
3093
|
+
type ManyToManyTargetTableName<
|
|
3094
|
+
TSourceTable extends TableName,
|
|
3095
|
+
TRelationName extends string,
|
|
3096
|
+
> = TRelationName extends keyof ManyToManySourceTableMap<TSourceTable>
|
|
3097
|
+
? ManyToManySourceTableMap<TSourceTable>[TRelationName] extends {
|
|
3098
|
+
targetTable: infer TTarget extends string;
|
|
3099
|
+
}
|
|
3100
|
+
? Extract<TTarget, TableName>
|
|
3101
|
+
: never
|
|
3102
|
+
: never;
|
|
3103
|
+
type RuntimeRelationsSchemaMap = typeof schema extends {
|
|
3104
|
+
__appflareRelations: infer TMap extends Record<string, unknown>;
|
|
3105
|
+
}
|
|
3106
|
+
? TMap
|
|
3107
|
+
: {};
|
|
3108
|
+
type RuntimeRelationsSourceTableMap<TSourceTable extends TableName> =
|
|
3109
|
+
TSourceTable extends keyof RuntimeRelationsSchemaMap
|
|
3110
|
+
? RuntimeRelationsSchemaMap[TSourceTable] extends Record<string, unknown>
|
|
3111
|
+
? RuntimeRelationsSchemaMap[TSourceTable]
|
|
3112
|
+
: {}
|
|
3113
|
+
: {};
|
|
3114
|
+
type RuntimeRelationName<TSourceTable extends TableName> =
|
|
3115
|
+
Extract<keyof RuntimeRelationsSourceTableMap<TSourceTable>, string>;
|
|
3116
|
+
type RuntimeRelationConfig<
|
|
3117
|
+
TSourceTable extends TableName,
|
|
3118
|
+
TRelationName extends string,
|
|
3119
|
+
> = TRelationName extends keyof RuntimeRelationsSourceTableMap<TSourceTable>
|
|
3120
|
+
? RuntimeRelationsSourceTableMap<TSourceTable>[TRelationName]
|
|
3121
|
+
: never;
|
|
3122
|
+
type RuntimeRelationKind<
|
|
3123
|
+
TSourceTable extends TableName,
|
|
3124
|
+
TRelationName extends string,
|
|
3125
|
+
> = RuntimeRelationConfig<TSourceTable, TRelationName> extends {
|
|
3126
|
+
kind: infer TKind extends string;
|
|
3127
|
+
}
|
|
3128
|
+
? TKind
|
|
3129
|
+
: never;
|
|
3130
|
+
type RuntimeRelationTargetTable<
|
|
3131
|
+
TSourceTable extends TableName,
|
|
3132
|
+
TRelationName extends string,
|
|
3133
|
+
> = RuntimeRelationConfig<TSourceTable, TRelationName> extends {
|
|
3134
|
+
targetTable: infer TTarget extends string;
|
|
3135
|
+
}
|
|
3136
|
+
? Extract<TTarget, TableName>
|
|
3137
|
+
: never;
|
|
3138
|
+
type TableInsertScalarModel<TName extends TableName> = TableInsertModel<TName>;
|
|
3139
|
+
type FindManyWithFromArgs<TArgs> = TArgs extends { with?: infer TWith }
|
|
3140
|
+
? TWith
|
|
3141
|
+
: undefined;
|
|
3142
|
+
type ManyToManyRelationRows<
|
|
3143
|
+
TTargetTable extends TableName,
|
|
3144
|
+
TRelationArgs,
|
|
3145
|
+
> = TRelationArgs extends true
|
|
3146
|
+
? Array<TableModel<TTargetTable>>
|
|
3147
|
+
: TRelationArgs extends Record<string, unknown>
|
|
3148
|
+
? Awaited<
|
|
3149
|
+
TableFindManyResult<
|
|
3150
|
+
TTargetTable,
|
|
3151
|
+
Extract<
|
|
3152
|
+
Omit<TRelationArgs, "_count" | "_avg">,
|
|
3153
|
+
QueryFindManyArgs<TTargetTable>
|
|
3154
|
+
>
|
|
3155
|
+
>
|
|
3156
|
+
>
|
|
3157
|
+
: Array<TableModel<TTargetTable>>;
|
|
3158
|
+
type ReplaceManyToManyRelationsInRow<
|
|
3159
|
+
TSourceTable extends TableName,
|
|
3160
|
+
TRow,
|
|
3161
|
+
TWith,
|
|
3162
|
+
> = TRow extends Record<string, unknown>
|
|
3163
|
+
? {
|
|
3164
|
+
[K in keyof TRow]: K extends string
|
|
3165
|
+
? TWith extends Record<string, unknown>
|
|
3166
|
+
? K extends keyof TWith
|
|
3167
|
+
? [ManyToManyTargetTableName<TSourceTable, K>] extends [never]
|
|
3168
|
+
? TRow[K]
|
|
3169
|
+
: ManyToManyRelationRows<
|
|
3170
|
+
Extract<ManyToManyTargetTableName<TSourceTable, K>, TableName>,
|
|
3171
|
+
TWith[K]
|
|
3172
|
+
>
|
|
3173
|
+
: TRow[K]
|
|
3174
|
+
: TRow[K]
|
|
3175
|
+
: TRow[K];
|
|
3176
|
+
}
|
|
3177
|
+
: TRow;
|
|
3178
|
+
type ApplyManyToManyFindManyResult<
|
|
3179
|
+
TSourceTable extends TableName,
|
|
3180
|
+
TArgs extends QueryFindManyArgs<TSourceTable> | undefined,
|
|
3181
|
+
TResult,
|
|
3182
|
+
> = TResult extends Promise<infer TRows>
|
|
3183
|
+
? TRows extends Array<infer TRow>
|
|
3184
|
+
? Promise<
|
|
3185
|
+
Array<
|
|
3186
|
+
ReplaceManyToManyRelationsInRow<
|
|
3187
|
+
TSourceTable,
|
|
3188
|
+
TRow,
|
|
3189
|
+
FindManyWithFromArgs<TArgs>
|
|
3190
|
+
>
|
|
3191
|
+
>
|
|
3192
|
+
>
|
|
3193
|
+
: TResult
|
|
3194
|
+
: TResult;
|
|
3195
|
+
type ApplyManyToManyFindFirstResult<
|
|
3196
|
+
TSourceTable extends TableName,
|
|
3197
|
+
TArgs extends QueryFindFirstArgs<TSourceTable> | undefined,
|
|
3198
|
+
TResult,
|
|
3199
|
+
> = TResult extends Promise<infer TRow>
|
|
3200
|
+
? Promise<
|
|
3201
|
+
TRow extends null
|
|
3202
|
+
? null
|
|
3203
|
+
: ReplaceManyToManyRelationsInRow<
|
|
3204
|
+
TSourceTable,
|
|
3205
|
+
TRow,
|
|
3206
|
+
FindManyWithFromArgs<TArgs>
|
|
3207
|
+
>
|
|
3208
|
+
>
|
|
3209
|
+
: TResult;
|
|
2634
3210
|
type TableFindManyResult<
|
|
2635
3211
|
TName extends TableName,
|
|
2636
3212
|
TArgs extends QueryFindManyArgs<TName> | undefined =
|
|
2637
3213
|
| QueryFindManyArgs<TName>
|
|
2638
3214
|
| undefined,
|
|
2639
|
-
> =
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
3215
|
+
> = ApplyManyToManyFindManyResult<
|
|
3216
|
+
TName,
|
|
3217
|
+
TArgs,
|
|
3218
|
+
TArgs extends undefined
|
|
3219
|
+
? Promise<Array<TableModel<TName>>>
|
|
3220
|
+
: Promise<
|
|
3221
|
+
Array<
|
|
3222
|
+
BuildQueryResult<
|
|
3223
|
+
SchemaRelations,
|
|
3224
|
+
TableRelationConfig<TName>,
|
|
3225
|
+
ResolveTableFindManySelection<TName, TArgs>
|
|
3226
|
+
>
|
|
2647
3227
|
>
|
|
2648
|
-
|
|
2649
|
-
|
|
3228
|
+
>
|
|
3229
|
+
>;
|
|
2650
3230
|
type TableFindFirstArgs<TName extends TableName> = Omit<
|
|
2651
3231
|
TableFindManyArgs<TName>,
|
|
2652
3232
|
"limit"
|
|
2653
3233
|
>;
|
|
2654
|
-
type NativeFindFirstWith<TName extends TableName> =
|
|
2655
|
-
NonNullable<TableFindFirstArgs<TName>> extends { with?: infer TWith }
|
|
2656
|
-
? TWith
|
|
2657
|
-
: never;
|
|
3234
|
+
type NativeFindFirstWith<TName extends TableName> = NativeFindManyWith<TName>;
|
|
2658
3235
|
type ResolveNativeFindFirstWith<
|
|
2659
3236
|
TName extends TableName,
|
|
2660
3237
|
TArgs extends QueryFindFirstArgs<TName> | undefined,
|
|
2661
3238
|
> = TArgs extends { with?: infer TWith }
|
|
2662
|
-
? Extract<TWith, NativeFindFirstWith<TName>>
|
|
3239
|
+
? Extract<TWith, NativeFindFirstWith<TName>> extends infer TResolved
|
|
3240
|
+
? [TResolved] extends [never]
|
|
3241
|
+
? TWith extends Record<string, unknown>
|
|
3242
|
+
? NativeFindFirstWith<TName>
|
|
3243
|
+
: never
|
|
3244
|
+
: TResolved
|
|
3245
|
+
: never
|
|
2663
3246
|
: never;
|
|
2664
3247
|
type ResolveTableFindFirstSelection<
|
|
2665
3248
|
TName extends TableName,
|
|
@@ -2675,21 +3258,25 @@ type TableFindFirstResult<
|
|
|
2675
3258
|
TArgs extends QueryFindFirstArgs<TName> | undefined =
|
|
2676
3259
|
| QueryFindFirstArgs<TName>
|
|
2677
3260
|
| undefined,
|
|
2678
|
-
> =
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
3261
|
+
> = ApplyManyToManyFindFirstResult<
|
|
3262
|
+
TName,
|
|
3263
|
+
TArgs,
|
|
3264
|
+
TArgs extends undefined
|
|
3265
|
+
? Promise<TableModel<TName> | null>
|
|
3266
|
+
: Promise<
|
|
3267
|
+
BuildQueryResult<
|
|
3268
|
+
SchemaRelations,
|
|
3269
|
+
TableRelationConfig<TName>,
|
|
3270
|
+
ResolveTableFindFirstSelection<TName, TArgs>
|
|
3271
|
+
> | null
|
|
3272
|
+
>
|
|
3273
|
+
>;
|
|
2687
3274
|
type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
2688
3275
|
(typeof mergedSchema)[TName]
|
|
2689
3276
|
>;
|
|
2690
|
-
`}function
|
|
3277
|
+
`}function Se(){return [ke(),ve(),Te(),Re()].join(`
|
|
2691
3278
|
|
|
2692
|
-
`)}function
|
|
3279
|
+
`)}function Ae(){return ` count: async (args?: QueryCountArgs<TableName>) => {
|
|
2693
3280
|
const withValue = args?.with;
|
|
2694
3281
|
const pathSegments = args?.field
|
|
2695
3282
|
? splitAggregateFieldPath(String(args.field))
|
|
@@ -2709,12 +3296,17 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
2709
3296
|
const transformedWith =
|
|
2710
3297
|
withValue === undefined
|
|
2711
3298
|
? undefined
|
|
2712
|
-
: transformWithRelations(withValue);
|
|
3299
|
+
: transformWithRelations(withValue, tableName);
|
|
2713
3300
|
const rawRows = await queryTable.findMany({
|
|
2714
3301
|
...(whereFilter ? { where: () => whereFilter } : {}),
|
|
2715
3302
|
...(transformedWith !== undefined ? { with: transformedWith } : {}),
|
|
2716
3303
|
});
|
|
2717
|
-
const
|
|
3304
|
+
const flattenedRows = flattenManyToManyResult(
|
|
3305
|
+
tableName,
|
|
3306
|
+
rawRows,
|
|
3307
|
+
withValue,
|
|
3308
|
+
);
|
|
3309
|
+
const rows = Array.isArray(flattenedRows) ? flattenedRows : [];
|
|
2718
3310
|
const constrainedRows = hasAggregateWithConstraints(withValue)
|
|
2719
3311
|
? rows.filter((row) =>
|
|
2720
3312
|
rowMatchesAggregateWithConstraints(row, withValue),
|
|
@@ -2787,12 +3379,17 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
2787
3379
|
const transformedWith =
|
|
2788
3380
|
withValue === undefined
|
|
2789
3381
|
? undefined
|
|
2790
|
-
: transformWithRelations(withValue);
|
|
3382
|
+
: transformWithRelations(withValue, tableName);
|
|
2791
3383
|
const rawRows = await queryTable.findMany({
|
|
2792
3384
|
...(whereFilter ? { where: () => whereFilter } : {}),
|
|
2793
3385
|
...(transformedWith !== undefined ? { with: transformedWith } : {}),
|
|
2794
3386
|
});
|
|
2795
|
-
const
|
|
3387
|
+
const flattenedRows = flattenManyToManyResult(
|
|
3388
|
+
tableName,
|
|
3389
|
+
rawRows,
|
|
3390
|
+
withValue,
|
|
3391
|
+
);
|
|
3392
|
+
const rows = Array.isArray(flattenedRows) ? flattenedRows : [];
|
|
2796
3393
|
const constrainedRows = hasAggregateWithConstraints(withValue)
|
|
2797
3394
|
? rows.filter((row) =>
|
|
2798
3395
|
rowMatchesAggregateWithConstraints(row, withValue),
|
|
@@ -2850,7 +3447,7 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
2850
3447
|
},
|
|
2851
3448
|
}) as AppflareQueryDb;
|
|
2852
3449
|
}
|
|
2853
|
-
`}function
|
|
3450
|
+
`}function Ne(){return `export class AppflareHandledError extends Error {
|
|
2854
3451
|
public readonly status: number;
|
|
2855
3452
|
public readonly payload: unknown;
|
|
2856
3453
|
|
|
@@ -2860,7 +3457,7 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
2860
3457
|
this.payload = payload;
|
|
2861
3458
|
}
|
|
2862
3459
|
}
|
|
2863
|
-
`}function
|
|
3460
|
+
`}function $e(){return ` findMany: (args?: Record<string, unknown>) => {
|
|
2864
3461
|
const where = isRecord(args?.where)
|
|
2865
3462
|
? (args?.where as Record<string, unknown>)
|
|
2866
3463
|
: undefined;
|
|
@@ -2880,10 +3477,19 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
2880
3477
|
with: undefined,
|
|
2881
3478
|
aggregatePlan: undefined,
|
|
2882
3479
|
}
|
|
2883
|
-
: transformWithRelationsAndExtractAggregates(withValue);
|
|
3480
|
+
: transformWithRelationsAndExtractAggregates(withValue, tableName);
|
|
2884
3481
|
const transformedWith = transformedWithResult.with;
|
|
2885
3482
|
const aggregatePlan = transformedWithResult.aggregatePlan;
|
|
2886
|
-
|
|
3483
|
+
const requiresManyToManyFlatten = hasManyToManyRelationsInWith(
|
|
3484
|
+
tableName,
|
|
3485
|
+
withValue,
|
|
3486
|
+
);
|
|
3487
|
+
if (
|
|
3488
|
+
!whereFilter &&
|
|
3489
|
+
transformedWith === withValue &&
|
|
3490
|
+
!aggregatePlan &&
|
|
3491
|
+
!requiresManyToManyFlatten
|
|
3492
|
+
) {
|
|
2887
3493
|
return queryTable.findMany(passthroughArgs);
|
|
2888
3494
|
}
|
|
2889
3495
|
|
|
@@ -2893,13 +3499,22 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
2893
3499
|
...(transformedWith !== undefined ? { with: transformedWith } : {}),
|
|
2894
3500
|
});
|
|
2895
3501
|
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
3502
|
+
return queryPromise.then((result) => {
|
|
3503
|
+
const flattenedResult = flattenManyToManyResult(
|
|
3504
|
+
tableName,
|
|
3505
|
+
result,
|
|
3506
|
+
withValue,
|
|
3507
|
+
);
|
|
2899
3508
|
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
3509
|
+
if (!aggregatePlan) {
|
|
3510
|
+
return flattenedResult;
|
|
3511
|
+
}
|
|
3512
|
+
|
|
3513
|
+
return applyRelationAggregatePlanToResult(
|
|
3514
|
+
flattenedResult,
|
|
3515
|
+
aggregatePlan,
|
|
3516
|
+
);
|
|
3517
|
+
});
|
|
2903
3518
|
},
|
|
2904
3519
|
findFirst: (args?: Record<string, unknown>) => {
|
|
2905
3520
|
const where = isRecord(args?.where)
|
|
@@ -2921,10 +3536,19 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
2921
3536
|
with: undefined,
|
|
2922
3537
|
aggregatePlan: undefined,
|
|
2923
3538
|
}
|
|
2924
|
-
: transformWithRelationsAndExtractAggregates(withValue);
|
|
3539
|
+
: transformWithRelationsAndExtractAggregates(withValue, tableName);
|
|
2925
3540
|
const transformedWith = transformedWithResult.with;
|
|
2926
3541
|
const aggregatePlan = transformedWithResult.aggregatePlan;
|
|
2927
|
-
|
|
3542
|
+
const requiresManyToManyFlatten = hasManyToManyRelationsInWith(
|
|
3543
|
+
tableName,
|
|
3544
|
+
withValue,
|
|
3545
|
+
);
|
|
3546
|
+
if (
|
|
3547
|
+
!whereFilter &&
|
|
3548
|
+
transformedWith === withValue &&
|
|
3549
|
+
!aggregatePlan &&
|
|
3550
|
+
!requiresManyToManyFlatten
|
|
3551
|
+
) {
|
|
2928
3552
|
return queryTable.findFirst(passthroughArgs);
|
|
2929
3553
|
}
|
|
2930
3554
|
|
|
@@ -2934,15 +3558,24 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
2934
3558
|
...(transformedWith !== undefined ? { with: transformedWith } : {}),
|
|
2935
3559
|
});
|
|
2936
3560
|
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
3561
|
+
return queryPromise.then((result) => {
|
|
3562
|
+
const flattenedResult = flattenManyToManyResult(
|
|
3563
|
+
tableName,
|
|
3564
|
+
result,
|
|
3565
|
+
withValue,
|
|
3566
|
+
);
|
|
2940
3567
|
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
3568
|
+
if (!aggregatePlan) {
|
|
3569
|
+
return flattenedResult;
|
|
3570
|
+
}
|
|
3571
|
+
|
|
3572
|
+
return applyRelationAggregatePlanToResult(
|
|
3573
|
+
flattenedResult,
|
|
3574
|
+
aggregatePlan,
|
|
3575
|
+
);
|
|
3576
|
+
});
|
|
2944
3577
|
},
|
|
2945
|
-
`}function
|
|
3578
|
+
`}function qe(){return `export function createQueryDb(
|
|
2946
3579
|
$db: AppflareDb,
|
|
2947
3580
|
options?: QueryDbOptions,
|
|
2948
3581
|
): AppflareQueryDb {
|
|
@@ -2984,16 +3617,555 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
2984
3617
|
};
|
|
2985
3618
|
|
|
2986
3619
|
const tableApi = {
|
|
2987
|
-
`}function
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
3620
|
+
`}function Ie(){return ` insert: async <TArgs extends QueryInsertArgs<TableName>>(args: TArgs) => {
|
|
3621
|
+
const transaction = ($db as any).transaction;
|
|
3622
|
+
|
|
3623
|
+
const valuesArray = Array.isArray(args.values)
|
|
3624
|
+
? args.values
|
|
3625
|
+
: [args.values];
|
|
3626
|
+
const baseValuesArray: Array<Record<string, unknown>> = [];
|
|
3627
|
+
const postInsertRelations: Array<
|
|
3628
|
+
Array<{
|
|
3629
|
+
relationName: string;
|
|
3630
|
+
relation: RuntimeRelation;
|
|
3631
|
+
value: unknown;
|
|
3632
|
+
}>
|
|
3633
|
+
> = [];
|
|
3634
|
+
|
|
3635
|
+
const toRelationItems = (
|
|
3636
|
+
relation: RuntimeRelation,
|
|
3637
|
+
relationName: string,
|
|
3638
|
+
value: unknown,
|
|
3639
|
+
): unknown[] => {
|
|
3640
|
+
if (value === undefined || value === null) {
|
|
3641
|
+
return [];
|
|
3642
|
+
}
|
|
3643
|
+
|
|
3644
|
+
if (relation.kind === "one") {
|
|
3645
|
+
if (Array.isArray(value)) {
|
|
3646
|
+
throw new Error(
|
|
3647
|
+
"Relation '" +
|
|
3648
|
+
tableName +
|
|
3649
|
+
"." +
|
|
3650
|
+
relationName +
|
|
3651
|
+
"' expects a single value.",
|
|
3652
|
+
);
|
|
3653
|
+
}
|
|
3654
|
+
return [value];
|
|
3655
|
+
}
|
|
3656
|
+
|
|
3657
|
+
return Array.isArray(value) ? value : [value];
|
|
3658
|
+
};
|
|
3659
|
+
|
|
3660
|
+
const resolveRelationIdentifier = async (
|
|
3661
|
+
tx: any,
|
|
3662
|
+
relation: RuntimeRelation,
|
|
3663
|
+
relationName: string,
|
|
3664
|
+
input: unknown,
|
|
3665
|
+
): Promise<unknown> => {
|
|
3666
|
+
if (
|
|
3667
|
+
typeof input === "string" ||
|
|
3668
|
+
typeof input === "number" ||
|
|
3669
|
+
typeof input === "bigint"
|
|
3670
|
+
) {
|
|
3671
|
+
return input;
|
|
3672
|
+
}
|
|
3673
|
+
|
|
3674
|
+
if (!isRecord(input)) {
|
|
3675
|
+
throw new Error(
|
|
3676
|
+
"Relation '" +
|
|
3677
|
+
tableName +
|
|
3678
|
+
"." +
|
|
3679
|
+
relationName +
|
|
3680
|
+
"' expects an id or object payload.",
|
|
3681
|
+
);
|
|
3682
|
+
}
|
|
3683
|
+
|
|
3684
|
+
const referenceField =
|
|
3685
|
+
relation.kind === "manyToMany"
|
|
3686
|
+
? (relation.targetReferenceField ?? "id")
|
|
3687
|
+
: (relation.referenceField ?? "id");
|
|
3688
|
+
const existingId = input[referenceField];
|
|
3689
|
+
if (existingId !== undefined && existingId !== null) {
|
|
3690
|
+
return existingId;
|
|
3691
|
+
}
|
|
3692
|
+
|
|
3693
|
+
const targetTable = (mergedSchema as Record<string, unknown>)[
|
|
3694
|
+
relation.targetTable
|
|
3695
|
+
];
|
|
3696
|
+
if (!targetTable) {
|
|
3697
|
+
throw new Error(
|
|
3698
|
+
"Unknown target table '" +
|
|
3699
|
+
relation.targetTable +
|
|
3700
|
+
"' for relation '" +
|
|
3701
|
+
tableName +
|
|
3702
|
+
"." +
|
|
3703
|
+
relationName +
|
|
3704
|
+
"'.",
|
|
3705
|
+
);
|
|
3706
|
+
}
|
|
3707
|
+
|
|
3708
|
+
let createQuery: any = tx.insert(targetTable as any).values(input as any);
|
|
3709
|
+
if (typeof createQuery.returning === "function") {
|
|
3710
|
+
createQuery = createQuery.returning();
|
|
3711
|
+
}
|
|
3712
|
+
const createdRows = (await createQuery) as Array<Record<string, unknown>>;
|
|
3713
|
+
const created = createdRows[0];
|
|
3714
|
+
if (!created) {
|
|
3715
|
+
throw new Error(
|
|
3716
|
+
"Failed to create relation target for '" +
|
|
3717
|
+
tableName +
|
|
3718
|
+
"." +
|
|
3719
|
+
relationName +
|
|
3720
|
+
"'.",
|
|
3721
|
+
);
|
|
3722
|
+
}
|
|
3723
|
+
|
|
3724
|
+
const createdId = created[referenceField];
|
|
3725
|
+
if (createdId === undefined || createdId === null) {
|
|
3726
|
+
throw new Error(
|
|
3727
|
+
"Created relation target for '" +
|
|
3728
|
+
tableName +
|
|
3729
|
+
"." +
|
|
3730
|
+
relationName +
|
|
3731
|
+
"' is missing '" +
|
|
3732
|
+
referenceField +
|
|
3733
|
+
"'.",
|
|
3734
|
+
);
|
|
3735
|
+
}
|
|
3736
|
+
|
|
3737
|
+
return createdId;
|
|
3738
|
+
};
|
|
3739
|
+
|
|
3740
|
+
const getRelationTargetTable = (
|
|
3741
|
+
relation: RuntimeRelation,
|
|
3742
|
+
relationName: string,
|
|
3743
|
+
): any => {
|
|
3744
|
+
const targetTable = (mergedSchema as Record<string, unknown>)[
|
|
3745
|
+
relation.targetTable
|
|
3746
|
+
];
|
|
3747
|
+
if (!targetTable) {
|
|
3748
|
+
throw new Error(
|
|
3749
|
+
"Unknown target table '" +
|
|
3750
|
+
relation.targetTable +
|
|
3751
|
+
"' for relation '" +
|
|
3752
|
+
tableName +
|
|
3753
|
+
"." +
|
|
3754
|
+
relationName +
|
|
3755
|
+
"'.",
|
|
3756
|
+
);
|
|
3757
|
+
}
|
|
3758
|
+
return targetTable;
|
|
3759
|
+
};
|
|
3760
|
+
|
|
3761
|
+
const getRelationReferenceField = (relation: RuntimeRelation): string => {
|
|
3762
|
+
if (relation.kind === "manyToMany") {
|
|
3763
|
+
return relation.targetReferenceField ?? "id";
|
|
3764
|
+
}
|
|
3765
|
+
return relation.referenceField ?? "id";
|
|
3766
|
+
};
|
|
3767
|
+
|
|
3768
|
+
const fetchRelatedRowByIdentifier = async (
|
|
3769
|
+
tx: any,
|
|
3770
|
+
relation: RuntimeRelation,
|
|
3771
|
+
relationName: string,
|
|
3772
|
+
identifier: unknown,
|
|
3773
|
+
): Promise<Record<string, unknown> | null> => {
|
|
3774
|
+
if (identifier === undefined || identifier === null) {
|
|
3775
|
+
return null;
|
|
3776
|
+
}
|
|
3777
|
+
|
|
3778
|
+
const targetTable = getRelationTargetTable(relation, relationName);
|
|
3779
|
+
const referenceField = getRelationReferenceField(relation);
|
|
3780
|
+
const referenceColumn = (targetTable as Record<string, unknown>)[
|
|
3781
|
+
referenceField
|
|
3782
|
+
];
|
|
3783
|
+
if (!referenceColumn) {
|
|
3784
|
+
throw new Error(
|
|
3785
|
+
"Target table '" +
|
|
3786
|
+
relation.targetTable +
|
|
3787
|
+
"' is missing column '" +
|
|
3788
|
+
referenceField +
|
|
3789
|
+
"' required by relation '" +
|
|
3790
|
+
tableName +
|
|
3791
|
+
"." +
|
|
3792
|
+
relationName +
|
|
3793
|
+
"'.",
|
|
3794
|
+
);
|
|
3795
|
+
}
|
|
3796
|
+
|
|
3797
|
+
let query: any = tx
|
|
3798
|
+
.select()
|
|
3799
|
+
.from(targetTable as any)
|
|
3800
|
+
.where(eq(referenceColumn as any, identifier as any));
|
|
3801
|
+
if (typeof query.limit === "function") {
|
|
3802
|
+
query = query.limit(1);
|
|
3803
|
+
}
|
|
3804
|
+
const rows = (await query) as Array<Record<string, unknown>>;
|
|
3805
|
+
return rows[0] ?? null;
|
|
3806
|
+
};
|
|
3807
|
+
|
|
3808
|
+
for (const inputValue of valuesArray) {
|
|
3809
|
+
const scalarValues: Record<string, unknown> = {};
|
|
3810
|
+
const relationInputs: Array<{
|
|
3811
|
+
relationName: string;
|
|
3812
|
+
relation: RuntimeRelation;
|
|
3813
|
+
value: unknown;
|
|
3814
|
+
}> = [];
|
|
3815
|
+
|
|
3816
|
+
const valueRecord = (inputValue ?? {}) as Record<string, unknown>;
|
|
3817
|
+
for (const [fieldName, fieldValue] of Object.entries(valueRecord)) {
|
|
3818
|
+
const runtimeRelation = getRuntimeRelation(tableName, fieldName);
|
|
3819
|
+
if (runtimeRelation) {
|
|
3820
|
+
relationInputs.push({
|
|
3821
|
+
relationName: fieldName,
|
|
3822
|
+
relation: runtimeRelation,
|
|
3823
|
+
value: fieldValue,
|
|
3824
|
+
});
|
|
3825
|
+
continue;
|
|
3826
|
+
}
|
|
3827
|
+
scalarValues[fieldName] = fieldValue;
|
|
3828
|
+
}
|
|
3829
|
+
|
|
3830
|
+
baseValuesArray.push(scalarValues);
|
|
3831
|
+
postInsertRelations.push(relationInputs);
|
|
3832
|
+
}
|
|
3833
|
+
|
|
3834
|
+
const executeInsertGraph = async (
|
|
3835
|
+
tx: any,
|
|
3836
|
+
): Promise<Array<QueryInsertResultRow<TableName, TArgs>>> => {
|
|
3837
|
+
for (let index = 0; index < baseValuesArray.length; index += 1) {
|
|
3838
|
+
const relationInputs = postInsertRelations[index] ?? [];
|
|
3839
|
+
for (const relationInput of relationInputs) {
|
|
3840
|
+
if (relationInput.relation.kind !== "one") {
|
|
3841
|
+
continue;
|
|
3842
|
+
}
|
|
3843
|
+
|
|
3844
|
+
const sourceField = relationInput.relation.sourceField;
|
|
3845
|
+
if (!sourceField) {
|
|
3846
|
+
throw new Error(
|
|
3847
|
+
"Relation '" +
|
|
3848
|
+
tableName +
|
|
3849
|
+
"." +
|
|
3850
|
+
relationInput.relationName +
|
|
3851
|
+
"' is missing sourceField metadata.",
|
|
3852
|
+
);
|
|
3853
|
+
}
|
|
3854
|
+
|
|
3855
|
+
const oneItems = toRelationItems(
|
|
3856
|
+
relationInput.relation,
|
|
3857
|
+
relationInput.relationName,
|
|
3858
|
+
relationInput.value,
|
|
3859
|
+
);
|
|
3860
|
+
if (oneItems.length === 0) {
|
|
3861
|
+
continue;
|
|
3862
|
+
}
|
|
3863
|
+
|
|
3864
|
+
const relationId = await resolveRelationIdentifier(
|
|
3865
|
+
tx,
|
|
3866
|
+
relationInput.relation,
|
|
3867
|
+
relationInput.relationName,
|
|
3868
|
+
oneItems[0],
|
|
3869
|
+
);
|
|
3870
|
+
const existingValue = baseValuesArray[index][sourceField];
|
|
3871
|
+
if (
|
|
3872
|
+
existingValue !== undefined &&
|
|
3873
|
+
existingValue !== relationId
|
|
3874
|
+
) {
|
|
3875
|
+
throw new Error(
|
|
3876
|
+
"Insert payload for '" +
|
|
3877
|
+
tableName +
|
|
3878
|
+
"' has conflicting values for '" +
|
|
3879
|
+
sourceField +
|
|
3880
|
+
"'.",
|
|
3881
|
+
);
|
|
3882
|
+
}
|
|
3883
|
+
baseValuesArray[index][sourceField] = relationId;
|
|
3884
|
+
}
|
|
3885
|
+
}
|
|
3886
|
+
|
|
3887
|
+
let insertQuery: any = tx.insert(table as any).values(baseValuesArray as any);
|
|
3888
|
+
if (typeof insertQuery.returning === "function") {
|
|
3889
|
+
insertQuery = insertQuery.returning();
|
|
3890
|
+
}
|
|
3891
|
+
const insertedRows = (await insertQuery) as Array<TableModel<TableName>>;
|
|
3892
|
+
const hydratedRows: Array<Record<string, unknown>> = [];
|
|
3893
|
+
|
|
3894
|
+
for (let index = 0; index < insertedRows.length; index += 1) {
|
|
3895
|
+
const parentRow = insertedRows[index] as unknown as Record<string, unknown>;
|
|
3896
|
+
const hydratedRow: Record<string, unknown> = {
|
|
3897
|
+
...parentRow,
|
|
3898
|
+
};
|
|
3899
|
+
const relationInputs = postInsertRelations[index] ?? [];
|
|
3900
|
+
|
|
3901
|
+
for (const relationInput of relationInputs) {
|
|
3902
|
+
if (relationInput.relation.kind === "one") {
|
|
3903
|
+
const sourceField = relationInput.relation.sourceField;
|
|
3904
|
+
if (!sourceField) {
|
|
3905
|
+
throw new Error(
|
|
3906
|
+
"Relation '" +
|
|
3907
|
+
tableName +
|
|
3908
|
+
"." +
|
|
3909
|
+
relationInput.relationName +
|
|
3910
|
+
"' is missing sourceField metadata.",
|
|
3911
|
+
);
|
|
3912
|
+
}
|
|
3913
|
+
|
|
3914
|
+
const relationItems = toRelationItems(
|
|
3915
|
+
relationInput.relation,
|
|
3916
|
+
relationInput.relationName,
|
|
3917
|
+
relationInput.value,
|
|
3918
|
+
);
|
|
3919
|
+
if (relationItems.length === 0) {
|
|
3920
|
+
hydratedRow[relationInput.relationName] = null;
|
|
3921
|
+
continue;
|
|
3922
|
+
}
|
|
3923
|
+
|
|
3924
|
+
const sourceIdentifier = parentRow[sourceField];
|
|
3925
|
+
hydratedRow[relationInput.relationName] =
|
|
3926
|
+
(await fetchRelatedRowByIdentifier(
|
|
3927
|
+
tx,
|
|
3928
|
+
relationInput.relation,
|
|
3929
|
+
relationInput.relationName,
|
|
3930
|
+
sourceIdentifier,
|
|
3931
|
+
)) ?? null;
|
|
3932
|
+
continue;
|
|
3933
|
+
}
|
|
3934
|
+
|
|
3935
|
+
const sourceReferenceField = relationInput.relation.referenceField ?? "id";
|
|
3936
|
+
const parentReferenceValue = parentRow[sourceReferenceField];
|
|
3937
|
+
if (
|
|
3938
|
+
parentReferenceValue === undefined ||
|
|
3939
|
+
parentReferenceValue === null
|
|
3940
|
+
) {
|
|
3941
|
+
throw new Error(
|
|
3942
|
+
"Inserted row for '" +
|
|
3943
|
+
tableName +
|
|
3944
|
+
"' is missing '" +
|
|
3945
|
+
sourceReferenceField +
|
|
3946
|
+
"' required by relation '" +
|
|
3947
|
+
relationInput.relationName +
|
|
3948
|
+
"'.",
|
|
3949
|
+
);
|
|
3950
|
+
}
|
|
3951
|
+
|
|
3952
|
+
const relatedRows: Array<Record<string, unknown>> = [];
|
|
3953
|
+
hydratedRow[relationInput.relationName] = relatedRows;
|
|
3954
|
+
|
|
3955
|
+
const relationItems = toRelationItems(
|
|
3956
|
+
relationInput.relation,
|
|
3957
|
+
relationInput.relationName,
|
|
3958
|
+
relationInput.value,
|
|
3959
|
+
);
|
|
3960
|
+
if (relationItems.length === 0) {
|
|
3961
|
+
continue;
|
|
3962
|
+
}
|
|
3963
|
+
|
|
3964
|
+
if (relationInput.relation.kind === "many") {
|
|
3965
|
+
const targetTable = getRelationTargetTable(
|
|
3966
|
+
relationInput.relation,
|
|
3967
|
+
relationInput.relationName,
|
|
3968
|
+
);
|
|
3969
|
+
|
|
3970
|
+
const sourceField = relationInput.relation.sourceField;
|
|
3971
|
+
const targetReferenceField =
|
|
3972
|
+
relationInput.relation.referenceField ?? "id";
|
|
3973
|
+
const targetReferenceColumn =
|
|
3974
|
+
(targetTable as Record<string, unknown>)[targetReferenceField];
|
|
3975
|
+
if (!sourceField) {
|
|
3976
|
+
throw new Error(
|
|
3977
|
+
"Relation '" +
|
|
3978
|
+
tableName +
|
|
3979
|
+
"." +
|
|
3980
|
+
relationInput.relationName +
|
|
3981
|
+
"' is missing sourceField metadata.",
|
|
3982
|
+
);
|
|
3983
|
+
}
|
|
3984
|
+
if (!targetReferenceColumn) {
|
|
3985
|
+
throw new Error(
|
|
3986
|
+
"Target table '" +
|
|
3987
|
+
relationInput.relation.targetTable +
|
|
3988
|
+
"' is missing column '" +
|
|
3989
|
+
targetReferenceField +
|
|
3990
|
+
"' required by relation '" +
|
|
3991
|
+
tableName +
|
|
3992
|
+
"." +
|
|
3993
|
+
relationInput.relationName +
|
|
3994
|
+
"'.",
|
|
3995
|
+
);
|
|
3996
|
+
}
|
|
3997
|
+
|
|
3998
|
+
for (const relationItem of relationItems) {
|
|
3999
|
+
if (
|
|
4000
|
+
typeof relationItem === "string" ||
|
|
4001
|
+
typeof relationItem === "number" ||
|
|
4002
|
+
typeof relationItem === "bigint"
|
|
4003
|
+
) {
|
|
4004
|
+
await tx
|
|
4005
|
+
.update(targetTable as any)
|
|
4006
|
+
.set({ [sourceField]: parentReferenceValue } as any)
|
|
4007
|
+
.where(
|
|
4008
|
+
eq(targetReferenceColumn as any, relationItem as any),
|
|
4009
|
+
);
|
|
4010
|
+
const linkedRow = await fetchRelatedRowByIdentifier(
|
|
4011
|
+
tx,
|
|
4012
|
+
relationInput.relation,
|
|
4013
|
+
relationInput.relationName,
|
|
4014
|
+
relationItem,
|
|
4015
|
+
);
|
|
4016
|
+
if (linkedRow) {
|
|
4017
|
+
relatedRows.push(linkedRow);
|
|
4018
|
+
}
|
|
4019
|
+
continue;
|
|
4020
|
+
}
|
|
4021
|
+
|
|
4022
|
+
if (!isRecord(relationItem)) {
|
|
4023
|
+
throw new Error(
|
|
4024
|
+
"Relation '" +
|
|
4025
|
+
tableName +
|
|
4026
|
+
"." +
|
|
4027
|
+
relationInput.relationName +
|
|
4028
|
+
"' expects id or object payloads.",
|
|
4029
|
+
);
|
|
4030
|
+
}
|
|
4031
|
+
|
|
4032
|
+
const existingId = relationItem[targetReferenceField];
|
|
4033
|
+
const payload = {
|
|
4034
|
+
...relationItem,
|
|
4035
|
+
[sourceField]: parentReferenceValue,
|
|
4036
|
+
};
|
|
4037
|
+
|
|
4038
|
+
if (existingId !== undefined && existingId !== null) {
|
|
4039
|
+
const setPayload: Record<string, unknown> = {
|
|
4040
|
+
...payload,
|
|
4041
|
+
};
|
|
4042
|
+
delete setPayload[targetReferenceField];
|
|
4043
|
+
await tx
|
|
4044
|
+
.update(targetTable as any)
|
|
4045
|
+
.set(setPayload as any)
|
|
4046
|
+
.where(
|
|
4047
|
+
eq(targetReferenceColumn as any, existingId as any),
|
|
4048
|
+
);
|
|
4049
|
+
const linkedRow = await fetchRelatedRowByIdentifier(
|
|
4050
|
+
tx,
|
|
4051
|
+
relationInput.relation,
|
|
4052
|
+
relationInput.relationName,
|
|
4053
|
+
existingId,
|
|
4054
|
+
);
|
|
4055
|
+
if (linkedRow) {
|
|
4056
|
+
relatedRows.push(linkedRow);
|
|
4057
|
+
}
|
|
4058
|
+
continue;
|
|
4059
|
+
}
|
|
4060
|
+
|
|
4061
|
+
let createQuery: any = tx
|
|
4062
|
+
.insert(targetTable as any)
|
|
4063
|
+
.values(payload as any);
|
|
4064
|
+
if (typeof createQuery.returning === "function") {
|
|
4065
|
+
createQuery = createQuery.returning();
|
|
4066
|
+
}
|
|
4067
|
+
const createdRows = (await createQuery) as Array<
|
|
4068
|
+
Record<string, unknown>
|
|
4069
|
+
>;
|
|
4070
|
+
const createdRow = createdRows[0];
|
|
4071
|
+
if (createdRow) {
|
|
4072
|
+
relatedRows.push(createdRow);
|
|
4073
|
+
}
|
|
4074
|
+
}
|
|
4075
|
+
continue;
|
|
4076
|
+
}
|
|
4077
|
+
|
|
4078
|
+
const junctionTable = (mergedSchema as Record<string, unknown>)[
|
|
4079
|
+
relationInput.relation.junctionTable
|
|
4080
|
+
];
|
|
4081
|
+
if (!junctionTable) {
|
|
4082
|
+
throw new Error(
|
|
4083
|
+
"Unknown junction table '" +
|
|
4084
|
+
relationInput.relation.junctionTable +
|
|
4085
|
+
"' for relation '" +
|
|
4086
|
+
tableName +
|
|
4087
|
+
"." +
|
|
4088
|
+
relationInput.relationName +
|
|
4089
|
+
"'.",
|
|
4090
|
+
);
|
|
4091
|
+
}
|
|
4092
|
+
|
|
4093
|
+
const sourceField = relationInput.relation.sourceField;
|
|
4094
|
+
const targetField = relationInput.relation.targetField;
|
|
4095
|
+
if (!sourceField || !targetField) {
|
|
4096
|
+
throw new Error(
|
|
4097
|
+
"Relation '" +
|
|
4098
|
+
tableName +
|
|
4099
|
+
"." +
|
|
4100
|
+
relationInput.relationName +
|
|
4101
|
+
"' is missing junction metadata fields.",
|
|
4102
|
+
);
|
|
4103
|
+
}
|
|
4104
|
+
|
|
4105
|
+
const linkValues: Array<Record<string, unknown>> = [];
|
|
4106
|
+
const targetIdentifiers: unknown[] = [];
|
|
4107
|
+
for (const relationItem of relationItems) {
|
|
4108
|
+
const targetId = await resolveRelationIdentifier(
|
|
4109
|
+
tx,
|
|
4110
|
+
relationInput.relation,
|
|
4111
|
+
relationInput.relationName,
|
|
4112
|
+
relationItem,
|
|
4113
|
+
);
|
|
4114
|
+
targetIdentifiers.push(targetId);
|
|
4115
|
+
|
|
4116
|
+
linkValues.push({
|
|
4117
|
+
[sourceField]: parentReferenceValue,
|
|
4118
|
+
[targetField]: targetId,
|
|
4119
|
+
});
|
|
4120
|
+
}
|
|
4121
|
+
|
|
4122
|
+
if (linkValues.length > 0) {
|
|
4123
|
+
await tx.insert(junctionTable as any).values(linkValues as any);
|
|
4124
|
+
}
|
|
4125
|
+
|
|
4126
|
+
for (const targetId of targetIdentifiers) {
|
|
4127
|
+
const linkedRow = await fetchRelatedRowByIdentifier(
|
|
4128
|
+
tx,
|
|
4129
|
+
relationInput.relation,
|
|
4130
|
+
relationInput.relationName,
|
|
4131
|
+
targetId,
|
|
4132
|
+
);
|
|
4133
|
+
if (linkedRow) {
|
|
4134
|
+
relatedRows.push(linkedRow);
|
|
4135
|
+
}
|
|
4136
|
+
}
|
|
4137
|
+
}
|
|
4138
|
+
|
|
4139
|
+
hydratedRows.push(hydratedRow);
|
|
4140
|
+
}
|
|
4141
|
+
|
|
4142
|
+
return hydratedRows as Array<QueryInsertResultRow<TableName, TArgs>>;
|
|
4143
|
+
};
|
|
2991
4144
|
|
|
2992
|
-
|
|
2993
|
-
|
|
4145
|
+
let rows: Array<QueryInsertResultRow<TableName, TArgs>>;
|
|
4146
|
+
if (typeof transaction === "function") {
|
|
4147
|
+
try {
|
|
4148
|
+
rows = await transaction.call($db, (tx: any) =>
|
|
4149
|
+
executeInsertGraph(tx),
|
|
4150
|
+
);
|
|
4151
|
+
} catch (error) {
|
|
4152
|
+
const message =
|
|
4153
|
+
error instanceof Error ? error.message : String(error);
|
|
4154
|
+
const lowered = message.toLowerCase();
|
|
4155
|
+
if (
|
|
4156
|
+
lowered.includes("failed query: begin") ||
|
|
4157
|
+
lowered.includes('near "begin"') ||
|
|
4158
|
+
lowered.includes("cannot start a transaction")
|
|
4159
|
+
) {
|
|
4160
|
+
rows = await executeInsertGraph($db as any);
|
|
4161
|
+
} else {
|
|
4162
|
+
throw error;
|
|
4163
|
+
}
|
|
4164
|
+
}
|
|
4165
|
+
} else {
|
|
4166
|
+
rows = await executeInsertGraph($db as any);
|
|
2994
4167
|
}
|
|
2995
4168
|
|
|
2996
|
-
const rows = (await insertQuery) as Array<TableModel<TableName>>;
|
|
2997
4169
|
emitMutation(
|
|
2998
4170
|
"insert",
|
|
2999
4171
|
{ values: args.values as unknown as Record<string, unknown> },
|
|
@@ -3118,9 +4290,9 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
3118
4290
|
);
|
|
3119
4291
|
return rows;
|
|
3120
4292
|
},
|
|
3121
|
-
`}function
|
|
4293
|
+
`}function Me(){return [qe(),$e(),Ie(),Ae(),Ne()].join(`
|
|
3122
4294
|
|
|
3123
|
-
`)}function
|
|
4295
|
+
`)}function Ce(){return `type AuthSession = typeof auth.$Infer.Session;
|
|
3124
4296
|
type User = AuthSession['user']
|
|
3125
4297
|
type Session = AuthSession['session']
|
|
3126
4298
|
|
|
@@ -3181,7 +4353,7 @@ export type AppflareContext = {
|
|
|
3181
4353
|
storage: AppflareStorage;
|
|
3182
4354
|
error: (status: number, message: string, details?: unknown) => never;
|
|
3183
4355
|
};
|
|
3184
|
-
`}function
|
|
4356
|
+
`}function Pe(){return `type InferOperationArgs<TShape extends ZodRawShape> = z.output<z.ZodObject<TShape>>;
|
|
3185
4357
|
|
|
3186
4358
|
export type SchedulerEnqueueOptions = {
|
|
3187
4359
|
delaySeconds?: number;
|
|
@@ -3313,22 +4485,22 @@ export function cron(definition: CronDefinition): RegisteredCron {
|
|
|
3313
4485
|
definition,
|
|
3314
4486
|
};
|
|
3315
4487
|
}
|
|
3316
|
-
`}function
|
|
4488
|
+
`}function De(){return [xe(),Se(),Me(),Ce(),Pe()].join(`
|
|
3317
4489
|
|
|
3318
|
-
`)}function
|
|
4490
|
+
`)}function Fe(e){return `import type { Context } from "hono";
|
|
3319
4491
|
import type { D1Database } from "@cloudflare/workers-types";
|
|
3320
4492
|
import { drizzle } from "drizzle-orm/d1";
|
|
3321
4493
|
import { z, type ZodRawShape } from "zod";
|
|
3322
4494
|
import * as authSchema from "./auth.schema";
|
|
3323
|
-
import * as schema from "${
|
|
4495
|
+
import * as schema from "${e}";
|
|
3324
4496
|
|
|
3325
|
-
${
|
|
3326
|
-
`}function
|
|
3327
|
-
`)}function
|
|
3328
|
-
`)}function
|
|
3329
|
-
`)}function
|
|
4497
|
+
${De()}
|
|
4498
|
+
`}function En(e){let t=e.replace(/[^A-Za-z0-9_]/g,"_");return /^[0-9]/.test(t)?`_${t}`:t}function On(e,t){let n=e.routePath.replace(/^\//,"").replace(/\//g,"_");return En(`op_${t}_${n}`)}function jn(e){return e.map((t,n)=>({operation:t,index:n,alias:On(t,n)}))}function Vn(e){return e.map(({operation:t,alias:n})=>`import { ${t.exportName} as ${n} } from "${t.importPath}";`).join(`
|
|
4499
|
+
`)}function Bn(e){return e.filter(({operation:t})=>t.kind==="query"||t.kind==="mutation").map(({alias:t})=>`const ${`${t}Schema`} = z.object(${t}.definition.args);`).join(`
|
|
4500
|
+
`)}function Hn(e){return e.filter(({operation:t})=>t.kind==="scheduler").map(({alias:t})=>`const ${`${t}SchedulerSchema`} = ${t}.definition.args ? z.object(${t}.definition.args) : z.undefined();`).join(`
|
|
4501
|
+
`)}function Wn(e){return e.filter(({operation:t})=>t.kind==="query").map(({operation:t,alias:n})=>{let r=`${n}Schema`;return `
|
|
3330
4502
|
app.get(
|
|
3331
|
-
"${
|
|
4503
|
+
"${t.routePath}",
|
|
3332
4504
|
sValidator("query", ${r}),
|
|
3333
4505
|
async (c) => {
|
|
3334
4506
|
const ctx = await createExecutionContext(c, options);
|
|
@@ -3339,9 +4511,9 @@ ${Ct()}
|
|
|
3339
4511
|
}
|
|
3340
4512
|
},
|
|
3341
4513
|
);`}).join(`
|
|
3342
|
-
`)}function
|
|
4514
|
+
`)}function Ln(e){return e.filter(({operation:t})=>t.kind==="mutation").map(({operation:t,alias:n})=>{let r=`${n}Schema`;return `
|
|
3343
4515
|
app.post(
|
|
3344
|
-
"${
|
|
4516
|
+
"${t.routePath}",
|
|
3345
4517
|
sValidator("json", ${r}),
|
|
3346
4518
|
async (c) => {
|
|
3347
4519
|
const ctx = await createExecutionContext(c, options);
|
|
@@ -3354,26 +4526,26 @@ ${Ct()}
|
|
|
3354
4526
|
}
|
|
3355
4527
|
},
|
|
3356
4528
|
);`}).join(`
|
|
3357
|
-
`)}function
|
|
4529
|
+
`)}function zn(e){return e.filter(({operation:t})=>t.kind==="query").map(({operation:t,alias:n})=>{let r=`${n}Schema`,a=t.handlerName??t.routePath;return `
|
|
3358
4530
|
${JSON.stringify(a)}: {
|
|
3359
4531
|
definition: ${n}.definition,
|
|
3360
4532
|
schema: ${r},
|
|
3361
4533
|
},`}).join(`
|
|
3362
|
-
`)}function
|
|
4534
|
+
`)}function Un(e){return e.filter(({operation:t})=>t.kind==="scheduler").map(({operation:t,alias:n})=>{let r=`${n}SchedulerSchema`,a=t.taskName??`${t.routePath}`;return `
|
|
3363
4535
|
${JSON.stringify(a)}: {
|
|
3364
4536
|
definition: ${n}.definition,
|
|
3365
4537
|
schema: ${r},
|
|
3366
4538
|
},`}).join(`
|
|
3367
|
-
`)}function
|
|
3368
|
-
`)}function
|
|
4539
|
+
`)}function Qn(e){return e.filter(({operation:t})=>t.kind==="scheduler").map(({operation:t,alias:n})=>{let r=t.taskName??`${t.routePath}`;return ` ${JSON.stringify(r)}: Parameters<typeof ${n}.definition.handler>[1];`}).join(`
|
|
4540
|
+
`)}function _n(e){return e.filter(({operation:t})=>t.kind==="cron").map(({operation:t,alias:n})=>{let r=t.taskName??`${t.routePath}`,a=t.cronTriggers??[];return `
|
|
3369
4541
|
{
|
|
3370
4542
|
taskName: ${JSON.stringify(r)},
|
|
3371
4543
|
cronTriggers: ${JSON.stringify(a)},
|
|
3372
4544
|
definition: ${n}.definition,
|
|
3373
4545
|
},`}).join(`
|
|
3374
|
-
`)}function
|
|
3375
|
-
${
|
|
3376
|
-
`)}function
|
|
4546
|
+
`)}function Kn(e){return e.filter(({operation:t})=>t.kind==="storage").map(({alias:t})=>`
|
|
4547
|
+
${t}.definition.handler,`).join(`
|
|
4548
|
+
`)}function Ee(e){let t=jn(e);return {imports:Vn(t),operationSchemas:Bn(t),schedulerSchemas:Hn(t),queryRoutes:Wn(t),mutationRoutes:Ln(t),queryRegistryEntries:zn(t),schedulerEntries:Un(t),schedulerPayloadMapEntries:Qn(t),cronEntries:_n(t),storageHandlersEntries:Kn(t)}}var Oe=`
|
|
3377
4549
|
function getRealtimeStub(
|
|
3378
4550
|
env: Record<string, unknown>,
|
|
3379
4551
|
options: RegisterHandlersOptions,
|
|
@@ -3447,7 +4619,7 @@ function buildRealtimeWsUrl(requestUrl: string, websocketPath: string): string {
|
|
|
3447
4619
|
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
3448
4620
|
return url.toString();
|
|
3449
4621
|
}
|
|
3450
|
-
`;var
|
|
4622
|
+
`;var je=`
|
|
3451
4623
|
export class AppflareRealtimeDurableObject {
|
|
3452
4624
|
private readonly subscriptions = new Map<string, RealtimeSubscription>();
|
|
3453
4625
|
private readonly sockets = new Map<string, WebSocket>();
|
|
@@ -3590,7 +4762,7 @@ export class AppflareRealtimeDurableObject {
|
|
|
3590
4762
|
return new Response("Not found", { status: 404 });
|
|
3591
4763
|
}
|
|
3592
4764
|
}
|
|
3593
|
-
`;var
|
|
4765
|
+
`;var Ve=`
|
|
3594
4766
|
async function publishMutationEvents(
|
|
3595
4767
|
c: { req: { raw: Request }; env: Record<string, unknown> },
|
|
3596
4768
|
options: RegisterHandlersOptions,
|
|
@@ -3691,7 +4863,7 @@ async function publishMutationEvents(
|
|
|
3691
4863
|
}
|
|
3692
4864
|
}
|
|
3693
4865
|
}
|
|
3694
|
-
`;var
|
|
4866
|
+
`;var Be=`
|
|
3695
4867
|
function registerRealtimeRoutes(
|
|
3696
4868
|
app: Hono<WorkerEnv>,
|
|
3697
4869
|
options: RegisterHandlersOptions,
|
|
@@ -3854,7 +5026,7 @@ function registerRealtimeRoutes(
|
|
|
3854
5026
|
return stub.fetch(c.req.raw);
|
|
3855
5027
|
});
|
|
3856
5028
|
}
|
|
3857
|
-
`;var
|
|
5029
|
+
`;var He=`
|
|
3858
5030
|
type RealtimeSubscription = {
|
|
3859
5031
|
token: string;
|
|
3860
5032
|
signature: string;
|
|
@@ -3883,7 +5055,7 @@ type RealtimeDurableObjectNamespace = {
|
|
|
3883
5055
|
type RealtimeQueryName = keyof typeof realtimeQueryHandlers extends never
|
|
3884
5056
|
? string
|
|
3885
5057
|
: Extract<keyof typeof realtimeQueryHandlers, string>;
|
|
3886
|
-
`;var
|
|
5058
|
+
`;var We=`
|
|
3887
5059
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
3888
5060
|
return typeof value === "object" && value !== null;
|
|
3889
5061
|
}
|
|
@@ -4398,9 +5570,9 @@ function doesSubscriptionMatchMutation(
|
|
|
4398
5570
|
|
|
4399
5571
|
return false;
|
|
4400
5572
|
}
|
|
4401
|
-
`;var
|
|
5573
|
+
`;var Le=[He,We,Oe,Ve,Be,je].join(`
|
|
4402
5574
|
|
|
4403
|
-
`);var
|
|
5575
|
+
`);var ze=`
|
|
4404
5576
|
function parseExpiresIn(value: string | undefined): number | undefined {
|
|
4405
5577
|
if (!value) {
|
|
4406
5578
|
return undefined;
|
|
@@ -4593,7 +5765,7 @@ export function registerGeneratedStorageRoutes(
|
|
|
4593
5765
|
}
|
|
4594
5766
|
});
|
|
4595
5767
|
}
|
|
4596
|
-
`;var
|
|
5768
|
+
`;var Ue=`
|
|
4597
5769
|
type SchedulerTaskName = keyof typeof schedulerHandlers extends never
|
|
4598
5770
|
? string
|
|
4599
5771
|
: keyof typeof schedulerHandlers;
|
|
@@ -4648,7 +5820,7 @@ export async function executeScheduledBatch(
|
|
|
4648
5820
|
}
|
|
4649
5821
|
}
|
|
4650
5822
|
}
|
|
4651
|
-
`;var
|
|
5823
|
+
`;var Qe=`
|
|
4652
5824
|
export async function executeCronTriggers(
|
|
4653
5825
|
controller: { cron: string },
|
|
4654
5826
|
env: Record<string, unknown>,
|
|
@@ -4677,7 +5849,7 @@ export async function executeCronTriggers(
|
|
|
4677
5849
|
}
|
|
4678
5850
|
}
|
|
4679
5851
|
}
|
|
4680
|
-
`;function
|
|
5852
|
+
`;function _e(e){let{imports:t,operationSchemas:n,schedulerSchemas:r,queryRoutes:a,mutationRoutes:o,queryRegistryEntries:i,schedulerEntries:s,schedulerPayloadMapEntries:l,cronEntries:u,storageHandlersEntries:c}=Ee(e);return `import { sValidator } from "@hono/standard-validator";
|
|
4681
5853
|
import type { Hono } from "hono";
|
|
4682
5854
|
import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@cloudflare/workers-types";
|
|
4683
5855
|
import { ZodError, z } from "zod";
|
|
@@ -4694,8 +5866,8 @@ import {
|
|
|
4694
5866
|
} from "./handlers";
|
|
4695
5867
|
import { createExecutionContext, createSchedulerExecutionContext, resolveSession } from "./handlers.context";
|
|
4696
5868
|
import { executeOperation, handleOperationError } from "./handlers.execution";
|
|
4697
|
-
${
|
|
4698
|
-
${
|
|
5869
|
+
${t?`
|
|
5870
|
+
${t}`:""}
|
|
4699
5871
|
|
|
4700
5872
|
${n}
|
|
4701
5873
|
${r}
|
|
@@ -4716,19 +5888,19 @@ declare global {
|
|
|
4716
5888
|
interface AppflareSchedulerHandlerMap extends GeneratedSchedulerPayloadMap {}
|
|
4717
5889
|
}
|
|
4718
5890
|
|
|
4719
|
-
const cronHandlers = [${
|
|
5891
|
+
const cronHandlers = [${u||`
|
|
4720
5892
|
`}
|
|
4721
5893
|
] as const;
|
|
4722
5894
|
|
|
4723
|
-
const storageHandlers = [${
|
|
5895
|
+
const storageHandlers = [${c||`
|
|
4724
5896
|
`}
|
|
4725
5897
|
] as const;
|
|
4726
5898
|
|
|
4727
5899
|
setStorageHandlers([...storageHandlers]);
|
|
4728
5900
|
|
|
4729
|
-
${
|
|
5901
|
+
${Ue}
|
|
4730
5902
|
|
|
4731
|
-
${
|
|
5903
|
+
${Le}
|
|
4732
5904
|
|
|
4733
5905
|
export function registerGeneratedHandlers(
|
|
4734
5906
|
app: Hono<WorkerEnv>,
|
|
@@ -4741,20 +5913,20 @@ export function registerGeneratedHandlers(
|
|
|
4741
5913
|
`}
|
|
4742
5914
|
}
|
|
4743
5915
|
|
|
4744
|
-
${
|
|
5916
|
+
${ze}
|
|
4745
5917
|
|
|
4746
|
-
${
|
|
4747
|
-
`}function
|
|
4748
|
-
KV: c.env["${
|
|
4749
|
-
DATABASE: c.env["${
|
|
4750
|
-
}`}function
|
|
5918
|
+
${Qe}
|
|
5919
|
+
`}function H(e,t,n){let r=Fe(e),a=be(n),o=we(),i=_e(t);return [{relativePath:"handlers.ts",source:r},{relativePath:"handlers.context.ts",source:a},{relativePath:"handlers.execution.ts",source:o},{relativePath:"handlers.routes.ts",source:i}]}function Gn(e){return e?`,
|
|
5920
|
+
KV: c.env["${e}"] as KVNamespace`:""}function Ke(e,t){return `{
|
|
5921
|
+
DATABASE: c.env["${e}"] as D1Database${Gn(t)}
|
|
5922
|
+
}`}function Ge(e,t,n){return `app.on(["GET", "POST"], "${e}/*", async (c) => {
|
|
4751
5923
|
const auth = createAuth(
|
|
4752
|
-
${
|
|
5924
|
+
${Ke(t,n)},
|
|
4753
5925
|
c.req.raw.cf as IncomingRequestCfProperties | undefined,
|
|
4754
5926
|
);
|
|
4755
5927
|
return auth.handler(getSanitizedRequest(c.req.raw));
|
|
4756
5928
|
});
|
|
4757
|
-
`}function
|
|
5929
|
+
`}function Jn(){return `export const getHeaders = (headers: Headers) => {
|
|
4758
5930
|
const newHeaders = Object.fromEntries(headers as any);
|
|
4759
5931
|
const headerObject: Record<string, any> = {};
|
|
4760
5932
|
let hasCookie = false;
|
|
@@ -4784,15 +5956,15 @@ ${zt}
|
|
|
4784
5956
|
|
|
4785
5957
|
return headerObject as any as Headers;
|
|
4786
5958
|
};
|
|
4787
|
-
`}function
|
|
5959
|
+
`}function Zn(){return `export const getSanitizedRequest = (req: Request) => {
|
|
4788
5960
|
const newRequest = new Request(req, {
|
|
4789
5961
|
headers: getHeaders(req.headers),
|
|
4790
5962
|
});
|
|
4791
5963
|
return newRequest;
|
|
4792
5964
|
};
|
|
4793
|
-
`}function
|
|
4794
|
-
`+
|
|
4795
|
-
`+
|
|
5965
|
+
`}function Je(){return Jn()+`
|
|
5966
|
+
`+Zn()}function Ze(e,t,n){return Ge(e,t,n)+`
|
|
5967
|
+
`+Je()}function Ye(){return `const app = new Hono<WorkerEnv>();
|
|
4796
5968
|
|
|
4797
5969
|
app.use('*', cors({
|
|
4798
5970
|
origin: (origin, c) => {
|
|
@@ -4808,7 +5980,7 @@ app.use('*', cors({
|
|
|
4808
5980
|
},
|
|
4809
5981
|
credentials: true
|
|
4810
5982
|
}));
|
|
4811
|
-
`}function
|
|
5983
|
+
`}function Xe(){return `export { AppflareRealtimeDurableObject };
|
|
4812
5984
|
|
|
4813
5985
|
export default {
|
|
4814
5986
|
fetch: app.fetch,
|
|
@@ -4819,42 +5991,42 @@ export default {
|
|
|
4819
5991
|
await executeCronTriggers(controller, env, generatedHandlerOptions);
|
|
4820
5992
|
},
|
|
4821
5993
|
};
|
|
4822
|
-
`}function
|
|
4823
|
-
kvBinding: "${
|
|
4824
|
-
r2Binding: "${r}",`:"",
|
|
5994
|
+
`}function et(e,t,n="APPFLARE_SCHEDULER_QUEUE",r,a="APPFLARE_REALTIME",o="global",i="/realtime/subscribe",s="/realtime/ws",l="appflare.realtime.v1"){let u=t?`
|
|
5995
|
+
kvBinding: "${t}",`:"",c=r?`
|
|
5996
|
+
r2Binding: "${r}",`:"",f=`
|
|
4825
5997
|
realtimeBinding: "${a}",
|
|
4826
5998
|
realtimeObjectName: "${o}",
|
|
4827
5999
|
realtimeSubscribePath: "${i}",
|
|
4828
6000
|
realtimeWebsocketPath: "${s}",
|
|
4829
6001
|
realtimeProtocol: "${l}",`;return `const generatedHandlerOptions = {
|
|
4830
|
-
databaseBinding: "${
|
|
4831
|
-
schedulerBinding: "${n}",${
|
|
6002
|
+
databaseBinding: "${e}",${u}
|
|
6003
|
+
schedulerBinding: "${n}",${c}${f}
|
|
4832
6004
|
};
|
|
4833
6005
|
registerGeneratedHandlers(app, generatedHandlerOptions);
|
|
4834
6006
|
registerGeneratedStorageRoutes(app, generatedHandlerOptions);
|
|
4835
6007
|
registerAdminDashboard(app, generatedHandlerOptions);
|
|
4836
|
-
`}function
|
|
6008
|
+
`}function tt(){return `import { createAuth } from "./auth.config";
|
|
4837
6009
|
import { AppflareRealtimeDurableObject, executeCronTriggers, executeScheduledBatch, registerGeneratedHandlers, registerGeneratedStorageRoutes } from "./handlers.routes";
|
|
4838
6010
|
import { registerAdminDashboard } from "./admin.routes";
|
|
4839
6011
|
import { Hono } from "hono";
|
|
4840
6012
|
import { cors } from "hono/cors";
|
|
4841
6013
|
import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@cloudflare/workers-types";
|
|
4842
|
-
`}function
|
|
6014
|
+
`}function nt(){return `type WorkerEnv = {
|
|
4843
6015
|
Bindings: Record<string, unknown>;
|
|
4844
6016
|
};
|
|
4845
|
-
`}function
|
|
6017
|
+
`}function rt(e,t,n,r,a,o,i,s,l,u){return tt()+nt()+Ye()+et(t,n,r,a,o,i,s,l,u)+Ze(e,t,n)+Xe()}function at(e){return !!e&&typeof e=="object"&&!Array.isArray(e)}function W(e,t){let n={...e};for(let[r,a]of Object.entries(t)){let o=n[r];if(at(o)&&at(a)){n[r]=W(o,a);continue}n[r]=a;}return n}function Yn(e){return Array.from(new Set(e.filter(t=>t.length>0)))}function ot(e,t){let n=t.filter(d=>d.kind==="scheduler"||d.kind==="cron"),r=Yn(t.filter(d=>d.kind==="cron").flatMap(d=>d.cronTriggers??[])),a=e.config.scheduler.enabled&&n.length>0,o=e.config.realtime.enabled,s=(typeof e.config.wranglerOverrides?.name=="string"?e.config.wranglerOverrides.name:void 0)??"appflare-worker",l=e.config.scheduler.queue??`${s}-scheduler`,u={name:s,main:"./src/index.ts",d1_databases:e.config.database.map(d=>({binding:d.binding,database_name:d.databaseName,database_id:d.databaseId,preview_database_id:d.previewDatabaseId??d.databaseId,...d.migrationsDir?{migrations_dir:d.migrationsDir}:{}})),kv_namespaces:e.config.kv.map(d=>({binding:d.binding,id:d.id,...d.previewId?{preview_id:d.previewId}:{}})),r2_buckets:e.config.r2.map(d=>({binding:d.binding,bucket_name:d.bucketName,...d.previewBucketName?{preview_bucket_name:d.previewBucketName}:{},...d.jurisdiction?{jurisdiction:d.jurisdiction}:{}})),...a?{queues:{producers:[{binding:e.config.scheduler.binding,queue:l}],consumers:[{queue:l}]}}:{},...r.length>0?{triggers:{crons:r}}:{},...o?{durable_objects:{bindings:[{name:e.config.realtime.binding,class_name:e.config.realtime.className}]},migrations:[{tag:"appflare-realtime-v1",new_sqlite_classes:[e.config.realtime.className]}]}:{}};if(!e.config.wranglerOverrides)return u;let{scheduler:c,...f}=e.config.wranglerOverrides;return W(u,f)}function it(e){return e.tables.map(t=>({exportName:t.exportName,tableName:t.tableName,columns:t.columns.map(n=>n.name)}))}function st(e){return `<li data-name="users">
|
|
4846
6018
|
<a href="/admin/users" hx-get="/admin/users" hx-target="#main-content" hx-push-url="true" hx-swap="outerHTML" class="sidebar-link flex items-center gap-2 px-3 py-2 text-sm rounded-lg w-full">
|
|
4847
6019
|
<iconify-icon icon="mdi:account-group" width="16" height="16" class="opacity-50 shrink-0"></iconify-icon>
|
|
4848
6020
|
<span class="truncate">users</span>
|
|
4849
6021
|
</a>
|
|
4850
6022
|
</li>
|
|
4851
|
-
${
|
|
6023
|
+
${e.map(n=>`<li data-name="${n.tableName}">
|
|
4852
6024
|
<a href="/admin/table/${n.exportName}" hx-get="/admin/table/${n.exportName}" hx-target="#main-content" hx-push-url="true" hx-swap="outerHTML" class="sidebar-link flex items-center gap-2 px-3 py-2 text-sm rounded-lg w-full">
|
|
4853
6025
|
<iconify-icon icon="mdi:table" width="16" height="16" class="opacity-50 shrink-0"></iconify-icon>
|
|
4854
6026
|
<span class="truncate">${n.tableName}</span>
|
|
4855
6027
|
</a>
|
|
4856
6028
|
</li>`).join(`
|
|
4857
|
-
`)}`}function
|
|
6029
|
+
`)}`}function lt(e){let t=e.filter(o=>o.kind==="query"),n=e.filter(o=>o.kind==="mutation"),r=t.map(o=>`
|
|
4858
6030
|
<li data-name="${o.exportName}">
|
|
4859
6031
|
<a href="/admin/functions${o.routePath}" hx-get="/admin/functions${o.routePath}" hx-target="#main-content" hx-push-url="true" hx-swap="outerHTML" class="sidebar-link flex items-center gap-2 px-3 py-2 text-sm rounded-lg w-full">
|
|
4860
6032
|
<iconify-icon icon="solar:reorder-linear" width="16" height="16" class="opacity-50 shrink-0"></iconify-icon>
|
|
@@ -4882,15 +6054,15 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
4882
6054
|
</div>
|
|
4883
6055
|
</div>
|
|
4884
6056
|
<nav class="flex-1 overflow-y-auto px-2 pb-4">
|
|
4885
|
-
${
|
|
6057
|
+
${t.length>0?`<p class="text-[9px] font-bold uppercase tracking-wider opacity-25 mt-4 mb-1 px-2">Queries</p>
|
|
4886
6058
|
<ul class="flex flex-col gap-0.5">${r}</ul>`:""}
|
|
4887
6059
|
${n.length>0?`<p class="text-[9px] font-bold uppercase tracking-wider opacity-25 mt-4 mb-1 px-2">Mutations</p>
|
|
4888
6060
|
<ul class="flex flex-col gap-0.5">${a}</ul>`:""}
|
|
4889
6061
|
</nav>
|
|
4890
6062
|
</div>
|
|
4891
|
-
`}function
|
|
6063
|
+
`}function ct(e){return e.map(t=>`
|
|
4892
6064
|
<a
|
|
4893
|
-
href="/admin/table/${
|
|
6065
|
+
href="/admin/table/${t.exportName}"
|
|
4894
6066
|
class="card bg-base-100 border border-base-200 hover:border-primary/30 hover:shadow-md transition-all cursor-pointer group"
|
|
4895
6067
|
>
|
|
4896
6068
|
<div class="card-body p-5">
|
|
@@ -4899,18 +6071,18 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
4899
6071
|
<iconify-icon icon="mdi:table" width="20" height="20" class="text-primary"></iconify-icon>
|
|
4900
6072
|
</div>
|
|
4901
6073
|
<div>
|
|
4902
|
-
<h2 class="font-semibold text-sm capitalize group-hover:text-primary transition-colors">${
|
|
6074
|
+
<h2 class="font-semibold text-sm capitalize group-hover:text-primary transition-colors">${t.tableName}</h2>
|
|
4903
6075
|
<p class="text-xs opacity-40 mt-0.5">Manage records</p>
|
|
4904
6076
|
</div>
|
|
4905
6077
|
</div>
|
|
4906
6078
|
</div>
|
|
4907
6079
|
</a>
|
|
4908
|
-
`.replace(/\n/g,"\\n")).join("")}function
|
|
4909
|
-
try { searchConditions.push(like(tableSchema.${
|
|
4910
|
-
`).join("")}function
|
|
6080
|
+
`.replace(/\n/g,"\\n")).join("")}function ut(e){return e.columns.filter(t=>t.type==="string").map(t=>`
|
|
6081
|
+
try { searchConditions.push(like(tableSchema.${t.name}, \`%\${search}%\`)); } catch (e) {}
|
|
6082
|
+
`).join("")}function Xn(e){switch(e){case "number":return "mdi:pound";case "boolean":return "mdi:toggle-switch-outline";case "date":return "mdi:calendar";default:return "mdi:format-text"}}function dt(e,t){return t.map(n=>{let r=e.columns.find(o=>o.name===n),a=r?Xn(r.type):"mdi:format-text";return `
|
|
4911
6083
|
<th>
|
|
4912
6084
|
<a href="#"
|
|
4913
|
-
hx-get="/admin/table/${
|
|
6085
|
+
hx-get="/admin/table/${e.exportName}?page=\${page}&search=\${search}&sort=${n}&order=\${sort === '${n}' && order === 'asc' ? 'desc' : 'asc'}"
|
|
4914
6086
|
hx-target="#main-content"
|
|
4915
6087
|
hx-push-url="true"
|
|
4916
6088
|
class="hover:text-primary flex items-center gap-1.5 transition-colors whitespace-nowrap">
|
|
@@ -4919,22 +6091,22 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
4919
6091
|
<span class="text-[10px] opacity-30">\${sort === '${n}' ? (order === 'asc' ? '\u25B2' : '\u25BC') : ''}</span>
|
|
4920
6092
|
</a>
|
|
4921
6093
|
</th>
|
|
4922
|
-
`}).join("")}function
|
|
6094
|
+
`}).join("")}function pt(e,t){return e.map(n=>t&&n===t?`<td><button type="button" class="truncate max-w-[200px] text-sm font-mono text-xs opacity-70 hover:opacity-100 cursor-copy text-left" title="Click to copy: \${String((row as any).${n} ?? '')}" data-copy-value="\${String((row as any).${n} ?? '')}" onclick="navigator.clipboard?.writeText(this.dataset.copyValue || '')">\${String((row as any).${n} ?? '')}</button></td>`:`<td><div class="truncate max-w-[200px] text-sm" title="\${String((row as any).${n} ?? '')}">\${String((row as any).${n} ?? '')}</div></td>`).join("")}function L(e,t,n){let r=e.columns.find(i=>i.name===t);if(!r)return "";let a=r.optional?"":" required",o=r.type==="number"?"number":r.type==="date"?"date":"text";if(r.type==="boolean")return n==="edit"?`
|
|
4923
6095
|
<div class="form-control">
|
|
4924
6096
|
<label class="label cursor-pointer justify-start gap-3">
|
|
4925
|
-
<input type="checkbox" name="${
|
|
4926
|
-
<span class="label-text text-sm">${
|
|
6097
|
+
<input type="checkbox" name="${t}" value="true" class="checkbox checkbox-sm checkbox-primary" \${(row as any).${t} ? 'checked' : ''} />
|
|
6098
|
+
<span class="label-text text-sm">${t}</span>
|
|
4927
6099
|
</label>
|
|
4928
6100
|
</div>
|
|
4929
6101
|
`:`
|
|
4930
6102
|
<div class="form-control">
|
|
4931
6103
|
<label class="label cursor-pointer justify-start gap-3">
|
|
4932
|
-
<input type="checkbox" name="${
|
|
4933
|
-
<span class="label-text text-sm">${
|
|
6104
|
+
<input type="checkbox" name="${t}" value="true" class="checkbox checkbox-sm checkbox-primary" />
|
|
6105
|
+
<span class="label-text text-sm">${t}</span>
|
|
4934
6106
|
</label>
|
|
4935
6107
|
</div>
|
|
4936
6108
|
`;if(n==="edit"){let i=r.type==="date"?`\${(() => {
|
|
4937
|
-
const value = (row as any).${
|
|
6109
|
+
const value = (row as any).${t};
|
|
4938
6110
|
if (value == null || value === '') return '';
|
|
4939
6111
|
|
|
4940
6112
|
const date =
|
|
@@ -4947,17 +6119,17 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
4947
6119
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
4948
6120
|
const day = String(date.getDate()).padStart(2, '0');
|
|
4949
6121
|
return String(year) + '-' + month + '-' + day;
|
|
4950
|
-
})()}`:`\${String((row as any).${
|
|
6122
|
+
})()}`:`\${String((row as any).${t} ?? '')}`;return `
|
|
4951
6123
|
<div class="form-control">
|
|
4952
|
-
<label class="label"><span class="label-text text-sm font-medium">${
|
|
4953
|
-
<input type="${o}" name="${
|
|
6124
|
+
<label class="label"><span class="label-text text-sm font-medium">${t}</span></label>
|
|
6125
|
+
<input type="${o}" name="${t}" class="input input-bordered w-full text-sm" value="${i}"${a} />
|
|
4954
6126
|
</div>
|
|
4955
6127
|
`}return `
|
|
4956
6128
|
<div class="form-control">
|
|
4957
|
-
<label class="label"><span class="label-text text-sm font-medium">${
|
|
4958
|
-
<input type="${o}" name="${
|
|
6129
|
+
<label class="label"><span class="label-text text-sm font-medium">${t}</span></label>
|
|
6130
|
+
<input type="${o}" name="${t}" class="input input-bordered w-full text-sm"${a} />
|
|
4959
6131
|
</div>
|
|
4960
|
-
`}function
|
|
6132
|
+
`}function z(e,t){return t.map(n=>{let r=e.columns.find(o=>o.name===n);if(!r)return "";let a=r.optional?"":`
|
|
4961
6133
|
if (raw_${n} === '') {
|
|
4962
6134
|
return c.text('${n} is required', 400);
|
|
4963
6135
|
}
|
|
@@ -5002,19 +6174,19 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5002
6174
|
payload.${n} = raw_${n};
|
|
5003
6175
|
}
|
|
5004
6176
|
`}).join(`
|
|
5005
|
-
`)}function
|
|
6177
|
+
`)}function mt(e){return e.columns.find(t=>t.primaryKey)?.name||e.columns[0]?.name||""}function gt(e,t){let n=e.columns.find(r=>r.name===t);return !(!n||n.autoIncrement||n.primaryKey)}function ft(e,t){let n=e.columns.find(r=>r.name===t);return !(!n||n.primaryKey||n.autoIncrement)}function ht(e,t,n,r){return t?`<td class="text-right">
|
|
5006
6178
|
<div class="drawer drawer-end">
|
|
5007
|
-
<input id="edit-drawer-${
|
|
6179
|
+
<input id="edit-drawer-${e.exportName}-\${rowIndex}" type="checkbox" class="drawer-toggle" />
|
|
5008
6180
|
<div class="drawer-content">
|
|
5009
6181
|
<div class="flex items-center justify-end gap-1">
|
|
5010
|
-
<label for="edit-drawer-${
|
|
6182
|
+
<label for="edit-drawer-${e.exportName}-\${rowIndex}" class="btn btn-ghost btn-xs btn-square" title="Edit">
|
|
5011
6183
|
<iconify-icon icon="mdi:pencil-outline" width="15" height="15" class="opacity-50"></iconify-icon>
|
|
5012
6184
|
</label>
|
|
5013
|
-
<button type="button" class="btn btn-ghost btn-xs btn-square" title="Delete" onclick="document.getElementById('delete-dialog-${
|
|
6185
|
+
<button type="button" class="btn btn-ghost btn-xs btn-square" title="Delete" onclick="document.getElementById('delete-dialog-${e.exportName}-\${rowIndex}').showModal()">
|
|
5014
6186
|
<iconify-icon icon="mdi:delete-outline" width="15" height="15" class="opacity-50 hover:text-error"></iconify-icon>
|
|
5015
6187
|
</button>
|
|
5016
6188
|
</div>
|
|
5017
|
-
<dialog id="delete-dialog-${
|
|
6189
|
+
<dialog id="delete-dialog-${e.exportName}-\${rowIndex}" class="modal">
|
|
5018
6190
|
<div class="modal-box max-w-sm">
|
|
5019
6191
|
<h3 class="font-semibold text-base">Delete record?</h3>
|
|
5020
6192
|
<p class="py-3 text-sm text-base-content/60">This action cannot be undone.</p>
|
|
@@ -5022,7 +6194,7 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5022
6194
|
<form method="dialog">
|
|
5023
6195
|
<button class="btn btn-ghost btn-sm">Cancel</button>
|
|
5024
6196
|
</form>
|
|
5025
|
-
<form hx-post="/admin/table/${
|
|
6197
|
+
<form hx-post="/admin/table/${e.exportName}/delete" hx-target="#main-content" hx-swap="outerHTML" class="inline">
|
|
5026
6198
|
<input type="hidden" name="${n}" value="\${String((row as any).${n} ?? '')}" />
|
|
5027
6199
|
<input type="hidden" name="sort" value="\${sort}" />
|
|
5028
6200
|
<input type="hidden" name="order" value="\${order}" />
|
|
@@ -5035,15 +6207,15 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5035
6207
|
</dialog>
|
|
5036
6208
|
</div>
|
|
5037
6209
|
<div class="drawer-side z-50">
|
|
5038
|
-
<label for="edit-drawer-${
|
|
6210
|
+
<label for="edit-drawer-${e.exportName}-\${rowIndex}" aria-label="close sidebar" class="drawer-overlay"></label>
|
|
5039
6211
|
<div class="w-full max-w-md min-h-full bg-base-100 p-6 border-l border-base-200 overflow-y-auto shadow-lg">
|
|
5040
6212
|
<div class="flex justify-between items-center mb-5">
|
|
5041
|
-
<h3 class="text-base font-semibold">Edit ${
|
|
5042
|
-
<label for="edit-drawer-${
|
|
6213
|
+
<h3 class="text-base font-semibold">Edit ${e.tableName}</h3>
|
|
6214
|
+
<label for="edit-drawer-${e.exportName}-\${rowIndex}" class="btn btn-sm btn-ghost btn-square">
|
|
5043
6215
|
<iconify-icon icon="mdi:close" width="18" height="18"></iconify-icon>
|
|
5044
6216
|
</label>
|
|
5045
6217
|
</div>
|
|
5046
|
-
<form hx-post="/admin/table/${
|
|
6218
|
+
<form hx-post="/admin/table/${e.exportName}/edit" hx-target="#main-content" hx-swap="outerHTML" class="flex flex-col gap-4">
|
|
5047
6219
|
<input type="hidden" name="${n}" value="\${String((row as any).${n} ?? '')}" />
|
|
5048
6220
|
<input type="hidden" name="sort" value="\${sort}" />
|
|
5049
6221
|
<input type="hidden" name="order" value="\${order}" />
|
|
@@ -5055,7 +6227,7 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5055
6227
|
</div>
|
|
5056
6228
|
</div>
|
|
5057
6229
|
</div>
|
|
5058
|
-
</td>`:'<td class="text-right"><span class="text-xs opacity-30">No primary key</span></td>'}function
|
|
6230
|
+
</td>`:'<td class="text-right"><span class="text-xs opacity-30">No primary key</span></td>'}function I(e){return `
|
|
5059
6231
|
<div class="flex flex-col sm:flex-row justify-between items-center mt-4 gap-3 py-3 px-1">
|
|
5060
6232
|
<div class="text-xs text-base-content/40">
|
|
5061
6233
|
Total found: <span class="font-medium text-base-content/60">\${total}</span>
|
|
@@ -5063,7 +6235,7 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5063
6235
|
\${totalPages > 1 ? html\`
|
|
5064
6236
|
<div class="join border border-base-200 rounded-lg">
|
|
5065
6237
|
\${page > 1 ? html\`
|
|
5066
|
-
<button hx-get="${
|
|
6238
|
+
<button hx-get="${e}?page=\${page - 1}&search=\${search}&sort=\${sort}&order=\${order}" hx-target="#main-content" hx-push-url="true" class="join-item btn btn-sm btn-ghost">
|
|
5067
6239
|
<iconify-icon icon="mdi:chevron-left" width="16" height="16"></iconify-icon>
|
|
5068
6240
|
</button>
|
|
5069
6241
|
\` : html\`<button class="join-item btn btn-sm btn-ghost btn-disabled"><iconify-icon icon="mdi:chevron-left" width="16" height="16"></iconify-icon></button>\`}
|
|
@@ -5071,47 +6243,47 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5071
6243
|
<button class="join-item btn btn-sm btn-ghost no-animation pointer-events-none text-xs">\${page} / \${totalPages}</button>
|
|
5072
6244
|
|
|
5073
6245
|
\${page < totalPages ? html\`
|
|
5074
|
-
<button hx-get="${
|
|
6246
|
+
<button hx-get="${e}?page=\${page + 1}&search=\${search}&sort=\${sort}&order=\${order}" hx-target="#main-content" hx-push-url="true" class="join-item btn btn-sm btn-ghost">
|
|
5075
6247
|
<iconify-icon icon="mdi:chevron-right" width="16" height="16"></iconify-icon>
|
|
5076
6248
|
</button>
|
|
5077
6249
|
\` : html\`<button class="join-item btn btn-sm btn-ghost btn-disabled"><iconify-icon icon="mdi:chevron-right" width="16" height="16"></iconify-icon></button>\`}
|
|
5078
6250
|
</div>
|
|
5079
6251
|
\` : ''}
|
|
5080
|
-
</div>`}function
|
|
6252
|
+
</div>`}function M(e,t="Search term or filter..."){return `
|
|
5081
6253
|
<div class="form-control w-full md:w-auto relative">
|
|
5082
6254
|
<iconify-icon icon="mdi:magnify" width="18" height="18" class="absolute left-3 top-1/2 -translate-y-1/2 opacity-40"></iconify-icon>
|
|
5083
6255
|
<input type="text"
|
|
5084
6256
|
name="search"
|
|
5085
|
-
placeholder="${
|
|
6257
|
+
placeholder="${t}"
|
|
5086
6258
|
value="\${search}"
|
|
5087
|
-
hx-get="${
|
|
6259
|
+
hx-get="${e}?sort=\${sort}&order=\${order}"
|
|
5088
6260
|
hx-trigger="keyup changed delay:500ms, search"
|
|
5089
6261
|
hx-target="#main-content"
|
|
5090
6262
|
class="input input-sm md:input-md input-bordered pl-9 w-full md:w-72 bg-base-200/50 border-base-200 focus:bg-base-100 focus:border-primary transition-all text-sm" />
|
|
5091
|
-
</div>`}function
|
|
5092
|
-
<div id="bulk-delete-bar-${
|
|
6263
|
+
</div>`}function bt(e,t,n,r,a,o,i,s,l,u){let c=I(`/admin/table/${e.exportName}`),f=M(`/admin/table/${e.exportName}`,"Search term or filter..."),d=r?`<th class="w-10"><input id="select-all-${e.exportName}" type="checkbox" class="checkbox checkbox-xs" /></th>`:'<th class="w-10"><input type="checkbox" class="checkbox checkbox-xs opacity-30" disabled /></th>',y=r?`<td><input type="checkbox" class="checkbox checkbox-xs row-select-checkbox" value="\${String((row as any).${n} ?? '')}" /></td>`:'<td><input type="checkbox" class="checkbox checkbox-xs opacity-30" disabled /></td>',w=r?`
|
|
6264
|
+
<div id="bulk-delete-bar-${e.exportName}" class="fixed bottom-4 left-1/2 -translate-x-1/2 z-40 hidden">
|
|
5093
6265
|
<div class="bg-base-100 border border-base-200 rounded-xl shadow-lg px-3 py-2 flex items-center gap-3">
|
|
5094
6266
|
<div class="text-xs text-base-content/70">
|
|
5095
|
-
<span id="bulk-selected-count-${
|
|
6267
|
+
<span id="bulk-selected-count-${e.exportName}" class="font-medium text-base-content">0</span> selected
|
|
5096
6268
|
</div>
|
|
5097
6269
|
<label class="label cursor-pointer gap-2 py-0 px-1">
|
|
5098
6270
|
<span class="label-text text-xs">All matching (\${total})</span>
|
|
5099
|
-
<input id="bulk-all-matching-${
|
|
6271
|
+
<input id="bulk-all-matching-${e.exportName}" type="checkbox" class="checkbox checkbox-xs" />
|
|
5100
6272
|
</label>
|
|
5101
|
-
<button id="bulk-delete-trigger-${
|
|
6273
|
+
<button id="bulk-delete-trigger-${e.exportName}" type="button" class="btn btn-error btn-xs gap-1">
|
|
5102
6274
|
<iconify-icon icon="mdi:delete-outline" width="14" height="14"></iconify-icon>
|
|
5103
6275
|
Delete selected
|
|
5104
6276
|
</button>
|
|
5105
6277
|
</div>
|
|
5106
6278
|
</div>
|
|
5107
6279
|
|
|
5108
|
-
<dialog id="bulk-delete-modal-${
|
|
6280
|
+
<dialog id="bulk-delete-modal-${e.exportName}" class="modal">
|
|
5109
6281
|
<div class="modal-box max-w-sm p-6 space-y-4">
|
|
5110
6282
|
<h3 class="font-semibold text-base">Delete selected rows?</h3>
|
|
5111
|
-
<p class="text-sm text-base-content/70" id="bulk-delete-description-${
|
|
5112
|
-
<form id="bulk-delete-form-${
|
|
5113
|
-
<input type="hidden" name="bulkMode" id="bulk-delete-mode-${
|
|
5114
|
-
<input type="hidden" name="selectedIds" id="bulk-delete-ids-${
|
|
6283
|
+
<p class="text-sm text-base-content/70" id="bulk-delete-description-${e.exportName}">This action cannot be undone.</p>
|
|
6284
|
+
<form id="bulk-delete-form-${e.exportName}" hx-post="/admin/table/${e.exportName}/delete-bulk" hx-target="#main-content" hx-swap="outerHTML" class="space-y-3">
|
|
6285
|
+
<input type="hidden" name="bulkMode" id="bulk-delete-mode-${e.exportName}" value="selected" />
|
|
6286
|
+
<input type="hidden" name="selectedIds" id="bulk-delete-ids-${e.exportName}" value="" />
|
|
5115
6287
|
<input type="hidden" name="sort" value="\${sort}" />
|
|
5116
6288
|
<input type="hidden" name="order" value="\${order}" />
|
|
5117
6289
|
<input type="hidden" name="search" value="\${search}" />
|
|
@@ -5133,15 +6305,15 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5133
6305
|
const rowCheckboxes = Array.from(container.querySelectorAll('.row-select-checkbox')).filter((node) => node instanceof HTMLInputElement);
|
|
5134
6306
|
if (rowCheckboxes.length === 0) return;
|
|
5135
6307
|
|
|
5136
|
-
const selectAll = container.querySelector('#select-all-${
|
|
5137
|
-
const bar = container.querySelector('#bulk-delete-bar-${
|
|
5138
|
-
const selectedCount = container.querySelector('#bulk-selected-count-${
|
|
5139
|
-
const allMatching = container.querySelector('#bulk-all-matching-${
|
|
5140
|
-
const trigger = container.querySelector('#bulk-delete-trigger-${
|
|
5141
|
-
const modal = container.querySelector('#bulk-delete-modal-${
|
|
5142
|
-
const modeInput = container.querySelector('#bulk-delete-mode-${
|
|
5143
|
-
const idsInput = container.querySelector('#bulk-delete-ids-${
|
|
5144
|
-
const description = container.querySelector('#bulk-delete-description-${
|
|
6308
|
+
const selectAll = container.querySelector('#select-all-${e.exportName}');
|
|
6309
|
+
const bar = container.querySelector('#bulk-delete-bar-${e.exportName}');
|
|
6310
|
+
const selectedCount = container.querySelector('#bulk-selected-count-${e.exportName}');
|
|
6311
|
+
const allMatching = container.querySelector('#bulk-all-matching-${e.exportName}');
|
|
6312
|
+
const trigger = container.querySelector('#bulk-delete-trigger-${e.exportName}');
|
|
6313
|
+
const modal = container.querySelector('#bulk-delete-modal-${e.exportName}');
|
|
6314
|
+
const modeInput = container.querySelector('#bulk-delete-mode-${e.exportName}');
|
|
6315
|
+
const idsInput = container.querySelector('#bulk-delete-ids-${e.exportName}');
|
|
6316
|
+
const description = container.querySelector('#bulk-delete-description-${e.exportName}');
|
|
5145
6317
|
|
|
5146
6318
|
if (!(selectAll instanceof HTMLInputElement) ||
|
|
5147
6319
|
!(bar instanceof HTMLElement) ||
|
|
@@ -5207,16 +6379,16 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5207
6379
|
})();
|
|
5208
6380
|
</script>
|
|
5209
6381
|
`:"";return `
|
|
5210
|
-
adminApp.get('/table/${
|
|
6382
|
+
adminApp.get('/table/${e.exportName}', async (c) => {
|
|
5211
6383
|
const db = drizzle(c.env[options.databaseBinding], { schema });
|
|
5212
6384
|
const page = parseInt(c.req.query('page') || '1');
|
|
5213
6385
|
const limit = 20;
|
|
5214
6386
|
const offset = (page - 1) * limit;
|
|
5215
|
-
const sort = c.req.query('sort') || '${
|
|
6387
|
+
const sort = c.req.query('sort') || '${t}';
|
|
5216
6388
|
const order = c.req.query('order') || 'desc';
|
|
5217
6389
|
const search = c.req.query('search') || '';
|
|
5218
6390
|
|
|
5219
|
-
let tableSchema = (schema as any).${
|
|
6391
|
+
let tableSchema = (schema as any).${e.exportName};
|
|
5220
6392
|
if (!tableSchema) return c.text("Table missing", 404);
|
|
5221
6393
|
|
|
5222
6394
|
let query = db.select().from(tableSchema);
|
|
@@ -5246,7 +6418,7 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5246
6418
|
<table class="table table-sm md:table-md w-full">
|
|
5247
6419
|
<thead>
|
|
5248
6420
|
<tr class="border-b border-base-200">
|
|
5249
|
-
${
|
|
6421
|
+
${d}
|
|
5250
6422
|
${i}
|
|
5251
6423
|
<th class="w-[100px] text-right">
|
|
5252
6424
|
<iconify-icon icon="mdi:dots-horizontal" width="16" height="16" class="opacity-30"></iconify-icon>
|
|
@@ -5267,7 +6439,7 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5267
6439
|
<div class="flex flex-col items-center gap-3">
|
|
5268
6440
|
<iconify-icon icon="mdi:database-off-outline" width="40" height="40" class="opacity-20"></iconify-icon>
|
|
5269
6441
|
<p class="text-sm text-base-content/40">No records found.</p>
|
|
5270
|
-
<label for="create-drawer-${
|
|
6442
|
+
<label for="create-drawer-${e.exportName}" class="btn btn-sm btn-primary gap-1">
|
|
5271
6443
|
<iconify-icon icon="mdi:plus" width="16" height="16"></iconify-icon>
|
|
5272
6444
|
New record
|
|
5273
6445
|
</label>
|
|
@@ -5278,52 +6450,52 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5278
6450
|
</tbody>
|
|
5279
6451
|
</table>
|
|
5280
6452
|
</div>
|
|
5281
|
-
${
|
|
6453
|
+
${c}
|
|
5282
6454
|
</div>
|
|
5283
6455
|
\`;
|
|
5284
6456
|
|
|
5285
6457
|
const content = html\`
|
|
5286
6458
|
<div id="main-content">
|
|
5287
6459
|
<div class="drawer drawer-end">
|
|
5288
|
-
<input id="create-drawer-${
|
|
6460
|
+
<input id="create-drawer-${e.exportName}" type="checkbox" class="drawer-toggle" />
|
|
5289
6461
|
<div class="drawer-content">
|
|
5290
6462
|
<div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-5 gap-3">
|
|
5291
6463
|
<div class="flex items-center gap-2 text-sm">
|
|
5292
6464
|
<a href="/admin" class="text-base-content/40 hover:text-primary transition-colors">Collections</a>
|
|
5293
6465
|
<iconify-icon icon="mdi:chevron-right" width="14" height="14" class="opacity-30"></iconify-icon>
|
|
5294
|
-
<span class="font-semibold capitalize">${
|
|
6466
|
+
<span class="font-semibold capitalize">${e.tableName}</span>
|
|
5295
6467
|
<button class="btn btn-ghost btn-xs btn-square opacity-40 hover:opacity-100" onclick="window.location.reload()">
|
|
5296
6468
|
<iconify-icon icon="mdi:refresh" width="14" height="14"></iconify-icon>
|
|
5297
6469
|
</button>
|
|
5298
6470
|
</div>
|
|
5299
6471
|
<div class="flex items-center gap-2 w-full md:w-auto">
|
|
5300
|
-
<label for="create-drawer-${
|
|
6472
|
+
<label for="create-drawer-${e.exportName}" class="btn btn-primary btn-sm gap-1">
|
|
5301
6473
|
<iconify-icon icon="mdi:plus" width="16" height="16"></iconify-icon>
|
|
5302
6474
|
New record
|
|
5303
6475
|
</label>
|
|
5304
6476
|
</div>
|
|
5305
6477
|
</div>
|
|
5306
6478
|
<div class="mb-4">
|
|
5307
|
-
${
|
|
6479
|
+
${f}
|
|
5308
6480
|
</div>
|
|
5309
6481
|
\${tableHtml}
|
|
5310
|
-
${
|
|
6482
|
+
${w}
|
|
5311
6483
|
</div>
|
|
5312
6484
|
<div class="drawer-side z-50">
|
|
5313
|
-
<label for="create-drawer-${
|
|
6485
|
+
<label for="create-drawer-${e.exportName}" aria-label="close sidebar" class="drawer-overlay"></label>
|
|
5314
6486
|
<div class="w-full max-w-md min-h-full bg-base-100 p-6 border-l border-base-200 overflow-y-auto shadow-lg">
|
|
5315
6487
|
<div class="flex justify-between items-center mb-5">
|
|
5316
|
-
<h3 class="text-base font-semibold">Create ${
|
|
5317
|
-
<label for="create-drawer-${
|
|
6488
|
+
<h3 class="text-base font-semibold">Create ${e.tableName}</h3>
|
|
6489
|
+
<label for="create-drawer-${e.exportName}" class="btn btn-sm btn-ghost btn-square">
|
|
5318
6490
|
<iconify-icon icon="mdi:close" width="18" height="18"></iconify-icon>
|
|
5319
6491
|
</label>
|
|
5320
6492
|
</div>
|
|
5321
|
-
<form hx-post="/admin/table/${
|
|
6493
|
+
<form hx-post="/admin/table/${e.exportName}/create" hx-target="#main-content" hx-swap="outerHTML" class="flex flex-col gap-4">
|
|
5322
6494
|
<input type="hidden" name="sort" value="\${sort}" />
|
|
5323
6495
|
<input type="hidden" name="order" value="\${order}" />
|
|
5324
6496
|
<input type="hidden" name="search" value="\${search}" />
|
|
5325
6497
|
<input type="hidden" name="page" value="\${page}" />
|
|
5326
|
-
${
|
|
6498
|
+
${u}
|
|
5327
6499
|
<button type="submit" class="btn btn-primary btn-sm mt-2">Create record</button>
|
|
5328
6500
|
</form>
|
|
5329
6501
|
</div>
|
|
@@ -5337,17 +6509,17 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5337
6509
|
}
|
|
5338
6510
|
|
|
5339
6511
|
return c.html(Layout({
|
|
5340
|
-
title: "${
|
|
6512
|
+
title: "${e.tableName} - Admin Dashboard",
|
|
5341
6513
|
children: content
|
|
5342
6514
|
}));
|
|
5343
|
-
});`}function
|
|
6515
|
+
});`}function yt(e,t,n,r,a,o,i,s){let l=r==="number"?`
|
|
5344
6516
|
const parsedId = Number(rawId);
|
|
5345
6517
|
if (Number.isNaN(parsedId)) return c.text('${n} must be a valid number', 400);
|
|
5346
6518
|
idValue = parsedId;
|
|
5347
|
-
`:"",
|
|
5348
|
-
adminApp.post('/table/${
|
|
6519
|
+
`:"",c=a?`
|
|
6520
|
+
adminApp.post('/table/${e}/edit', async (c) => {
|
|
5349
6521
|
const db = drizzle(c.env[options.databaseBinding], { schema });
|
|
5350
|
-
const tableSchema = (schema as any).${
|
|
6522
|
+
const tableSchema = (schema as any).${e};
|
|
5351
6523
|
if (!tableSchema) return c.text('Table missing', 404);
|
|
5352
6524
|
|
|
5353
6525
|
const body = await c.req.parseBody();
|
|
@@ -5372,16 +6544,16 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5372
6544
|
|
|
5373
6545
|
const query = new URLSearchParams({
|
|
5374
6546
|
page: getValue(body.page) || '1',
|
|
5375
|
-
sort: getValue(body.sort) || '${
|
|
6547
|
+
sort: getValue(body.sort) || '${t}',
|
|
5376
6548
|
order: getValue(body.order) || 'desc',
|
|
5377
6549
|
search: getValue(body.search) || '',
|
|
5378
6550
|
});
|
|
5379
|
-
return c.redirect('/admin/table/${
|
|
6551
|
+
return c.redirect('/admin/table/${e}?' + query.toString());
|
|
5380
6552
|
});
|
|
5381
6553
|
|
|
5382
|
-
adminApp.post('/table/${
|
|
6554
|
+
adminApp.post('/table/${e}/delete', async (c) => {
|
|
5383
6555
|
const db = drizzle(c.env[options.databaseBinding], { schema });
|
|
5384
|
-
const tableSchema = (schema as any).${
|
|
6556
|
+
const tableSchema = (schema as any).${e};
|
|
5385
6557
|
if (!tableSchema) return c.text('Table missing', 404);
|
|
5386
6558
|
|
|
5387
6559
|
const body = await c.req.parseBody();
|
|
@@ -5399,16 +6571,16 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5399
6571
|
|
|
5400
6572
|
const query = new URLSearchParams({
|
|
5401
6573
|
page: getValue(body.page) || '1',
|
|
5402
|
-
sort: getValue(body.sort) || '${
|
|
6574
|
+
sort: getValue(body.sort) || '${t}',
|
|
5403
6575
|
order: getValue(body.order) || 'desc',
|
|
5404
6576
|
search: getValue(body.search) || '',
|
|
5405
6577
|
});
|
|
5406
|
-
return c.redirect('/admin/table/${
|
|
6578
|
+
return c.redirect('/admin/table/${e}?' + query.toString());
|
|
5407
6579
|
});
|
|
5408
6580
|
|
|
5409
|
-
adminApp.post('/table/${
|
|
6581
|
+
adminApp.post('/table/${e}/delete-bulk', async (c) => {
|
|
5410
6582
|
const db = drizzle(c.env[options.databaseBinding], { schema });
|
|
5411
|
-
const tableSchema = (schema as any).${
|
|
6583
|
+
const tableSchema = (schema as any).${e};
|
|
5412
6584
|
if (!tableSchema) return c.text('Table missing', 404);
|
|
5413
6585
|
|
|
5414
6586
|
const body = await c.req.parseBody();
|
|
@@ -5445,15 +6617,15 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5445
6617
|
|
|
5446
6618
|
const query = new URLSearchParams({
|
|
5447
6619
|
page: getValue(body.page) || '1',
|
|
5448
|
-
sort: getValue(body.sort) || '${
|
|
6620
|
+
sort: getValue(body.sort) || '${t}',
|
|
5449
6621
|
order: getValue(body.order) || 'desc',
|
|
5450
6622
|
search: getValue(body.search) || '',
|
|
5451
6623
|
});
|
|
5452
|
-
return c.redirect('/admin/table/${
|
|
6624
|
+
return c.redirect('/admin/table/${e}?' + query.toString());
|
|
5453
6625
|
});`:"";return `
|
|
5454
|
-
adminApp.post('/table/${
|
|
6626
|
+
adminApp.post('/table/${e}/create', async (c) => {
|
|
5455
6627
|
const db = drizzle(c.env[options.databaseBinding], { schema });
|
|
5456
|
-
const tableSchema = (schema as any).${
|
|
6628
|
+
const tableSchema = (schema as any).${e};
|
|
5457
6629
|
if (!tableSchema) return c.text('Table missing', 404);
|
|
5458
6630
|
|
|
5459
6631
|
const body = await c.req.parseBody();
|
|
@@ -5466,22 +6638,22 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5466
6638
|
|
|
5467
6639
|
const query = new URLSearchParams({
|
|
5468
6640
|
page: getValue(body.page) || '1',
|
|
5469
|
-
sort: getValue(body.sort) || '${
|
|
6641
|
+
sort: getValue(body.sort) || '${t}',
|
|
5470
6642
|
order: getValue(body.order) || 'desc',
|
|
5471
6643
|
search: getValue(body.search) || '',
|
|
5472
6644
|
});
|
|
5473
|
-
return c.redirect('/admin/table/${
|
|
6645
|
+
return c.redirect('/admin/table/${e}?' + query.toString());
|
|
5474
6646
|
});
|
|
5475
|
-
${
|
|
5476
|
-
`}function
|
|
5477
|
-
`+
|
|
6647
|
+
${c}
|
|
6648
|
+
`}function U(e){let t=mt(e),n=!!t,r=e.columns.map(m=>m.name),a=r.filter(m=>gt(e,m)),o=r.filter(m=>ft(e,m)),i=ut(e),s=dt(e,r),l=pt(r,t),u=a.map(m=>L(e,m,"create")).join(""),c=o.map(m=>L(e,m,"edit")).join(""),f=z(e,a),d=z(e,o),y=n?t:r[0]||"id",w=e.columns.find(m=>m.name===t)?.type,b=ht(e,n,t,c);return bt(e,y,t,n,r,i,s,l,b,u)+`
|
|
6649
|
+
`+yt(e.exportName,y,t,w,n,i,f,d)}function wt(){return `
|
|
5478
6650
|
const buildUsersRedirect = (params: { page?: string; sort?: string; order?: string; search?: string }) => {
|
|
5479
6651
|
const page = params.page && params.page.trim() ? params.page : '1';
|
|
5480
6652
|
const sort = params.sort && params.sort.trim() ? params.sort : 'createdAt';
|
|
5481
6653
|
const order = params.order === 'asc' ? 'asc' : 'desc';
|
|
5482
6654
|
const search = params.search ? params.search : '';
|
|
5483
6655
|
return '/admin/users?page=' + encodeURIComponent(page) + '&sort=' + encodeURIComponent(sort) + '&order=' + encodeURIComponent(order) + '&search=' + encodeURIComponent(search);
|
|
5484
|
-
};`}function
|
|
6656
|
+
};`}function xt(){return `
|
|
5485
6657
|
\${(row as any).id === currentUserId ? '' : html\`
|
|
5486
6658
|
<input type="checkbox" id="ban-user-modal-\${String((row as any).id)}" class="modal-toggle" />
|
|
5487
6659
|
<div class="modal">
|
|
@@ -5502,7 +6674,7 @@ ${d}
|
|
|
5502
6674
|
</div>
|
|
5503
6675
|
<label class="modal-backdrop" for="ban-user-modal-\${String((row as any).id)}">Close</label>
|
|
5504
6676
|
</div>
|
|
5505
|
-
\`}`}function
|
|
6677
|
+
\`}`}function vt(){return `
|
|
5506
6678
|
\${(row as any).id === currentUserId ? '' : html\`
|
|
5507
6679
|
<input type="checkbox" id="delete-user-modal-\${String((row as any).id)}" class="modal-toggle" />
|
|
5508
6680
|
<div class="modal">
|
|
@@ -5523,15 +6695,15 @@ ${d}
|
|
|
5523
6695
|
</div>
|
|
5524
6696
|
<label class="modal-backdrop" for="delete-user-modal-\${String((row as any).id)}">Close</label>
|
|
5525
6697
|
</div>
|
|
5526
|
-
\`}`}var
|
|
5527
|
-
`),
|
|
6698
|
+
\`}`}var er=["id","name","email","role","createdAt","banned"],tr={id:"mdi:pound",name:"mdi:format-text",email:"mdi:at",role:"mdi:shield-account-outline",createdAt:"mdi:calendar",banned:"mdi:toggle-switch-outline"};function nr(e){let t=tr[e]||"mdi:format-text";return `<th><a href="#" hx-get="/admin/users?page=\${page}&search=\${search}&sort=${e}&order=\${sort === '${e}' && order === 'asc' ? 'desc' : 'asc'}" hx-target="#main-content" hx-push-url="true" class="hover:text-primary flex items-center gap-1.5 transition-colors whitespace-nowrap"><iconify-icon icon="${t}" width="14" height="14" class="opacity-40"></iconify-icon>${e} <span class="text-[10px] opacity-30">\${sort === '${e}' ? (order === 'asc' ? '\u25B2' : '\u25BC') : ''}</span></a></th>`}function Tt(){let e=er.map(nr).join(`
|
|
6699
|
+
`),t=I("/admin/users");return `
|
|
5528
6700
|
const tableHtml = html\`
|
|
5529
6701
|
<div class="bg-base-100 rounded-xl border border-base-200 overflow-hidden">
|
|
5530
6702
|
<div class="overflow-x-auto">
|
|
5531
6703
|
<table class="table table-sm md:table-md w-full">
|
|
5532
6704
|
<thead>
|
|
5533
6705
|
<tr class="border-b border-base-200">
|
|
5534
|
-
${
|
|
6706
|
+
${e}
|
|
5535
6707
|
<th class="text-right">
|
|
5536
6708
|
<iconify-icon icon="mdi:dots-horizontal" width="16" height="16" class="opacity-30"></iconify-icon>
|
|
5537
6709
|
</th>
|
|
@@ -5540,7 +6712,7 @@ ${d}
|
|
|
5540
6712
|
<tbody>
|
|
5541
6713
|
\${data.map((row) => html\`
|
|
5542
6714
|
<tr class="hover:bg-base-200/30 transition-colors">
|
|
5543
|
-
<td><
|
|
6715
|
+
<td><button type="button" class="truncate max-w-[220px] text-sm font-mono text-xs opacity-70 hover:opacity-100 cursor-copy text-left" title="Click to copy: \${String((row as any).id ?? '')}" data-copy-value="\${String((row as any).id ?? '')}" onclick="navigator.clipboard?.writeText(this.dataset.copyValue || '')">\${String((row as any).id ?? '')}</button></td>
|
|
5544
6716
|
<td><div class="truncate max-w-[220px] text-sm" title="\${String((row as any).name ?? '')}">\${String((row as any).name ?? '')}</div></td>
|
|
5545
6717
|
<td><div class="truncate max-w-[260px] text-sm" title="\${String((row as any).email ?? '')}">\${String((row as any).email ?? '')}</div></td>
|
|
5546
6718
|
<td><span class="badge badge-sm \${String((row as any).role ?? '') === 'admin' ? 'badge-primary' : 'badge-ghost'}">\${String((row as any).role ?? '')}</span></td>
|
|
@@ -5592,8 +6764,8 @@ ${d}
|
|
|
5592
6764
|
</div>
|
|
5593
6765
|
</div>
|
|
5594
6766
|
</div>
|
|
5595
|
-
${
|
|
5596
|
-
${
|
|
6767
|
+
${xt()}
|
|
6768
|
+
${vt()}
|
|
5597
6769
|
</td>
|
|
5598
6770
|
</tr>
|
|
5599
6771
|
\`)}
|
|
@@ -5606,9 +6778,10 @@ ${be()}
|
|
|
5606
6778
|
</tbody>
|
|
5607
6779
|
</table>
|
|
5608
6780
|
</div>
|
|
5609
|
-
${
|
|
6781
|
+
${t}
|
|
5610
6782
|
</div>
|
|
5611
|
-
|
|
6783
|
+
\`;
|
|
6784
|
+
`}function Rt(){return `
|
|
5612
6785
|
const content = html\`
|
|
5613
6786
|
<div id="main-content">
|
|
5614
6787
|
<div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-5 gap-3">
|
|
@@ -5620,11 +6793,11 @@ ${be()}
|
|
|
5620
6793
|
<iconify-icon icon="mdi:refresh" width="14" height="14"></iconify-icon>
|
|
5621
6794
|
</button>
|
|
5622
6795
|
</div>
|
|
5623
|
-
${
|
|
6796
|
+
${M("/admin/users","Search users...")}
|
|
5624
6797
|
</div>
|
|
5625
6798
|
\${tableHtml}
|
|
5626
6799
|
</div>
|
|
5627
|
-
\`;`}function
|
|
6800
|
+
\`;`}function kt(){let e=Tt(),t=Rt();return `
|
|
5628
6801
|
adminApp.get('/users', async (c) => {
|
|
5629
6802
|
const db = drizzle(c.env[options.databaseBinding]);
|
|
5630
6803
|
const auth = createAuth({ DATABASE: c.env[options.databaseBinding] } as any, c.req.raw.cf as any);
|
|
@@ -5668,10 +6841,10 @@ ${be()}
|
|
|
5668
6841
|
const total = Number(totalResult[0]?.count || 0);
|
|
5669
6842
|
const totalPages = Math.ceil(total / limit);
|
|
5670
6843
|
|
|
5671
|
-
${t}
|
|
5672
|
-
|
|
5673
6844
|
${e}
|
|
5674
6845
|
|
|
6846
|
+
${t}
|
|
6847
|
+
|
|
5675
6848
|
if (c.req.header('hx-request')) {
|
|
5676
6849
|
return c.html(content);
|
|
5677
6850
|
}
|
|
@@ -5680,7 +6853,7 @@ ${be()}
|
|
|
5680
6853
|
title: "users - Admin Dashboard",
|
|
5681
6854
|
children: content,
|
|
5682
6855
|
}));
|
|
5683
|
-
});`}function
|
|
6856
|
+
});`}function St(){return `
|
|
5684
6857
|
adminApp.post('/users/edit', async (c) => {
|
|
5685
6858
|
const session = await requireAdminSession(c);
|
|
5686
6859
|
if (!session) {
|
|
@@ -5823,8 +6996,8 @@ ${be()}
|
|
|
5823
6996
|
const resolvedPage = String(Math.min(nextPageCandidate, totalPages));
|
|
5824
6997
|
|
|
5825
6998
|
return c.redirect(buildUsersRedirect({ page: resolvedPage, search, sort, order }));
|
|
5826
|
-
});`}function
|
|
5827
|
-
${
|
|
6999
|
+
});`}function Q(){return `
|
|
7000
|
+
${wt()}
|
|
5828
7001
|
|
|
5829
7002
|
const requireAdminSession = async (c: any) => {
|
|
5830
7003
|
const auth = createAuth({ DATABASE: c.env[options.databaseBinding] } as any, c.req.raw.cf as any);
|
|
@@ -5835,29 +7008,29 @@ ${be()}
|
|
|
5835
7008
|
return session;
|
|
5836
7009
|
};
|
|
5837
7010
|
|
|
5838
|
-
${
|
|
7011
|
+
${kt()}
|
|
5839
7012
|
|
|
5840
|
-
${
|
|
5841
|
-
`}function
|
|
7013
|
+
${St()}
|
|
7014
|
+
`}function At(e){return `${e.tables.map(t=>U(t)).join(`
|
|
5842
7015
|
`)}
|
|
5843
|
-
${
|
|
7016
|
+
${Q()}`}function Nt(e){return `
|
|
5844
7017
|
<div class="flex items-center justify-between">
|
|
5845
7018
|
<div class="flex items-center gap-3">
|
|
5846
7019
|
<div class="w-10 h-10 rounded-xl bg-primary/10 flex items-center justify-center">
|
|
5847
|
-
<iconify-icon icon="${
|
|
7020
|
+
<iconify-icon icon="${e.kind==="query"?"solar:reorder-bold-duotone":"solar:bolt-bold-duotone"}" width="24" height="24" class="text-primary"></iconify-icon>
|
|
5848
7021
|
</div>
|
|
5849
7022
|
<div>
|
|
5850
|
-
<h1 class="text-xl font-bold tracking-tight">${
|
|
5851
|
-
<p class="text-xs opacity-50 font-medium uppercase tracking-wider">${
|
|
7023
|
+
<h1 class="text-xl font-bold tracking-tight">${e.exportName}</h1>
|
|
7024
|
+
<p class="text-xs opacity-50 font-medium uppercase tracking-wider">${e.kind}</p>
|
|
5852
7025
|
</div>
|
|
5853
7026
|
</div>
|
|
5854
7027
|
<div class="flex items-center gap-2">
|
|
5855
|
-
<span class="badge badge-sm badge-ghost font-mono opacity-50 px-2 py-3">/api${
|
|
7028
|
+
<span class="badge badge-sm badge-ghost font-mono opacity-50 px-2 py-3">/api${e.routePath}</span>
|
|
5856
7029
|
</div>
|
|
5857
7030
|
</div>
|
|
5858
|
-
`}function
|
|
5859
|
-
<div class="text-[11px] opacity-30 italic py-2">No arguments defined for this ${
|
|
5860
|
-
`:
|
|
7031
|
+
`}function rr(e){return e==="boolean"?"checkbox":e==="number"?"number":"text"}function ar(e){let t=e.args??[];return t.length===0?`
|
|
7032
|
+
<div class="text-[11px] opacity-30 italic py-2">No arguments defined for this ${e.kind}.</div>
|
|
7033
|
+
`:t.map(n=>{let r=rr(n.type),a=r==="checkbox",o=`${n.name}${n.optional?"":" *"}`,i=n.type!=="unknown"?`<span class="badge badge-xs badge-ghost font-mono opacity-40 ml-1">${n.type}</span>`:"";return a?`
|
|
5861
7034
|
<div class="flex items-center gap-3 py-1">
|
|
5862
7035
|
<input
|
|
5863
7036
|
type="checkbox"
|
|
@@ -5886,12 +7059,12 @@ ${W()}`}function Te(t){return `
|
|
|
5886
7059
|
/>
|
|
5887
7060
|
</div>
|
|
5888
7061
|
`}).join(`
|
|
5889
|
-
`)}function
|
|
7062
|
+
`)}function or(e){return `
|
|
5890
7063
|
<div class="space-y-4">
|
|
5891
7064
|
<div class="flex items-center justify-between">
|
|
5892
7065
|
<div class="flex flex-col">
|
|
5893
7066
|
<span class="text-[11px] font-bold uppercase tracking-wider opacity-40">Arguments</span>
|
|
5894
|
-
<span class="text-[10px] font-mono opacity-30">${
|
|
7067
|
+
<span class="text-[10px] font-mono opacity-30">${e.kind}</span>
|
|
5895
7068
|
</div>
|
|
5896
7069
|
<label class="flex items-center gap-2 cursor-pointer select-none group" title="Enable realtime updates via WebSocket">
|
|
5897
7070
|
<span class="text-[10px] font-bold uppercase tracking-wider opacity-40 group-hover:opacity-70 transition-opacity">Realtime</span>
|
|
@@ -5899,11 +7072,11 @@ ${W()}`}function Te(t){return `
|
|
|
5899
7072
|
</label>
|
|
5900
7073
|
</div>
|
|
5901
7074
|
<div id="args-rows" class="flex flex-col gap-3">
|
|
5902
|
-
${
|
|
7075
|
+
${ar(e)}
|
|
5903
7076
|
</div>
|
|
5904
|
-
<p class="text-[11px] opacity-30 mt-2 italic">Values are sent as ${
|
|
7077
|
+
<p class="text-[11px] opacity-30 mt-2 italic">Values are sent as ${e.kind==="query"?"query string params":"JSON request body"}.</p>
|
|
5905
7078
|
</div>
|
|
5906
|
-
`}function
|
|
7079
|
+
`}function ir(){return `
|
|
5907
7080
|
<div class="space-y-4">
|
|
5908
7081
|
<label class="text-[11px] font-bold uppercase tracking-wider opacity-40 block">Bearer Token <span class="font-normal normal-case">(optional)</span></label>
|
|
5909
7082
|
<div class="relative group">
|
|
@@ -5920,7 +7093,7 @@ ${W()}`}function Te(t){return `
|
|
|
5920
7093
|
</div>
|
|
5921
7094
|
<p class="text-[10px] opacity-30 italic">Token will be included in the Authorization header.</p>
|
|
5922
7095
|
</div>
|
|
5923
|
-
`}function
|
|
7096
|
+
`}function sr(){return `
|
|
5924
7097
|
<div class="space-y-4">
|
|
5925
7098
|
<div class="flex items-center justify-between">
|
|
5926
7099
|
<span class="text-[11px] font-bold uppercase tracking-wider opacity-40">Custom Headers</span>
|
|
@@ -5934,7 +7107,7 @@ ${W()}`}function Te(t){return `
|
|
|
5934
7107
|
</div>
|
|
5935
7108
|
<p id="headers-error" class="text-[11px] text-error mt-1.5 hidden"></p>
|
|
5936
7109
|
</div>
|
|
5937
|
-
`}function
|
|
7110
|
+
`}function $t(e){return `
|
|
5938
7111
|
<div class="card bg-base-100 border border-base-200 shadow-sm overflow-hidden flex flex-col h-full">
|
|
5939
7112
|
<div class="px-5 py-3 border-b border-base-200 bg-base-200/20 flex items-center justify-between flex-none">
|
|
5940
7113
|
<h3 class="text-xs font-bold uppercase tracking-widest opacity-40">Request</h3>
|
|
@@ -5955,13 +7128,13 @@ ${W()}`}function Te(t){return `
|
|
|
5955
7128
|
<!-- Tab Content -->
|
|
5956
7129
|
<div class="flex-1 overflow-y-auto">
|
|
5957
7130
|
<div id="request-tab-args" class="p-5">
|
|
5958
|
-
${
|
|
7131
|
+
${or(e)}
|
|
5959
7132
|
</div>
|
|
5960
7133
|
<div id="request-tab-auth" class="p-5 hidden">
|
|
5961
|
-
${
|
|
7134
|
+
${ir()}
|
|
5962
7135
|
</div>
|
|
5963
7136
|
<div id="request-tab-headers" class="p-5 hidden">
|
|
5964
|
-
${
|
|
7137
|
+
${sr()}
|
|
5965
7138
|
</div>
|
|
5966
7139
|
</div>
|
|
5967
7140
|
|
|
@@ -5973,13 +7146,13 @@ ${W()}`}function Te(t){return `
|
|
|
5973
7146
|
class="btn btn-primary w-full gap-2 rounded-xl shadow-lg shadow-primary/20 hover:shadow-xl hover:shadow-primary/30 transition-all font-semibold"
|
|
5974
7147
|
>
|
|
5975
7148
|
<iconify-icon icon="solar:play-bold" width="18" height="18"></iconify-icon>
|
|
5976
|
-
Run ${
|
|
7149
|
+
Run ${e.kind}
|
|
5977
7150
|
</button>
|
|
5978
7151
|
</div>
|
|
5979
7152
|
</form>
|
|
5980
7153
|
</div>
|
|
5981
7154
|
</div>
|
|
5982
|
-
`}function
|
|
7155
|
+
`}function qt(){return `
|
|
5983
7156
|
<div class="card bg-base-100 border border-base-200 shadow-sm overflow-hidden flex flex-col">
|
|
5984
7157
|
<!-- Panel Header -->
|
|
5985
7158
|
<div class="px-5 py-3 border-b border-base-200 bg-base-200/20 flex items-center justify-between">
|
|
@@ -6061,7 +7234,7 @@ ${W()}`}function Te(t){return `
|
|
|
6061
7234
|
|
|
6062
7235
|
</div>
|
|
6063
7236
|
</div>
|
|
6064
|
-
`}function
|
|
7237
|
+
`}function It(e){let t=e.kind==="query",n=e.routePath,r=e.handlerName??e.routePath;return `
|
|
6065
7238
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css">
|
|
6066
7239
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
|
|
6067
7240
|
|
|
@@ -6287,7 +7460,7 @@ ${W()}`}function Te(t){return `
|
|
|
6287
7460
|
if (indicator) indicator.classList.remove('opacity-0');
|
|
6288
7461
|
showBodyLoading();
|
|
6289
7462
|
|
|
6290
|
-
var isQuery = ${
|
|
7463
|
+
var isQuery = ${t};
|
|
6291
7464
|
var method = isQuery ? 'GET' : 'POST';
|
|
6292
7465
|
var pathWithQuery = '${n}';
|
|
6293
7466
|
|
|
@@ -6359,7 +7532,7 @@ ${W()}`}function Te(t){return `
|
|
|
6359
7532
|
var _rtToken = null;
|
|
6360
7533
|
var _rtEnabled = false;
|
|
6361
7534
|
var _rtEventCount = 0;
|
|
6362
|
-
var _isRealtimeSupported = ${
|
|
7535
|
+
var _isRealtimeSupported = ${t};
|
|
6363
7536
|
var _realtimeQueryName = '${r}';
|
|
6364
7537
|
var _rtPingInterval = null;
|
|
6365
7538
|
|
|
@@ -6603,21 +7776,21 @@ ${W()}`}function Te(t){return `
|
|
|
6603
7776
|
_rtEnabled = false;
|
|
6604
7777
|
});
|
|
6605
7778
|
</script>
|
|
6606
|
-
`}function
|
|
7779
|
+
`}function Mt(e){return `
|
|
6607
7780
|
const content = html\`
|
|
6608
7781
|
<div class="flex flex-col gap-6 max-w-5xl mx-auto" id="main-content">
|
|
6609
|
-
${
|
|
7782
|
+
${Nt(e)}
|
|
6610
7783
|
|
|
6611
7784
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
6612
7785
|
<!-- Request Panel -->
|
|
6613
|
-
${
|
|
7786
|
+
${$t(e)}
|
|
6614
7787
|
|
|
6615
7788
|
<!-- Result Panel -->
|
|
6616
|
-
${
|
|
7789
|
+
${qt()}
|
|
6617
7790
|
</div>
|
|
6618
7791
|
</div>
|
|
6619
7792
|
|
|
6620
|
-
${
|
|
7793
|
+
${It(e)}
|
|
6621
7794
|
\`;
|
|
6622
7795
|
|
|
6623
7796
|
if (c.req.header('hx-request')) {
|
|
@@ -6625,13 +7798,13 @@ ${W()}`}function Te(t){return `
|
|
|
6625
7798
|
}
|
|
6626
7799
|
|
|
6627
7800
|
return c.html(Layout({
|
|
6628
|
-
title: "${
|
|
7801
|
+
title: "${e.exportName} - Functions",
|
|
6629
7802
|
children: content
|
|
6630
|
-
}));`}function
|
|
7803
|
+
}));`}function Ct(e){return e.map(n=>n.kind!=="query"&&n.kind!=="mutation"?"":`
|
|
6631
7804
|
adminApp.get('/functions${n.routePath}', (c) => {
|
|
6632
|
-
${
|
|
7805
|
+
${Mt(n)}
|
|
6633
7806
|
});`).join(`
|
|
6634
|
-
`)}function
|
|
7807
|
+
`)}function Pt(){return `
|
|
6635
7808
|
const getStorageBucket = (c: any): R2Bucket | null => {
|
|
6636
7809
|
const r2Binding = (options as any).r2Binding;
|
|
6637
7810
|
if (!r2Binding || !c.env[r2Binding]) return null;
|
|
@@ -6700,7 +7873,7 @@ ${W()}`}function Te(t){return `
|
|
|
6700
7873
|
const parts = prefix.split('/').filter(Boolean);
|
|
6701
7874
|
return parts.slice(0, -1).join('/') + (parts.length > 1 ? '/' : '');
|
|
6702
7875
|
};
|
|
6703
|
-
`}function
|
|
7876
|
+
`}function Dt(){return `
|
|
6704
7877
|
const buildStorageListingContent = (listed: any, prefix: string) => {
|
|
6705
7878
|
const parts = prefix.split('/').filter(Boolean);
|
|
6706
7879
|
const breadcrumbs = [];
|
|
@@ -6827,7 +8000,7 @@ ${W()}`}function Te(t){return `
|
|
|
6827
8000
|
</div>
|
|
6828
8001
|
\`;
|
|
6829
8002
|
};
|
|
6830
|
-
`}function
|
|
8003
|
+
`}function Ft(){return `
|
|
6831
8004
|
const handleStorageListRoute = async (c: any) => {
|
|
6832
8005
|
const bucket = getStorageBucket(c);
|
|
6833
8006
|
if (!bucket) {
|
|
@@ -6849,7 +8022,7 @@ ${W()}`}function Te(t){return `
|
|
|
6849
8022
|
|
|
6850
8023
|
adminApp.get('/storage', handleStorageListRoute);
|
|
6851
8024
|
adminApp.get('/storage/*', handleStorageListRoute);
|
|
6852
|
-
`}function
|
|
8025
|
+
`}function Et(){return `
|
|
6853
8026
|
adminApp.post('/storage/upload', async (c) => {
|
|
6854
8027
|
const bucket = getStorageBucket(c);
|
|
6855
8028
|
if (!bucket) return c.text("Storage not configured", 400);
|
|
@@ -6867,7 +8040,7 @@ ${W()}`}function Te(t){return `
|
|
|
6867
8040
|
|
|
6868
8041
|
return c.redirect(prefixToStoragePath(prefix));
|
|
6869
8042
|
});
|
|
6870
|
-
`}function
|
|
8043
|
+
`}function Ot(){return `
|
|
6871
8044
|
adminApp.delete('/storage/delete', async (c) => {
|
|
6872
8045
|
const bucket = getStorageBucket(c);
|
|
6873
8046
|
if (!bucket) return c.text("Storage not configured", 400);
|
|
@@ -6882,7 +8055,7 @@ ${W()}`}function Te(t){return `
|
|
|
6882
8055
|
c.header('HX-Redirect', prefixToStoragePath(prefix));
|
|
6883
8056
|
return c.html('');
|
|
6884
8057
|
});
|
|
6885
|
-
`}function
|
|
8058
|
+
`}function jt(){return `
|
|
6886
8059
|
adminApp.post('/storage/directory', async (c) => {
|
|
6887
8060
|
const bucket = getStorageBucket(c);
|
|
6888
8061
|
if (!bucket) return c.text("Storage not configured", 400);
|
|
@@ -6908,7 +8081,7 @@ ${W()}`}function Te(t){return `
|
|
|
6908
8081
|
|
|
6909
8082
|
return c.redirect(prefixToStoragePath(prefix));
|
|
6910
8083
|
});
|
|
6911
|
-
`}function
|
|
8084
|
+
`}function Vt(){return `
|
|
6912
8085
|
adminApp.get('/storage/download', async (c) => {
|
|
6913
8086
|
const bucket = getStorageBucket(c);
|
|
6914
8087
|
if (!bucket) return c.text("Storage not configured", 400);
|
|
@@ -6928,7 +8101,7 @@ ${W()}`}function Te(t){return `
|
|
|
6928
8101
|
|
|
6929
8102
|
return new Response(object.body, { headers });
|
|
6930
8103
|
});
|
|
6931
|
-
`}function
|
|
8104
|
+
`}function Bt(){return `
|
|
6932
8105
|
adminApp.get('/storage/preview', async (c) => {
|
|
6933
8106
|
const bucket = getStorageBucket(c);
|
|
6934
8107
|
if (!bucket) return c.text("Storage not configured", 400);
|
|
@@ -6946,25 +8119,25 @@ ${W()}`}function Te(t){return `
|
|
|
6946
8119
|
|
|
6947
8120
|
return new Response(object.body, { headers });
|
|
6948
8121
|
});
|
|
6949
|
-
`}function
|
|
6950
|
-
${
|
|
8122
|
+
`}function Ht(){return `
|
|
8123
|
+
${Vt()}
|
|
6951
8124
|
|
|
6952
|
-
${
|
|
8125
|
+
${Bt()}
|
|
6953
8126
|
|
|
6954
|
-
${
|
|
8127
|
+
${Et()}
|
|
6955
8128
|
|
|
6956
|
-
${
|
|
8129
|
+
${Ot()}
|
|
6957
8130
|
|
|
6958
|
-
${
|
|
8131
|
+
${jt()}
|
|
6959
8132
|
|
|
6960
|
-
${
|
|
6961
|
-
`}function
|
|
6962
|
-
${
|
|
8133
|
+
${Ft()}
|
|
8134
|
+
`}function Wt(){return `
|
|
8135
|
+
${Pt()}
|
|
6963
8136
|
|
|
6964
|
-
${
|
|
8137
|
+
${Dt()}
|
|
6965
8138
|
|
|
6966
|
-
${
|
|
6967
|
-
`}function
|
|
8139
|
+
${Ht()}
|
|
8140
|
+
`}function Lt(e,t){let n=lt(t);return `
|
|
6968
8141
|
function Layout(props: { children: any; title: string; hideSidebar?: boolean }) {
|
|
6969
8142
|
return html\`<!DOCTYPE html>
|
|
6970
8143
|
<html lang="en" data-theme="light">
|
|
@@ -7154,7 +8327,7 @@ function Layout(props: { children: any; title: string; hideSidebar?: boolean })
|
|
|
7154
8327
|
</div>
|
|
7155
8328
|
<nav class="flex-1 overflow-y-auto px-2 pb-4">
|
|
7156
8329
|
<ul class="flex flex-col gap-0.5" id="table-list">
|
|
7157
|
-
${
|
|
8330
|
+
${e}
|
|
7158
8331
|
</ul>
|
|
7159
8332
|
</nav>
|
|
7160
8333
|
</div>
|
|
@@ -7339,7 +8512,7 @@ function Layout(props: { children: any; title: string; hideSidebar?: boolean })
|
|
|
7339
8512
|
</body>
|
|
7340
8513
|
</html>\`;
|
|
7341
8514
|
}
|
|
7342
|
-
`}function
|
|
8515
|
+
`}function zt(){return `
|
|
7343
8516
|
// Auth Middleware
|
|
7344
8517
|
adminApp.use('*', async (c, next) => {
|
|
7345
8518
|
const auth = createAuth({ DATABASE: c.env[options.databaseBinding] } as any, c.req.raw.cf as any);
|
|
@@ -7398,7 +8571,7 @@ function Layout(props: { children: any; title: string; hideSidebar?: boolean })
|
|
|
7398
8571
|
}
|
|
7399
8572
|
await next();
|
|
7400
8573
|
});
|
|
7401
|
-
`}function
|
|
8574
|
+
`}function Ut(e){return `
|
|
7402
8575
|
adminApp.get('/', (c) => {
|
|
7403
8576
|
return c.html(Layout({
|
|
7404
8577
|
title: "Admin Dashboard",
|
|
@@ -7409,28 +8582,28 @@ function Layout(props: { children: any; title: string; hideSidebar?: boolean })
|
|
|
7409
8582
|
<p class="text-base-content/50 text-sm">Select a collection to view and manage its data.</p>
|
|
7410
8583
|
</div>
|
|
7411
8584
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
7412
|
-
${
|
|
8585
|
+
${e}
|
|
7413
8586
|
</div>
|
|
7414
8587
|
</div>
|
|
7415
8588
|
\`
|
|
7416
8589
|
}));
|
|
7417
8590
|
});
|
|
7418
|
-
`}function
|
|
8591
|
+
`}function Qt(e,t,n){let r=it(t),a=st(r),o=ct(r),i=At(t),s=Ct(n),l=Wt(),u=Lt(a,n),c=zt(),f=Ut(o);return `import { Hono } from "hono";
|
|
7419
8592
|
import { html, raw } from "hono/html";
|
|
7420
8593
|
import { drizzle } from "drizzle-orm/d1";
|
|
7421
8594
|
import { eq, desc, asc, sql, like, or, inArray } from "drizzle-orm";
|
|
7422
8595
|
import { createAuth } from "./auth.config";
|
|
7423
|
-
import * as schema from "${
|
|
8596
|
+
import * as schema from "${e}";
|
|
7424
8597
|
import { users } from "./auth.schema";
|
|
7425
8598
|
|
|
7426
|
-
${
|
|
8599
|
+
${u}
|
|
7427
8600
|
|
|
7428
8601
|
export function registerAdminDashboard(app: Hono<any>, options: { databaseBinding: string, r2Binding?: string }) {
|
|
7429
8602
|
const adminApp = new Hono<any>();
|
|
7430
8603
|
|
|
7431
|
-
${
|
|
8604
|
+
${c}
|
|
7432
8605
|
|
|
7433
|
-
${
|
|
8606
|
+
${f}
|
|
7434
8607
|
|
|
7435
8608
|
// Generate table routes
|
|
7436
8609
|
${i}
|
|
@@ -7444,30 +8617,69 @@ ${g}
|
|
|
7444
8617
|
app.route('/admin', adminApp);
|
|
7445
8618
|
app.get('/admin/', (c) => c.redirect('/admin'));
|
|
7446
8619
|
}
|
|
7447
|
-
`}function
|
|
7448
|
-
`}function
|
|
7449
|
-
|
|
8620
|
+
`}function _(e){if(typeof e!="object"||e===null)return false;let t=e;return t.kind==="schema"&&typeof t.tables=="object"}function C(e){return e.replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/[\s-]+/g,"_").toLowerCase()}function D(e){return e.replace(/[_-]+/g," ").replace(/\s+(.)/g,(t,n)=>n.toUpperCase()).replace(/\s/g,"").replace(/^(.)/,(t,n)=>n.toUpperCase())}function J(e){return e.endsWith("ies")?`${e.slice(0,-3)}y`:e.endsWith("ses")?e.slice(0,-2):e.endsWith("s")&&e.length>1?e.slice(0,-1):e}function h(e){return JSON.stringify(e)}function cr(e){if(typeof e=="string")return h(e);if(typeof e=="number"||typeof e=="boolean")return String(e);if(e===null)return "null";if(e instanceof Date)return h(e.toISOString());throw new Error(`Unsupported SQL default value '${String(e)}'. Use string, number, boolean, null, or Date.`)}function ur(e){return {kind:"schema",tables:Object.fromEntries(Object.entries(e.tables).map(([t,n])=>[t,{kind:"table",sqlName:n.sqlName,columns:Object.fromEntries(Object.entries(n.columns).map(([r,a])=>[r,{...a}])),relations:Object.fromEntries(Object.entries(n.relations).map(([r,a])=>[r,{...a}]))}]))}}function P(e,t,n){let r=e.tables[t];return r?r.columns[n]?.type:void 0}function _t(e,t,n,r,a,o,i){let s=t.columns[n];if(s){if(s.references&&(s.references.table!==r||s.references.column!==a))throw new Error(`Inferred relation '${e}.${n}' conflicts with explicit references(${s.references.table}.${s.references.column}).`);t.columns[n]={...s,notNull:s.notNull??(s.nullable===true?false:o.notNull),nullable:s.nullable??(o.notNull===false?true:void 0),references:{table:r,column:a,onDelete:s.references?.onDelete??o.onDelete,onUpdate:s.references?.onUpdate??o.onUpdate}};return}t.columns[n]={kind:"column",type:o.fkType??i,sqlName:o.sqlName,notNull:o.notNull??true,nullable:o.notNull===false?true:void 0,references:{table:r,column:a,onDelete:o.onDelete,onUpdate:o.onUpdate}};}function Kt(e,t,n){if(t.notNull===true&&t.nullable===true)throw new Error(`Invalid nullable configuration on '${e}': cannot set both notNull and nullable to true.`);return t.notNull===true?true:t.nullable===true||t.notNull===false?false:n}function Gt(e,t){return `${e}:${t}`}function dr(e,t,n,r){let a=Gt(e,t),o=Gt(n,r);return a<=o?{key:`${a}|${o}`,leftTable:e,leftReferenceField:t,rightTable:n,rightReferenceField:r,sourceIsLeft:true}:{key:`${o}|${a}`,leftTable:n,leftReferenceField:r,rightTable:e,rightReferenceField:t,sourceIsLeft:false}}function pr(e,t){return `${e}${D(t)}Links`}function Jt(e,t,n){let r=J(e),a=J(t);return r===a?`${n}${D(r)}Id`:`${r}Id`}function mr(e,t,n){if(e.junctionTable!==t.junctionTable)throw new Error(`manyToMany pair '${n}' has conflicting junctionTable values ('${e.junctionTable}' vs '${t.junctionTable}').`);if(e.leftField!==t.leftField)throw new Error(`manyToMany pair '${n}' has conflicting left field values ('${e.leftField}' vs '${t.leftField}').`);if(e.rightField!==t.rightField)throw new Error(`manyToMany pair '${n}' has conflicting right field values ('${e.rightField}' vs '${t.rightField}').`);if(e.leftSqlName!==t.leftSqlName)throw new Error(`manyToMany pair '${n}' has conflicting left sql name values ('${e.leftSqlName}' vs '${t.leftSqlName}').`);if(e.rightSqlName!==t.rightSqlName)throw new Error(`manyToMany pair '${n}' has conflicting right sql name values ('${e.rightSqlName}' vs '${t.rightSqlName}').`);if(e.onDelete!==t.onDelete)throw new Error(`manyToMany pair '${n}' has conflicting onDelete values ('${e.onDelete}' vs '${t.onDelete}').`);if(e.onUpdate!==t.onUpdate)throw new Error(`manyToMany pair '${n}' has conflicting onUpdate values ('${e.onUpdate}' vs '${t.onUpdate}').`);return e}function gr(e){let t=new Map;for(let[n,r]of Object.entries(e.tables))for(let a of Object.values(r.relations)){if(a.relation!=="manyToMany")continue;let o=a.referenceField??"id",i=a.targetReferenceField??"id",s=dr(n,o,a.targetTable,i),l=Jt(s.leftTable,s.rightTable,"source"),u=Jt(s.rightTable,s.leftTable,"target"),c={leftTable:s.leftTable,leftReferenceField:s.leftReferenceField,rightTable:s.rightTable,rightReferenceField:s.rightReferenceField,junctionTable:a.junctionTable??pr(s.leftTable,s.rightTable),leftField:s.sourceIsLeft?a.sourceField??l:a.targetField??l,rightField:s.sourceIsLeft?a.targetField??u:a.sourceField??u,leftSqlName:s.sourceIsLeft?a.sourceSqlName:a.targetSqlName,rightSqlName:s.sourceIsLeft?a.targetSqlName:a.sourceSqlName,onDelete:a.onDelete,onUpdate:a.onUpdate};if(c.leftField===c.rightField)throw new Error(`manyToMany pair '${s.key}' resolves to duplicate junction fields '${c.leftField}'. Set sourceField/targetField explicitly.`);let f=t.get(s.key);f?mr(f,c,s.key):t.set(s.key,c),a.referenceField=o,a.targetReferenceField=i,a.junctionTable=c.junctionTable,a.sourceField=s.sourceIsLeft?c.leftField:c.rightField,a.targetField=s.sourceIsLeft?c.rightField:c.leftField,a.sourceSqlName=s.sourceIsLeft?c.leftSqlName:c.rightSqlName,a.targetSqlName=s.sourceIsLeft?c.rightSqlName:c.leftSqlName;}for(let n of t.values()){if(n.junctionTable in e.tables)throw new Error(`manyToMany auto junction table '${n.junctionTable}' conflicts with an existing table. Set a different junctionTable name.`);let r=P(e,n.leftTable,n.leftReferenceField)??"string",a=P(e,n.rightTable,n.rightReferenceField)??"string";e.tables[n.junctionTable]={kind:"table",columns:{[n.leftField]:{kind:"column",type:r,sqlName:n.leftSqlName,notNull:true,nullable:false,references:{table:n.leftTable,column:n.leftReferenceField,onDelete:n.onDelete,onUpdate:n.onUpdate},index:true},[n.rightField]:{kind:"column",type:a,sqlName:n.rightSqlName,notNull:true,nullable:false,references:{table:n.rightTable,column:n.rightReferenceField,onDelete:n.onDelete,onUpdate:n.onUpdate},index:true}},relations:{[n.leftTable]:{kind:"relation",relation:"one",targetTable:n.leftTable,field:n.leftField,referenceField:n.leftReferenceField},[n.rightTable]:{kind:"relation",relation:"one",targetTable:n.rightTable,field:n.rightField,referenceField:n.rightReferenceField}}};}}function fr(e){for(let[t,n]of Object.entries(e.tables)){for(let[r,a]of Object.entries(n.columns))if(a.notNull===true&&a.nullable===true)throw new Error(`Invalid nullable configuration on '${t}.${r}': cannot set both notNull and nullable to true.`);for(let[r,a]of Object.entries(n.relations))if(a.relation!=="manyToMany"&&a.notNull===true&&a.nullable===true)throw new Error(`Invalid nullable configuration on '${t}.${r}': cannot set both notNull and nullable to true.`)}}function hr(e){fr(e);let t=ur(e);for(let[n,r]of Object.entries(t.tables))for(let[a,o]of Object.entries(r.relations)){if(o.relation!=="one")continue;let i=o.referenceField??"id",s=o.field??`${a}Id`;o.field=s;let l=P(t,o.targetTable,i)??o.fkType??"string";_t(n,r,s,o.targetTable,i,{fkType:o.fkType,sqlName:o.sqlName,notNull:Kt(`${n}.${a}`,o,true),onDelete:o.onDelete,onUpdate:o.onUpdate},l);}for(let[n,r]of Object.entries(t.tables))for(let a of Object.values(r.relations)){if(a.relation!=="many")continue;let o=t.tables[a.targetTable];if(!o)continue;let i=a.referenceField??"id",s=a.field??`${J(n)}Id`;a.field=s;let l=P(t,n,i)??a.fkType??"string";_t(a.targetTable,o,s,n,i,{fkType:a.fkType,sqlName:a.sqlName,notNull:Kt(`${n}.${a.targetTable}`,a,true),onDelete:a.onDelete,onUpdate:a.onUpdate},l);}return gr(t),t}function Yt(e){return e.primaryKey===true||e.notNull!==true||e.autoIncrement===true||e.sqlDefault!==void 0||e.runtimeDefaultFn!==void 0}function $(e){return e.notNull!==true}function br(e,t,n){let r=t.sqlName??C(e),a=r!==e;return t.type==="int"?a?`t.int(${h(r)})`:"t.int()":t.type==="string"?t.length!==void 0?a?`t.text(${h(r)}, { length: ${t.length} })`:`t.text({ length: ${t.length} })`:a?`t.text(${h(r)})`:"t.text()":t.type==="boolean"?a?`t.int(${h(r)}, { mode: "boolean" })`:'t.int({ mode: "boolean" })':t.type==="date"?a?`t.int(${h(r)}, { mode: "timestamp_ms" })`:'t.int({ mode: "timestamp_ms" })':n==="camelToSnake"&&a?`t.text(${h(r)})`:"t.text()"}function yr(e,t,n){let r=n.field,a=n.referenceField??"id";if(!r)throw new Error(`Relation on '${e}' targeting '${n.targetTable}' is missing a local field.`);if(!(r in t.columns))throw new Error(`Relation '${e}.${r}' references missing local field '${r}'.`);return {sourceField:r,targetField:a}}function wr(e){return e.size===0?"":`import { ${Array.from(e).sort().join(", ")} } from "./auth.schema";
|
|
8621
|
+
`}function xr(e){return Object.values(e.relations).filter(t=>t.relation==="one").map(t=>t.targetTable)}function vr(e,t,n){if(t.references)return {tableName:t.references.table,fieldName:t.references.column};let r=Object.values(n.relations).find(a=>a.relation==="one"&&a.field===e);if(r)return {tableName:r.targetTable,fieldName:r.referenceField??"id"}}function Tr(e){let t=[];for(let[n,r]of Object.entries(e.tables)){let a=[];for(let[o,i]of Object.entries(r.relations))i.relation==="manyToMany"&&i.junctionTable&&a.push(`${h(o)}: {
|
|
8622
|
+
targetTable: ${h(i.targetTable)},
|
|
8623
|
+
junctionTable: ${h(i.junctionTable)},
|
|
8624
|
+
sourceField: ${h(i.sourceField??"")},
|
|
8625
|
+
targetField: ${h(i.targetField??"")},
|
|
8626
|
+
},`);a.length!==0&&t.push(`${h(n)}: {
|
|
8627
|
+
${a.map(o=>` ${o}`).join(`
|
|
8628
|
+
`)}
|
|
8629
|
+
},`);}return t.length===0?`export const __appflareManyToMany = {} as const;
|
|
8630
|
+
`:`export const __appflareManyToMany = {
|
|
8631
|
+
${t.map(n=>` ${n}`).join(`
|
|
8632
|
+
`)}
|
|
8633
|
+
} as const;
|
|
8634
|
+
`}function Rr(e){let t=[];for(let[n,r]of Object.entries(e.tables)){let a=[];for(let[o,i]of Object.entries(r.relations)){if(i.relation==="one"){a.push(`${h(o)}: {
|
|
8635
|
+
kind: "one",
|
|
8636
|
+
targetTable: ${h(i.targetTable)},
|
|
8637
|
+
sourceField: ${h(i.field??"")},
|
|
8638
|
+
referenceField: ${h(i.referenceField??"id")},
|
|
8639
|
+
},`);continue}if(i.relation==="many"){a.push(`${h(o)}: {
|
|
8640
|
+
kind: "many",
|
|
8641
|
+
targetTable: ${h(i.targetTable)},
|
|
8642
|
+
sourceField: ${h(i.field??"")},
|
|
8643
|
+
referenceField: ${h(i.referenceField??"id")},
|
|
8644
|
+
},`);continue}a.push(`${h(o)}: {
|
|
8645
|
+
kind: "manyToMany",
|
|
8646
|
+
targetTable: ${h(i.targetTable)},
|
|
8647
|
+
junctionTable: ${h(i.junctionTable??"")},
|
|
8648
|
+
sourceField: ${h(i.sourceField??"")},
|
|
8649
|
+
targetField: ${h(i.targetField??"")},
|
|
8650
|
+
referenceField: ${h(i.referenceField??"id")},
|
|
8651
|
+
targetReferenceField: ${h(i.targetReferenceField??"id")},
|
|
8652
|
+
},`);}a.length!==0&&t.push(`${h(n)}: {
|
|
8653
|
+
${a.map(o=>` ${o}`).join(`
|
|
8654
|
+
`)}
|
|
8655
|
+
},`);}return t.length===0?`export const __appflareRelations = {} as const;
|
|
8656
|
+
`:`export const __appflareRelations = {
|
|
8657
|
+
${t.map(n=>` ${n}`).join(`
|
|
8658
|
+
`)}
|
|
8659
|
+
} as const;
|
|
8660
|
+
`}function kr(e,t){let n=new Set(Object.keys(e.tables)),r=new Set;for(let i of Object.values(e.tables)){for(let s of xr(i))n.has(s)||r.add(s);for(let s of Object.values(i.columns))s.references&&!n.has(s.references.table)&&r.add(s.references.table);}let a=[],o=[];for(let[i,s]of Object.entries(e.tables)){let l=s.sqlName??C(i),u=[],c=[];for(let[b,m]of Object.entries(s.columns)){let x=br(b,m,t);m.uuidPrimaryKey&&(x+=".$defaultFn(() => crypto.randomUUID())"),m.primaryKey&&(x+=m.autoIncrement?".primaryKey({ autoIncrement: true })":".primaryKey()"),m.notNull&&(x+=".notNull()"),m.sqlDefault!==void 0&&(x+=`.default(${cr(m.sqlDefault)})`);let v=vr(b,m,s);if(v)if(m.references?.onDelete||m.references?.onUpdate){let R=[];m.references.onDelete&&R.push(`onDelete: ${h(m.references.onDelete)}`),m.references.onUpdate&&R.push(`onUpdate: ${h(m.references.onUpdate)}`),x+=`.references(() => ${v.tableName}.${v.fieldName}, { ${R.join(", ")} })`;}else x+=`.references(() => ${v.tableName}.${v.fieldName})`;if(m.unique){let R=typeof m.unique=="object"&&m.unique.name?m.unique.name:`${l}_${C(b)}_unique_idx`;c.push(` t.uniqueIndex(${h(R)}).on(table.${b})`);}if(m.index){let R=typeof m.index=="object"&&m.index.name?m.index.name:`${l}_${C(b)}_idx`;c.push(` t.index(${h(R)}).on(table.${b})`);}u.push(` ${b}: ${x},`);}c.length>0?a.push(`export const ${i} = table(
|
|
8661
|
+
${h(l)},
|
|
7450
8662
|
{
|
|
7451
|
-
${
|
|
8663
|
+
${u.join(`
|
|
7452
8664
|
`)}
|
|
7453
8665
|
},
|
|
7454
8666
|
(table) => [
|
|
7455
|
-
${
|
|
8667
|
+
${c.join(`,
|
|
7456
8668
|
`)}
|
|
7457
8669
|
],
|
|
7458
|
-
);`):a.push(`export const ${i} = table(${
|
|
7459
|
-
${
|
|
8670
|
+
);`):a.push(`export const ${i} = table(${h(l)}, {
|
|
8671
|
+
${u.join(`
|
|
7460
8672
|
`)}
|
|
7461
|
-
});`);let
|
|
7462
|
-
fields: [${i}.${
|
|
7463
|
-
references: [${
|
|
7464
|
-
}),`);}for(let[b,
|
|
7465
|
-
${
|
|
8673
|
+
});`);let f=Object.entries(s.relations).filter(([,b])=>b.relation==="one"),d=Object.entries(s.relations).filter(([,b])=>b.relation==="many"),y=Object.entries(s.relations).filter(([,b])=>b.relation==="manyToMany");if(f.length===0&&d.length===0&&y.length===0)continue;let w=[];for(let[b,m]of f){let x=yr(i,s,m);w.push(` ${b}: one(${m.targetTable}, {
|
|
8674
|
+
fields: [${i}.${x.sourceField}],
|
|
8675
|
+
references: [${m.targetTable}.${x.targetField}],
|
|
8676
|
+
}),`);}for(let[b,m]of d)w.push(` ${b}: many(${m.targetTable}),`);for(let[b,m]of y){if(!m.junctionTable)throw new Error(`manyToMany relation '${i}.${b}' is missing junctionTable after normalization.`);w.push(` ${b}: many(${m.junctionTable}),`);}o.push(`export const ${i}Relations = relations(${i}, ({ one, many }) => ({
|
|
8677
|
+
${w.join(`
|
|
7466
8678
|
`)}
|
|
7467
8679
|
}));`);}return `import * as t from "drizzle-orm/sqlite-core";
|
|
7468
8680
|
import { sqliteTable as table } from "drizzle-orm/sqlite-core";
|
|
7469
8681
|
import { relations } from "drizzle-orm";
|
|
7470
|
-
${
|
|
8682
|
+
${wr(r)}
|
|
7471
8683
|
${a.join(`
|
|
7472
8684
|
|
|
7473
8685
|
`)}
|
|
@@ -7475,7 +8687,11 @@ ${a.join(`
|
|
|
7475
8687
|
${o.join(`
|
|
7476
8688
|
|
|
7477
8689
|
`)}
|
|
7478
|
-
|
|
8690
|
+
|
|
8691
|
+
${Tr(e)}
|
|
8692
|
+
|
|
8693
|
+
${Rr(e)}
|
|
8694
|
+
`}function Zt(e,t,n){let r="z.unknown()";return e.type==="int"?r="z.number().int()":e.type==="string"?(r="z.string()",e.length!==void 0&&(r+=`.max(${e.length})`)):e.type==="boolean"?r="z.boolean()":e.type==="date"&&(r="z.date()"),t&&(r+=".optional()"),n&&(r+=".nullable()"),r}function Sr(e){let t=[];for(let[n,r]of Object.entries(e.tables)){let a=D(n),o=[],i=[];for(let[s,l]of Object.entries(r.columns))o.push(` ${s}: ${Zt(l,Yt(l),$(l))},`),i.push(` ${s}: ${Zt(l,$(l),$(l))},`);t.push(`export const ${n}InsertSchema = z.object({
|
|
7479
8695
|
${o.join(`
|
|
7480
8696
|
`)}
|
|
7481
8697
|
});
|
|
@@ -7488,8 +8704,8 @@ export type ${a}Insert = z.infer<typeof ${n}InsertSchema>;
|
|
|
7488
8704
|
export type ${a}Select = z.infer<typeof ${n}SelectSchema>;
|
|
7489
8705
|
`);}return `import { z } from "zod";
|
|
7490
8706
|
|
|
7491
|
-
${
|
|
7492
|
-
`)}`}function
|
|
8707
|
+
${t.join(`
|
|
8708
|
+
`)}`}function Ar(e){return e.type==="int"?"number":e.type==="string"?"string":e.type==="boolean"?"boolean":e.type==="date"?"Date":"unknown"}function Nr(e){let t=[];for(let[n,r]of Object.entries(e.tables)){let a=D(n),o=[],i=[];for(let[s,l]of Object.entries(r.columns)){let u=Ar(l),c=$(l)?" | null":"";o.push(` ${s}${$(l)?"?":""}: ${u}${c};`),i.push(` ${s}${Yt(l)?"?":""}: ${u}${c};`);}t.push(`export type ${a} = {
|
|
7493
8709
|
${o.join(`
|
|
7494
8710
|
`)}
|
|
7495
8711
|
};
|
|
@@ -7497,14 +8713,14 @@ ${o.join(`
|
|
|
7497
8713
|
export type New${a} = {
|
|
7498
8714
|
${i.join(`
|
|
7499
8715
|
`)}
|
|
7500
|
-
};`);}return `${
|
|
8716
|
+
};`);}return `${t.join(`
|
|
7501
8717
|
|
|
7502
8718
|
`)}
|
|
7503
|
-
`}function wr(t,e){if(e){let n=t[e];if(!L(n))throw new Error(`schemaDsl.exportName '${e}' does not point to a schema() export.`);return n}for(let n of Object.values(t))if(L(n))return n;throw new Error("No schema() export found in schemaDsl entry module. Set schemaDsl.exportName to the correct export.")}async function Ge(t){let e=t.config.schemaDsl;if(!e)return;let n=e.namingStrategy??"camelToSnake",r=resolve(t.configDir,e.entry),a=resolve(t.configDir,e.outFile??resolve(t.outDirAbs,"schema.compiled.ts")),o=resolve(t.configDir,e.typesOutFile??resolve(t.outDirAbs,"schema.types.ts")),i=resolve(t.configDir,e.zodOutFile??resolve(t.outDirAbs,"schema.zod.ts")),l=await import(`${pathToFileURL(r).href}?t=${Date.now()}`),c=wr(l,e.exportName),d=ur(c);await Promise.all([mkdir(dirname(a),{recursive:true}),mkdir(dirname(o),{recursive:true}),mkdir(dirname(i),{recursive:true})]);let g=hr(d,n),u=xr(d),y=br(d);return await Promise.all([Bun.write(a,g),Bun.write(o,u),Bun.write(i,y)]),{schemaPath:a,typesPath:o,zodPath:i,tableNames:Object.keys(d.tables)}}function kr(t){return t.replaceAll("\\","/")}function R(t,e){let n=kr(relative(t,e)).replace(/\.tsx?$/,"");return n.startsWith(".")?n:`./${n}`}var Ar=new Set([".ts",".tsx",".mts",".cts"]);async function Xe(t){let e=await readdir(t,{withFileTypes:true}),n=[];for(let r of e){if(r.name.startsWith(".")||r.name==="node_modules"||r.name==="_generated")continue;let a=resolve(t,r.name);if(r.isDirectory()){n.push(...await Xe(a));continue}r.isFile()&&Ar.has(extname(r.name))&&n.push(a);}return n}function _(t){return t.replace(/\.[cm]?tsx?$/,"")}function $r(t,e){let n=t,r=false,a,o="unknown";for(;m.isCallExpression(n);){let i=n.expression;if(!m.isPropertyAccessExpression(i))break;let s=i.name.text;if(s==="optional"||s==="nullable")r=true,n=i.expression;else if(s==="default"){r=true;let l=n.arguments[0];l&&(m.isStringLiteral(l)||m.isNumericLiteral(l)?a=l.text:l.kind===m.SyntaxKind.TrueKeyword?a="true":l.kind===m.SyntaxKind.FalseKeyword&&(a="false")),n=i.expression;}else if(s==="string"||s==="uuid"||s==="email"||s==="url"){o="string";break}else if(s==="number"||s==="int"||s==="float"){o="number";break}else if(s==="boolean"){o="boolean";break}else n=i.expression;}return {name:e,type:o,optional:r,defaultValue:a}}function Nr(t){if(!t||!m.isObjectLiteralExpression(t))return [];let e=t.properties.find(r=>m.isPropertyAssignment(r)&&m.isIdentifier(r.name)&&r.name.text==="args");if(!e||!m.isObjectLiteralExpression(e.initializer))return [];let n=[];for(let r of e.initializer.properties)!m.isPropertyAssignment(r)||!m.isIdentifier(r.name)||n.push($r(r.initializer,r.name.text));return n}function qr(t){return m.isVariableStatement(t)?t.modifiers?.some(e=>e.kind===m.SyntaxKind.ExportKeyword)??false:false}function tn(t){return m.isIdentifier(t)?t.text:m.isParenthesizedExpression(t)?tn(t.expression):null}function Cr(t){if(!t||!m.isObjectLiteralExpression(t))return [];let e=t.properties.find(r=>!m.isPropertyAssignment(r)||!m.isIdentifier(r.name)?false:r.name.text==="cronTrigger");if(!e||!m.isPropertyAssignment(e))return [];let n=e.initializer;return m.isStringLiteral(n)||m.isNoSubstitutionTemplateLiteral(n)?[n.text.trim()].filter(r=>r.length>0):m.isArrayLiteralExpression(n)?n.elements.map(r=>m.isStringLiteral(r)||m.isNoSubstitutionTemplateLiteral(r)?r.text.trim():"").filter(r=>r.length>0):[]}function Pr(t,e){let n=m.createSourceFile(e,t,m.ScriptTarget.Latest,true,m.ScriptKind.TS),r=[];for(let a of n.statements)if(qr(a))for(let o of a.declarationList.declarations){if(!m.isIdentifier(o.name)||!o.initializer||!m.isCallExpression(o.initializer))continue;let i=tn(o.initializer.expression);i!=="query"&&i!=="mutation"&&i!=="scheduler"&&i!=="cron"&&i!=="storageManager"||r.push({exportName:o.name.text,kind:i==="storageManager"?"storage":i,cronTriggers:i==="cron"?Cr(o.initializer.arguments[0]):[],args:i==="query"||i==="mutation"?Nr(o.initializer.arguments[0]):[]});}return r}function Je(t,e,n){let r=e.replace(/\\/g,"/"),o=_(r).split("/").filter(Boolean);return `/${[t,...o,n].filter(Boolean).map(s=>s.trim()).filter(s=>s.length>0).join("/")}`}function Dr(t,e){let n=t.replace(/\\/g,"/"),r=`${e}/`,a=n.indexOf(r);return a>=0?n.slice(a+r.length):n===e?"index.ts":n}function Ze(t,e){let n=t.replace(/\\/g,"/"),a=_(n).split("/").filter(Boolean),o=a[a.length-1]??"index";return [a.length>1?a[a.length-2]:"root",o,e].map(s=>s.trim()).filter(s=>s.length>0).join("/")}async function en(t){let e=[],n=await Xe(t.scanDirAbs).catch(()=>[]);for(let a of n){let o=Bun.file(a);if(!await o.exists())continue;let i=await o.text(),s=relative(t.scanDirAbs,a),l=Pr(i,a),c=[{kind:"query",kindDirectory:"queries",exports:l.filter(d=>d.kind==="query")},{kind:"mutation",kindDirectory:"mutations",exports:l.filter(d=>d.kind==="mutation")},{kind:"scheduler",kindDirectory:"schedulers",exports:l.filter(d=>d.kind==="scheduler")},{kind:"cron",kindDirectory:"crons",exports:l.filter(d=>d.kind==="cron")},{kind:"storage",kindDirectory:"queries",exports:l.filter(d=>d.kind==="storage")}];for(let d of c){if(d.exports.length===0)continue;let g=Dr(s,d.kindDirectory);for(let u of d.exports){let y=d.kind==="query"||d.kind==="mutation"?Ze(g,u.exportName):void 0,b=d.kind==="scheduler"||d.kind==="cron"?Ze(g,u.exportName):void 0,f=d.kind==="query"||d.kind==="mutation"?[..._(g).split("/").filter(Boolean),u.exportName]:void 0,h=d.kind==="query"?Je("queries",g,u.exportName):d.kind==="mutation"?Je("mutations",g,u.exportName):d.kind==="storage"?`/storage/managers/${u.exportName}`:`/${d.kindDirectory}/${b}`;e.push({kind:d.kind,exportName:u.exportName,filePath:a,importPath:R(t.outDirAbs,a),clientImportPath:R(resolve(t.outDirAbs,"client"),a),routePath:h,handlerName:y,clientSegments:f,taskName:b,cronTriggers:u.cronTriggers,args:u.args});}}}e.sort((a,o)=>a.routePath.localeCompare(o.routePath));let r=new Map;for(let a of e){let o=a.taskName?`task:${a.taskName}`:`route:${a.routePath}`,i=r.get(o);if(i)throw new Error(`Duplicate handler operation discovered: ${a.taskName??a.routePath} (${i} and ${a.filePath}#${a.exportName}).`);r.set(o,`${a.filePath}#${a.exportName}`);}return e}function Er(t){let e=[],n="",r=0,a=0,o=0,i=false,s=false,l=false,c=false;for(let g=0;g<t.length;g+=1){let u=t[g];if(c){n+=u,c=false;continue}if(u==="\\"){n+=u,c=true;continue}if(!s&&!l&&u==="'"){i=!i,n+=u;continue}if(!i&&!l&&u==='"'){s=!s,n+=u;continue}if(!i&&!s&&u==="`"){l=!l,n+=u;continue}if(i||s||l){n+=u;continue}if(u==="("?r+=1:u===")"?r-=1:u==="{"?a+=1:u==="}"?a-=1:u==="["?o+=1:u==="]"&&(o-=1),u===","&&r===0&&a===0&&o===0){let y=n.trim();y.length>0&&e.push(y),n="";continue}n+=u;}let d=n.trim();return d.length>0&&e.push(d),e}function Ir(t){let e=0,n=0,r=0,a=false,o=false,i=false,s=false;for(let l=0;l<t.length;l+=1){let c=t[l];if(s){s=false;continue}if(c==="\\"){s=true;continue}if(!o&&!i&&c==="'"){a=!a;continue}if(!a&&!i&&c==='"'){o=!o;continue}if(!a&&!o&&c==="`"){i=!i;continue}if(!(a||o||i)){if(c==="("){e+=1;continue}if(c===")"){e-=1;continue}if(c==="{"){n+=1;continue}if(c==="}"){n-=1;continue}if(c==="["){r+=1;continue}if(c==="]"){r-=1;continue}if(c===":"&&e===0&&n===0&&r===0)return l}}return -1}function Fr(t){let e=t.toLowerCase();return /mode\s*:\s*["'`](timestamp|timestamp_ms)["'`]/.test(e)?"date":/mode\s*:\s*["'`]boolean["'`]/.test(e)?"boolean":/\.(date|datetime|timestamp)\s*\(/.test(e)?"date":/\.(int|integer|real|numeric|decimal|float|double)\s*\(/.test(e)?"number":/\.(text|varchar|char)\s*\(/.test(e)?"string":/\.(boolean|bool)\s*\(/.test(e)?"boolean":"unknown"}function Mr(t){let e=Er(t),n=[];for(let r of e){let a=Ir(r);if(a===-1)continue;let o=r.slice(0,a).trim().replace(/^['"]|['"]$/g,"");if(!o)continue;let i=r.slice(a+1).trim(),s=/\.primarykey\s*\(/i.test(i),l=/autoincrement\s*:\s*true/i.test(i),c=/\.default\s*\(/i.test(i),g=!/\.notnull\s*\(/i.test(i)||c||l||s;n.push({name:o,expression:i,type:Fr(i),optional:g,primaryKey:s,autoIncrement:l});}return n}function jr(t){let e=/export\s+const\s+(\w+)\s*=\s*table\s*\(\s*["'`]([^"'`]+)["'`]/g,n=[],r=(o,i)=>{let s=0,l=false,c=false,d=false,g=false;for(let u=i;u<o.length;u+=1){let y=o[u];if(g){g=false;continue}if(y==="\\"){g=true;continue}if(!c&&!d&&y==="'"){l=!l;continue}if(!l&&!d&&y==='"'){c=!c;continue}if(!l&&!c&&y==="`"){d=!d;continue}if(!(l||c||d)){if(y==="{"){s+=1;continue}if(y==="}"&&(s-=1,s===0))return u}}return -1},a=e.exec(t);for(;a;){let o=a[1],i=a[2],s=t.indexOf("{",e.lastIndex);if(s===-1){a=e.exec(t);continue}let l=r(t,s);if(l===-1){a=e.exec(t);continue}let c=t.slice(s+1,l);n.push({exportName:o,tableName:i,columns:Mr(c)}),a=e.exec(t);}return n}async function rn(t){let e=await readdir(t,{withFileTypes:true}),n=[];for(let r of e){if(r.name.startsWith(".")||r.name==="node_modules"||r.name==="_generated")continue;let a=resolve(t,r.name);if(r.isDirectory()){n.push(...await rn(a));continue}r.isFile()&&r.name==="schema.ts"&&n.push(a);}return n}async function an(t,e=[]){let n=await rn(t.scanDirAbs).catch(()=>[]),r=resolve(t.configDir,"schema.ts"),a=[...e,...n.length?n:[r]];for(let o of a){let i=Bun.file(o);if(!await i.exists())continue;let s=await i.text(),l=jr(s);if(l.length>0)return {schemaPath:o,tables:l}}throw new Error(`Unable to discover schema.ts under scanDir (${t.scanDirAbs}) or fallback (${r}).`)}function Br(t,e){let n=relative(t,e).replace(/\\/g,"/");return n.startsWith(".")?n:`./${n}`}async function on(t){let{outDirAbs:e,wranglerOutDirAbs:n,config:r,configPath:a,configDir:o}=t,i=R(e,a),s=resolve(e,"client"),l=R(s,a);await Promise.all([mkdir(e,{recursive:true}),mkdir(s,{recursive:true}),mkdir(n,{recursive:true})]);let c=resolve(e,"server.ts"),d=resolve(e,"client.ts"),g=resolve(e,"auth.config.ts"),u=resolve(e,"auth.schema.ts"),y=resolve(e,"drizzle.config.ts"),b=resolve(n,"wrangler.json"),f=await Ge(t),h=await an(t,f?[f.schemaPath]:[]),k=R(e,h.schemaPath),w=await en(t),hn=Xt(r.auth.basePath,r.database[0].binding,r.kv[0]?.binding,r.scheduler.binding,r.r2[0]?.binding,r.realtime.binding,r.realtime.objectName,r.realtime.subscribePath,r.realtime.websocketPath,r.realtime.protocol),bn=at(l,w),yn=j(k,w,r.r2[0]?.binding),xn=Z(i),wn=f?[Br(o,f.schemaPath),...r.schema.filter(T=>!/(^|\/)schema\.ts$/.test(T))]:r.schema,vn=ot(wn),kn=ee(t,w),Tn=ze(k,h,w),Sn=resolve(e,"admin.routes.ts"),Rn=yn.map(T=>Bun.write(resolve(e,T.relativePath),T.source)),An=bn.map(T=>Bun.write(resolve(e,T.relativePath),T.source));await Promise.all([Bun.write(c,hn),Bun.write(d,`export * from "./client/index";
|
|
7504
|
-
`),...
|
|
7505
|
-
`),Bun.write(
|
|
7506
|
-
`);return}process.stdout.write(`\u2705 Generated server/client in ${
|
|
7507
|
-
`);}async function
|
|
7508
|
-
`);}finally{r=false,a&&(a=false,await o());}};
|
|
8719
|
+
`}function $r(e,t){if(t){let n=e[t];if(!_(n))throw new Error(`schemaDsl.exportName '${t}' does not point to a schema() export.`);return n}for(let n of Object.values(e))if(_(n))return n;throw new Error("No schema() export found in schemaDsl entry module. Set schemaDsl.exportName to the correct export.")}async function Xt(e){let t=e.config.schemaDsl;if(!t)return;let n=t.namingStrategy??"camelToSnake",r=resolve(e.configDir,t.entry),a=resolve(e.configDir,t.outFile??resolve(e.outDirAbs,"schema.compiled.ts")),o=resolve(e.configDir,t.typesOutFile??resolve(e.outDirAbs,"schema.types.ts")),i=resolve(e.configDir,t.zodOutFile??resolve(e.outDirAbs,"schema.zod.ts")),l=await import(`${pathToFileURL(r).href}?t=${Date.now()}`),u=$r(l,t.exportName),c=hr(u);await Promise.all([mkdir(dirname(a),{recursive:true}),mkdir(dirname(o),{recursive:true}),mkdir(dirname(i),{recursive:true})]);let f=kr(c,n),d=Nr(c),y=Sr(c);return await Promise.all([Bun.write(a,f),Bun.write(o,d),Bun.write(i,y)]),{schemaPath:a,typesPath:o,zodPath:i,tableNames:Object.keys(c.tables)}}function Ir(e){return e.replaceAll("\\","/")}function A(e,t){let n=Ir(relative(e,t)).replace(/\.tsx?$/,"");return n.startsWith(".")?n:`./${n}`}var Dr=new Set([".ts",".tsx",".mts",".cts"]);async function rn(e){let t=await readdir(e,{withFileTypes:true}),n=[];for(let r of t){if(r.name.startsWith(".")||r.name==="node_modules"||r.name==="_generated")continue;let a=resolve(e,r.name);if(r.isDirectory()){n.push(...await rn(a));continue}r.isFile()&&Dr.has(extname(r.name))&&n.push(a);}return n}function Z(e){return e.replace(/\.[cm]?tsx?$/,"")}function Fr(e,t){let n=e,r=false,a,o="unknown";for(;g.isCallExpression(n);){let i=n.expression;if(!g.isPropertyAccessExpression(i))break;let s=i.name.text;if(s==="optional"||s==="nullable")r=true,n=i.expression;else if(s==="default"){r=true;let l=n.arguments[0];l&&(g.isStringLiteral(l)||g.isNumericLiteral(l)?a=l.text:l.kind===g.SyntaxKind.TrueKeyword?a="true":l.kind===g.SyntaxKind.FalseKeyword&&(a="false")),n=i.expression;}else if(s==="string"||s==="uuid"||s==="email"||s==="url"){o="string";break}else if(s==="number"||s==="int"||s==="float"){o="number";break}else if(s==="boolean"){o="boolean";break}else n=i.expression;}return {name:t,type:o,optional:r,defaultValue:a}}function Er(e){if(!e||!g.isObjectLiteralExpression(e))return [];let t=e.properties.find(r=>g.isPropertyAssignment(r)&&g.isIdentifier(r.name)&&r.name.text==="args");if(!t||!g.isObjectLiteralExpression(t.initializer))return [];let n=[];for(let r of t.initializer.properties)!g.isPropertyAssignment(r)||!g.isIdentifier(r.name)||n.push(Fr(r.initializer,r.name.text));return n}function Or(e){return g.isVariableStatement(e)?e.modifiers?.some(t=>t.kind===g.SyntaxKind.ExportKeyword)??false:false}function an(e){return g.isIdentifier(e)?e.text:g.isParenthesizedExpression(e)?an(e.expression):null}function jr(e){if(!e||!g.isObjectLiteralExpression(e))return [];let t=e.properties.find(r=>!g.isPropertyAssignment(r)||!g.isIdentifier(r.name)?false:r.name.text==="cronTrigger");if(!t||!g.isPropertyAssignment(t))return [];let n=t.initializer;return g.isStringLiteral(n)||g.isNoSubstitutionTemplateLiteral(n)?[n.text.trim()].filter(r=>r.length>0):g.isArrayLiteralExpression(n)?n.elements.map(r=>g.isStringLiteral(r)||g.isNoSubstitutionTemplateLiteral(r)?r.text.trim():"").filter(r=>r.length>0):[]}function Vr(e,t){let n=g.createSourceFile(t,e,g.ScriptTarget.Latest,true,g.ScriptKind.TS),r=[];for(let a of n.statements)if(Or(a))for(let o of a.declarationList.declarations){if(!g.isIdentifier(o.name)||!o.initializer||!g.isCallExpression(o.initializer))continue;let i=an(o.initializer.expression);i!=="query"&&i!=="mutation"&&i!=="scheduler"&&i!=="cron"&&i!=="storageManager"||r.push({exportName:o.name.text,kind:i==="storageManager"?"storage":i,cronTriggers:i==="cron"?jr(o.initializer.arguments[0]):[],args:i==="query"||i==="mutation"?Er(o.initializer.arguments[0]):[]});}return r}function en(e,t,n){let r=t.replace(/\\/g,"/"),o=Z(r).split("/").filter(Boolean);return `/${[e,...o,n].filter(Boolean).map(s=>s.trim()).filter(s=>s.length>0).join("/")}`}function Br(e,t){let n=e.replace(/\\/g,"/"),r=`${t}/`,a=n.indexOf(r);return a>=0?n.slice(a+r.length):n===t?"index.ts":n}function tn(e,t){let n=e.replace(/\\/g,"/"),a=Z(n).split("/").filter(Boolean),o=a[a.length-1]??"index";return [a.length>1?a[a.length-2]:"root",o,t].map(s=>s.trim()).filter(s=>s.length>0).join("/")}async function on(e){let t=[],n=await rn(e.scanDirAbs).catch(()=>[]);for(let a of n){let o=Bun.file(a);if(!await o.exists())continue;let i=await o.text(),s=relative(e.scanDirAbs,a),l=Vr(i,a),u=[{kind:"query",kindDirectory:"queries",exports:l.filter(c=>c.kind==="query")},{kind:"mutation",kindDirectory:"mutations",exports:l.filter(c=>c.kind==="mutation")},{kind:"scheduler",kindDirectory:"schedulers",exports:l.filter(c=>c.kind==="scheduler")},{kind:"cron",kindDirectory:"crons",exports:l.filter(c=>c.kind==="cron")},{kind:"storage",kindDirectory:"queries",exports:l.filter(c=>c.kind==="storage")}];for(let c of u){if(c.exports.length===0)continue;let f=Br(s,c.kindDirectory);for(let d of c.exports){let y=c.kind==="query"||c.kind==="mutation"?tn(f,d.exportName):void 0,w=c.kind==="scheduler"||c.kind==="cron"?tn(f,d.exportName):void 0,b=c.kind==="query"||c.kind==="mutation"?[...Z(f).split("/").filter(Boolean),d.exportName]:void 0,m=c.kind==="query"?en("queries",f,d.exportName):c.kind==="mutation"?en("mutations",f,d.exportName):c.kind==="storage"?`/storage/managers/${d.exportName}`:`/${c.kindDirectory}/${w}`;t.push({kind:c.kind,exportName:d.exportName,filePath:a,importPath:A(e.outDirAbs,a),clientImportPath:A(resolve(e.outDirAbs,"client"),a),routePath:m,handlerName:y,clientSegments:b,taskName:w,cronTriggers:d.cronTriggers,args:d.args});}}}t.sort((a,o)=>a.routePath.localeCompare(o.routePath));let r=new Map;for(let a of t){let o=a.taskName?`task:${a.taskName}`:`route:${a.routePath}`,i=r.get(o);if(i)throw new Error(`Duplicate handler operation discovered: ${a.taskName??a.routePath} (${i} and ${a.filePath}#${a.exportName}).`);r.set(o,`${a.filePath}#${a.exportName}`);}return t}function Wr(e){let t=[],n="",r=0,a=0,o=0,i=false,s=false,l=false,u=false;for(let f=0;f<e.length;f+=1){let d=e[f];if(u){n+=d,u=false;continue}if(d==="\\"){n+=d,u=true;continue}if(!s&&!l&&d==="'"){i=!i,n+=d;continue}if(!i&&!l&&d==='"'){s=!s,n+=d;continue}if(!i&&!s&&d==="`"){l=!l,n+=d;continue}if(i||s||l){n+=d;continue}if(d==="("?r+=1:d===")"?r-=1:d==="{"?a+=1:d==="}"?a-=1:d==="["?o+=1:d==="]"&&(o-=1),d===","&&r===0&&a===0&&o===0){let y=n.trim();y.length>0&&t.push(y),n="";continue}n+=d;}let c=n.trim();return c.length>0&&t.push(c),t}function Lr(e){let t=0,n=0,r=0,a=false,o=false,i=false,s=false;for(let l=0;l<e.length;l+=1){let u=e[l];if(s){s=false;continue}if(u==="\\"){s=true;continue}if(!o&&!i&&u==="'"){a=!a;continue}if(!a&&!i&&u==='"'){o=!o;continue}if(!a&&!o&&u==="`"){i=!i;continue}if(!(a||o||i)){if(u==="("){t+=1;continue}if(u===")"){t-=1;continue}if(u==="{"){n+=1;continue}if(u==="}"){n-=1;continue}if(u==="["){r+=1;continue}if(u==="]"){r-=1;continue}if(u===":"&&t===0&&n===0&&r===0)return l}}return -1}function zr(e){let t=e.toLowerCase();return /mode\s*:\s*["'`](timestamp|timestamp_ms)["'`]/.test(t)?"date":/mode\s*:\s*["'`]boolean["'`]/.test(t)?"boolean":/\.(date|datetime|timestamp)\s*\(/.test(t)?"date":/\.(int|integer|real|numeric|decimal|float|double)\s*\(/.test(t)?"number":/\.(text|varchar|char)\s*\(/.test(t)?"string":/\.(boolean|bool)\s*\(/.test(t)?"boolean":"unknown"}function Ur(e){let t=Wr(e),n=[];for(let r of t){let a=Lr(r);if(a===-1)continue;let o=r.slice(0,a).trim().replace(/^['"]|['"]$/g,"");if(!o)continue;let i=r.slice(a+1).trim(),s=/\.primarykey\s*\(/i.test(i),l=/autoincrement\s*:\s*true/i.test(i),u=/\.default\s*\(/i.test(i),f=!/\.notnull\s*\(/i.test(i)||u||l||s;n.push({name:o,expression:i,type:zr(i),optional:f,primaryKey:s,autoIncrement:l});}return n}function Qr(e){let t=/export\s+const\s+(\w+)\s*=\s*table\s*\(\s*["'`]([^"'`]+)["'`]/g,n=[],r=(o,i)=>{let s=0,l=false,u=false,c=false,f=false;for(let d=i;d<o.length;d+=1){let y=o[d];if(f){f=false;continue}if(y==="\\"){f=true;continue}if(!u&&!c&&y==="'"){l=!l;continue}if(!l&&!c&&y==='"'){u=!u;continue}if(!l&&!u&&y==="`"){c=!c;continue}if(!(l||u||c)){if(y==="{"){s+=1;continue}if(y==="}"&&(s-=1,s===0))return d}}return -1},a=t.exec(e);for(;a;){let o=a[1],i=a[2],s=e.indexOf("{",t.lastIndex);if(s===-1){a=t.exec(e);continue}let l=r(e,s);if(l===-1){a=t.exec(e);continue}let u=e.slice(s+1,l);n.push({exportName:o,tableName:i,columns:Ur(u)}),a=t.exec(e);}return n}async function ln(e){let t=await readdir(e,{withFileTypes:true}),n=[];for(let r of t){if(r.name.startsWith(".")||r.name==="node_modules"||r.name==="_generated")continue;let a=resolve(e,r.name);if(r.isDirectory()){n.push(...await ln(a));continue}r.isFile()&&r.name==="schema.ts"&&n.push(a);}return n}async function cn(e,t=[]){let n=await ln(e.scanDirAbs).catch(()=>[]),r=resolve(e.configDir,"schema.ts"),a=[...t,...n.length?n:[r]];for(let o of a){let i=Bun.file(o);if(!await i.exists())continue;let s=await i.text(),l=Qr(s);if(l.length>0)return {schemaPath:o,tables:l}}throw new Error(`Unable to discover schema.ts under scanDir (${e.scanDirAbs}) or fallback (${r}).`)}function _r(e,t){let n=relative(e,t).replace(/\\/g,"/");return n.startsWith(".")?n:`./${n}`}async function un(e){let{outDirAbs:t,wranglerOutDirAbs:n,config:r,configPath:a,configDir:o}=e,i=A(t,a),s=resolve(t,"client"),l=A(s,a);await Promise.all([mkdir(t,{recursive:true}),mkdir(s,{recursive:true}),mkdir(n,{recursive:true})]);let u=resolve(t,"server.ts"),c=resolve(t,"client.ts"),f=resolve(t,"auth.config.ts"),d=resolve(t,"auth.schema.ts"),y=resolve(t,"drizzle.config.ts"),w=resolve(n,"wrangler.json"),b=await Xt(e),m=await cn(e,b?[b.schemaPath]:[]),x=A(t,m.schemaPath),v=await on(e),R=rt(r.auth.basePath,r.database[0].binding,r.kv[0]?.binding,r.scheduler.binding,r.r2[0]?.binding,r.realtime.binding,r.realtime.objectName,r.realtime.subscribePath,r.realtime.websocketPath,r.realtime.protocol),xn=le(l,v),vn=H(x,v,r.r2[0]?.binding),Tn=te(i),Rn=b?[_r(o,b.schemaPath),...r.schema.filter(k=>!/(^|\/)schema\.ts$/.test(k))]:r.schema,kn=ce(Rn),Sn=ot(e,v),An=Qt(x,m,v),Nn=resolve(t,"admin.routes.ts"),$n=vn.map(k=>Bun.write(resolve(t,k.relativePath),k.source)),qn=xn.map(k=>Bun.write(resolve(t,k.relativePath),k.source));await Promise.all([Bun.write(u,R),Bun.write(c,`export * from "./client/index";
|
|
8720
|
+
`),...qn,...$n,Bun.write(f,Tn),Bun.write(d,""),Bun.write(y,kn),Bun.write(w,`${JSON.stringify(Sn,null,2)}
|
|
8721
|
+
`),Bun.write(Nn,An)]);let O=relative(o,f).replace(/\\/g,"/"),In=O.startsWith(".")?O:`./${O}`,j=relative(o,d).replace(/\\/g,"/"),Mn=j.startsWith(".")?j:`./${j}`,ee=await Bun.spawn(["npx","@better-auth/cli","generate","--config",In,"--output",Mn,"--yes"],{cwd:o,stdout:"inherit",stderr:"inherit"}).exited;if(ee!==0)throw new Error(`better-auth generation failed with exit code ${ee}`)}var dn=z$1.object({binding:z$1.string().min(1),databaseName:z$1.string().min(1),databaseId:z$1.string().min(1),previewDatabaseId:z$1.string().min(1).optional(),migrationsDir:z$1.string().min(1).optional()}).strict(),pn=z$1.object({binding:z$1.string().min(1),id:z$1.string().min(1),previewId:z$1.string().min(1).optional()}).strict(),mn=z$1.object({binding:z$1.string().min(1),bucketName:z$1.string().min(1),previewBucketName:z$1.string().min(1).optional(),jurisdiction:z$1.string().min(1).optional()}).strict(),gn=z$1.object({enabled:z$1.boolean().optional(),binding:z$1.string().min(1).optional(),queue:z$1.string().min(1).optional()}).strict(),Zr=z$1.object({enabled:z$1.boolean().optional(),binding:z$1.string().min(1).optional(),className:z$1.string().min(1).optional(),objectName:z$1.string().min(1).optional(),subscribePath:z$1.string().min(1).optional(),websocketPath:z$1.string().min(1).optional(),protocol:z$1.string().min(1).optional()}).strict(),Yr=z$1.object({scanDir:z$1.string().min(1),outDir:z$1.string().min(1),wranglerOutDir:z$1.string().min(1).optional(),wranglerOutPath:z$1.string().min(1).optional(),schema:z$1.array(z$1.string()).min(1),schemaDsl:z$1.object({entry:z$1.string().min(1),exportName:z$1.string().min(1).optional(),outFile:z$1.string().min(1).optional(),typesOutFile:z$1.string().min(1).optional(),zodOutFile:z$1.string().min(1).optional(),namingStrategy:z$1.literal("camelToSnake").optional()}).strict().optional(),database:z$1.union([dn,z$1.array(dn).min(1)]),kv:z$1.union([pn,z$1.array(pn)]).optional(),r2:z$1.union([mn,z$1.array(mn)]).optional(),auth:z$1.object({enabled:z$1.boolean(),basePath:z$1.string().min(1),options:z$1.custom(e=>typeof e=="object"&&e!==null),clientOptions:z$1.custom(e=>typeof e=="object"&&e!==null)}).strict(),scheduler:gn.optional(),realtime:Zr.optional(),wranglerOverrides:z$1.record(z$1.string(),z$1.unknown()).optional()}).strict();function fn(e){return typeof e=="object"&&e!==null}function Xr(e){let t=fn(e.wranglerOverrides)?e.wranglerOverrides.scheduler:void 0,n=gn.safeParse(t);return n.success?n.data:{}}function ea(e){if(!fn(e)||!("scheduler"in e))return e;let{scheduler:t,...n}=e;return n}function ta(e){let n={...Xr(e)??{},...e.scheduler??{}},r=e.realtime??{};return {...e,database:Array.isArray(e.database)?e.database:[e.database],kv:e.kv?Array.isArray(e.kv)?e.kv:[e.kv]:[],r2:e.r2?Array.isArray(e.r2)?e.r2:[e.r2]:[],scheduler:{enabled:n.enabled??true,binding:n.binding??"APPFLARE_SCHEDULER_QUEUE",queue:n.queue},realtime:{enabled:r.enabled??true,binding:r.binding??"APPFLARE_REALTIME",className:r.className??"AppflareRealtimeDurableObject",objectName:r.objectName??"global",subscribePath:r.subscribePath??"/realtime/subscribe",websocketPath:r.websocketPath??"/realtime/ws",protocol:r.protocol??"appflare.realtime.v1"},wranglerOverrides:ea(e.wranglerOverrides),wranglerOutDir:e.wranglerOutDir??e.wranglerOutPath??e.outDir}}async function q(e){let t=isAbsolute(e??"")?e:resolve(process.cwd(),e??"appflare.config.ts"),n=dirname(t),o=(await import(pathToFileURL(t).href)).default,i=Yr.parse(o),s=ta(i);return {configPath:t,configDir:n,scanDirAbs:resolve(n,s.scanDir),outDirAbs:resolve(n,s.outDir),wranglerOutDirAbs:resolve(n,s.wranglerOutDir),config:s}}function oa(e){let t=e;for(;;){if(existsSync(resolve(t,"package.json")))return t;let n=dirname(t);if(n===t)return e;t=n;}}async function E(e){let t=await q(e);if(await un(t),t.wranglerOutDirAbs===t.outDirAbs){process.stdout.write(`\u2705 Generated artifacts in ${t.outDirAbs}
|
|
8722
|
+
`);return}process.stdout.write(`\u2705 Generated server/client in ${t.outDirAbs} and wrangler.json in ${t.wranglerOutDirAbs}
|
|
8723
|
+
`);}async function bn(e,t=false){if(await E(e),!t)return;let n=await q(e),r=false,a=false,o=async()=>{if(r){a=true;return}r=true;try{await E(e);}catch(s){process.stderr.write(`\u274C Build failed: ${s.message}
|
|
8724
|
+
`);}finally{r=false,a&&(a=false,await o());}};na.watch(n.scanDirAbs,{ignoreInitial:true}).on("all",async(s,l)=>{process.stdout.write(`\u{1F504} Change detected: ${l}
|
|
7509
8725
|
`),await o();}),process.stdout.write(`\u{1F440} Watching ${n.scanDirAbs}
|
|
7510
|
-
`);}async function
|
|
8726
|
+
`);}async function yn(e,t={}){let n=await q(e),r=oa(process.cwd());if([!!t.local,!!t.remote,!!t.preview].filter(Boolean).length>1)throw new Error("Only one of --local, --remote, or --preview can be set.");let o=resolve(n.outDirAbs,"drizzle.config.ts"),i=process.platform==="win32"?"npx.cmd":"npx",l=await Bun.spawn([i,"drizzle-kit","generate","--config",o],{cwd:r,stdin:"inherit",stdout:"inherit",stderr:"inherit"}).exited;if(l!==0)throw new Error(`drizzle-kit generate failed with exit code ${l}`);let u=n.config.database[0].databaseName,c=[i,"wrangler","d1","migrations","apply",u];t.local?c.push("--local"):t.remote?c.push("--remote"):t.preview&&c.push("--preview");let d=await Bun.spawn(c,{cwd:n.configDir,stdin:"inherit",stdout:"inherit",stderr:"inherit"}).exited;if(d!==0)throw new Error(`wrangler d1 migrations apply failed with exit code ${d}`)}async function wn(e,t={name:"",email:"",password:""}){let n=await q(e);if([!!t.local,!!t.remote].filter(Boolean).length>1)throw new Error("Only one of --local or --remote can be set.");let{hashPassword:a}=await import('better-auth/crypto'),o=await a(t.password),i=crypto.randomUUID(),s=crypto.randomUUID(),l=Date.now(),u=t.name.replace(/'/g,"''"),c=t.email.replace(/'/g,"''"),f=["INSERT INTO users (id, name, email, email_verified, created_at, updated_at, role, banned)",`VALUES ('${i}', '${u}', '${c}', 1, ${l}, ${l}, 'admin', 0);`,"INSERT INTO accounts (id, account_id, provider_id, user_id, password, created_at, updated_at)",`VALUES ('${s}', '${c}', 'credential', '${i}', '${o}', ${l}, ${l});`].join(" "),d=n.config.database[0].databaseName,w=[process.platform==="win32"?"npx.cmd":"npx","wrangler","d1","execute",d,`--command=${f}`];t.local?w.push("--local"):t.remote&&w.push("--remote");let m=await Bun.spawn(w,{cwd:n.configDir,stdin:"inherit",stdout:"inherit",stderr:"inherit"}).exited;if(m!==0)throw new Error(`Failed to add admin user. wrangler d1 execute exited with code ${m}`);console.log("\u2705 Admin user "+t.email+" created successfully!");}var N=new Command;N.name("appflare").description("Appflare compiler/bundler for Cloudflare-native backends and SDK generation").version("0.0.28");N.command("build").description("Generate server.ts, client.ts, auth.config.ts, drizzle.config.ts, and wrangler.json artifacts").option("-c, --config <path>","Path to appflare.config.ts","appflare.config.ts").action(async e=>{await E(e.config);});N.command("dev").description("Run generator in development mode").option("-c, --config <path>","Path to appflare.config.ts","appflare.config.ts").option("-w, --watch","Watch scanDir and regenerate on changes",false).action(async e=>{await bn(e.config,e.watch);});N.command("migrate").description("Generate drizzle migration files from outDir/auth.schema.ts and apply them to the configured D1 database").option("-c, --config <path>","Path to appflare.config.ts","appflare.config.ts").option("--local","Execute commands/files against a local DB for use with wrangler dev",false).option("--remote","Execute commands/files against a remote DB for use with wrangler dev --remote",false).option("--preview","Execute commands/files against a preview D1 DB",false).action(async e=>{await yn(e.config,{local:e.local,remote:e.remote,preview:e.preview});});N.command("add-admin").description("Add an admin user to the database").requiredOption("-n, --name <name>","Admin's display name").requiredOption("-e, --email <email>","Admin's email address").requiredOption("-p, --password <password>","Admin's password").option("-c, --config <path>","Path to appflare.config.ts","appflare.config.ts").option("--local","Execute command against a local DB for use with wrangler dev",false).option("--remote","Execute command against a remote DB for use with wrangler dev --remote",false).action(async e=>{await wn(e.config,{name:e.name,email:e.email,password:e.password,local:e.local,remote:e.remote});});(async()=>{process.versions.bun||(console.error("Appflare CLI must be run with Bun."),process.exit(1)),await N.parseAsync(process.argv);})().catch(e=>{console.error(e),process.exit(1);});
|