appflare 0.2.14 → 0.2.16
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 +535 -9
- package/cli/templates/dashboard/builders/table-routes/helpers.ts +1 -5
- package/cli/templates/handlers/generators/types/query-definitions/filter-and-where-types.ts +88 -7
- package/cli/templates/handlers/generators/types/query-definitions/query-api-types.ts +1 -1
- 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 +174 -19
- 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 +425 -6
- package/cli/utils/schema-discovery.ts +1 -1
- package/dist/cli/index.js +1478 -385
- package/dist/cli/index.mjs +1478 -385
- package/dist/index.d.mts +31 -2
- package/dist/index.d.ts +31 -2
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/schema.ts +76 -3
package/dist/cli/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
'use strict';var commander=require('commander'),
|
|
2
|
+
'use strict';var commander=require('commander'),na=require('chokidar'),fs=require('fs'),path=require('path'),promises=require('fs/promises'),url=require('url'),g=require('typescript'),zod=require('zod');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var na__default=/*#__PURE__*/_interopDefault(na);var g__namespace=/*#__PURE__*/_interopNamespace(g);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 Pn(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 In(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}${In(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=Pn(`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 En(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=>En(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 infer TTarget
|
|
1759
|
+
? TTarget extends TableName
|
|
1760
|
+
? QueryManyToManyWithRelationInput<TTarget>
|
|
1761
|
+
: QueryNativeWithRelationInput<TEntry>
|
|
1762
|
+
: QueryNativeWithRelationInput<TEntry>;
|
|
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,59 @@ 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 SingularizeRelationName<TName extends string> =
|
|
1799
|
+
TName extends \`\${infer TRoot}ies\`
|
|
1800
|
+
? \`\${TRoot}y\`
|
|
1801
|
+
: TName extends \`\${infer TRoot}s\`
|
|
1802
|
+
? TRoot
|
|
1803
|
+
: TName;
|
|
1804
|
+
|
|
1805
|
+
type RelationInsertItem<TTargetTable extends TableName> =
|
|
1806
|
+
| TableModel<TTargetTable>
|
|
1807
|
+
| TableInsertModel<TTargetTable>
|
|
1808
|
+
| ("id" extends keyof TableModel<TTargetTable>
|
|
1809
|
+
? TableModel<TTargetTable>["id"]
|
|
1810
|
+
: never);
|
|
1811
|
+
|
|
1812
|
+
type RelationInsertValue<
|
|
1813
|
+
TSourceTable extends TableName,
|
|
1814
|
+
TRelationName extends RuntimeRelationName<TSourceTable>,
|
|
1815
|
+
> = RuntimeRelationTargetTable<TSourceTable, TRelationName> extends infer TTargetTable
|
|
1816
|
+
? TTargetTable extends TableName
|
|
1817
|
+
? RuntimeRelationKind<TSourceTable, TRelationName> extends "one"
|
|
1818
|
+
? RelationInsertItem<TTargetTable>
|
|
1819
|
+
: RelationInsertItem<TTargetTable> | Array<RelationInsertItem<TTargetTable>>
|
|
1820
|
+
: never
|
|
1821
|
+
: never;
|
|
1822
|
+
|
|
1823
|
+
type RelationInsertFields<TName extends TableName> = {
|
|
1824
|
+
[TRelationName in RuntimeRelationName<TName>]?: RelationInsertValue<
|
|
1825
|
+
TName,
|
|
1826
|
+
TRelationName
|
|
1827
|
+
>;
|
|
1828
|
+
};
|
|
1829
|
+
|
|
1830
|
+
type RelationInsertIdAliasFields<TName extends TableName> = {
|
|
1831
|
+
[TRelationName in RuntimeRelationName<TName> as \`\${TRelationName}Id\`]?: RelationInsertValue<
|
|
1832
|
+
TName,
|
|
1833
|
+
TRelationName
|
|
1834
|
+
>;
|
|
1835
|
+
} & {
|
|
1836
|
+
[TRelationName in RuntimeRelationName<TName> as \`\${SingularizeRelationName<TRelationName>}Id\`]?: RelationInsertValue<
|
|
1837
|
+
TName,
|
|
1838
|
+
TRelationName
|
|
1839
|
+
>;
|
|
1763
1840
|
};
|
|
1764
1841
|
|
|
1842
|
+
type QueryInsertValue<TName extends TableName> = TableInsertScalarModel<TName> &
|
|
1843
|
+
RelationInsertFields<TName> &
|
|
1844
|
+
RelationInsertIdAliasFields<TName>;
|
|
1845
|
+
|
|
1765
1846
|
export type QueryInsertArgs<TName extends TableName> = {
|
|
1766
|
-
values:
|
|
1847
|
+
values: QueryInsertValue<TName> | Array<QueryInsertValue<TName>>;
|
|
1767
1848
|
};
|
|
1768
1849
|
|
|
1769
1850
|
export type QueryUpdateArgs<TName extends TableName> = {
|
|
@@ -1776,8 +1857,8 @@ export type QueryDeleteArgs<TName extends TableName> = {
|
|
|
1776
1857
|
where?: WhereInput<TableModel<TName>>;
|
|
1777
1858
|
limit?: number;
|
|
1778
1859
|
};
|
|
1779
|
-
`}function
|
|
1780
|
-
QueryWithInput<NativeFindManyWith<TName>>;
|
|
1860
|
+
`}function Te(){return `type AggregateWithInput<TName extends TableName> =
|
|
1861
|
+
QueryWithInput<TName, NativeFindManyWith<TName>>;
|
|
1781
1862
|
|
|
1782
1863
|
type NumericFieldKey<TName extends TableName> = NumericModelFieldKey<
|
|
1783
1864
|
TableModel<TName>
|
|
@@ -1906,7 +1987,7 @@ export type DbMutationEvent = {
|
|
|
1906
1987
|
export type QueryDbOptions = {
|
|
1907
1988
|
onMutation?: (event: DbMutationEvent) => void;
|
|
1908
1989
|
};
|
|
1909
|
-
`}function
|
|
1990
|
+
`}function Re(){return `function isRecord(value: unknown): value is Record<string, unknown> {
|
|
1910
1991
|
return typeof value === "object" && value !== null;
|
|
1911
1992
|
}
|
|
1912
1993
|
|
|
@@ -2186,8 +2267,292 @@ function buildWhereFilterFromFields(
|
|
|
2186
2267
|
return and(...filters);
|
|
2187
2268
|
}
|
|
2188
2269
|
|
|
2189
|
-
|
|
2190
|
-
|
|
2270
|
+
type ManyToManyRuntimeRelation = {
|
|
2271
|
+
targetTable: string;
|
|
2272
|
+
junctionTable: string;
|
|
2273
|
+
sourceField?: string;
|
|
2274
|
+
targetField?: string;
|
|
2275
|
+
referenceField?: string;
|
|
2276
|
+
targetReferenceField?: string;
|
|
2277
|
+
};
|
|
2278
|
+
|
|
2279
|
+
type RuntimeRelationOne = {
|
|
2280
|
+
kind: "one";
|
|
2281
|
+
targetTable: string;
|
|
2282
|
+
sourceField?: string;
|
|
2283
|
+
referenceField?: string;
|
|
2284
|
+
};
|
|
2285
|
+
|
|
2286
|
+
type RuntimeRelationMany = {
|
|
2287
|
+
kind: "many";
|
|
2288
|
+
targetTable: string;
|
|
2289
|
+
sourceField?: string;
|
|
2290
|
+
referenceField?: string;
|
|
2291
|
+
};
|
|
2292
|
+
|
|
2293
|
+
type RuntimeRelationManyToMany = ManyToManyRuntimeRelation & {
|
|
2294
|
+
kind: "manyToMany";
|
|
2295
|
+
};
|
|
2296
|
+
|
|
2297
|
+
type RuntimeRelation =
|
|
2298
|
+
| RuntimeRelationOne
|
|
2299
|
+
| RuntimeRelationMany
|
|
2300
|
+
| RuntimeRelationManyToMany;
|
|
2301
|
+
|
|
2302
|
+
type RuntimeRelationMap = Record<string, Record<string, RuntimeRelation>>;
|
|
2303
|
+
|
|
2304
|
+
function getRuntimeRelationMap(): RuntimeRelationMap {
|
|
2305
|
+
const rawValue = (mergedSchema as Record<string, unknown>)[
|
|
2306
|
+
"__appflareRelations"
|
|
2307
|
+
];
|
|
2308
|
+
if (!isRecord(rawValue)) {
|
|
2309
|
+
return {};
|
|
2310
|
+
}
|
|
2311
|
+
|
|
2312
|
+
const map: RuntimeRelationMap = {};
|
|
2313
|
+
for (const [tableName, tableValue] of Object.entries(rawValue)) {
|
|
2314
|
+
if (!isRecord(tableValue)) {
|
|
2315
|
+
continue;
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2318
|
+
const relationMap: Record<string, RuntimeRelation> = {};
|
|
2319
|
+
for (const [relationName, relationValue] of Object.entries(tableValue)) {
|
|
2320
|
+
if (!isRecord(relationValue)) {
|
|
2321
|
+
continue;
|
|
2322
|
+
}
|
|
2323
|
+
|
|
2324
|
+
const kind = relationValue.kind;
|
|
2325
|
+
const targetTable = relationValue.targetTable;
|
|
2326
|
+
if (typeof kind !== "string" || typeof targetTable !== "string") {
|
|
2327
|
+
continue;
|
|
2328
|
+
}
|
|
2329
|
+
|
|
2330
|
+
const sourceField =
|
|
2331
|
+
typeof relationValue.sourceField === "string"
|
|
2332
|
+
? relationValue.sourceField
|
|
2333
|
+
: undefined;
|
|
2334
|
+
const referenceField =
|
|
2335
|
+
typeof relationValue.referenceField === "string"
|
|
2336
|
+
? relationValue.referenceField
|
|
2337
|
+
: undefined;
|
|
2338
|
+
|
|
2339
|
+
if (kind === "one") {
|
|
2340
|
+
relationMap[relationName] = {
|
|
2341
|
+
kind: "one",
|
|
2342
|
+
targetTable,
|
|
2343
|
+
sourceField,
|
|
2344
|
+
referenceField,
|
|
2345
|
+
};
|
|
2346
|
+
continue;
|
|
2347
|
+
}
|
|
2348
|
+
|
|
2349
|
+
if (kind === "many") {
|
|
2350
|
+
relationMap[relationName] = {
|
|
2351
|
+
kind: "many",
|
|
2352
|
+
targetTable,
|
|
2353
|
+
sourceField,
|
|
2354
|
+
referenceField,
|
|
2355
|
+
};
|
|
2356
|
+
continue;
|
|
2357
|
+
}
|
|
2358
|
+
|
|
2359
|
+
if (kind === "manyToMany") {
|
|
2360
|
+
const junctionTable = relationValue.junctionTable;
|
|
2361
|
+
if (typeof junctionTable !== "string") {
|
|
2362
|
+
continue;
|
|
2363
|
+
}
|
|
2364
|
+
|
|
2365
|
+
relationMap[relationName] = {
|
|
2366
|
+
kind: "manyToMany",
|
|
2367
|
+
targetTable,
|
|
2368
|
+
junctionTable,
|
|
2369
|
+
sourceField,
|
|
2370
|
+
targetField:
|
|
2371
|
+
typeof relationValue.targetField === "string"
|
|
2372
|
+
? relationValue.targetField
|
|
2373
|
+
: undefined,
|
|
2374
|
+
referenceField,
|
|
2375
|
+
targetReferenceField:
|
|
2376
|
+
typeof relationValue.targetReferenceField === "string"
|
|
2377
|
+
? relationValue.targetReferenceField
|
|
2378
|
+
: undefined,
|
|
2379
|
+
};
|
|
2380
|
+
}
|
|
2381
|
+
}
|
|
2382
|
+
|
|
2383
|
+
if (Object.keys(relationMap).length > 0) {
|
|
2384
|
+
map[tableName] = relationMap;
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
|
|
2388
|
+
return map;
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2391
|
+
const runtimeRelationMap = getRuntimeRelationMap();
|
|
2392
|
+
|
|
2393
|
+
function getRuntimeRelation(
|
|
2394
|
+
tableName: string,
|
|
2395
|
+
relationName: string,
|
|
2396
|
+
): RuntimeRelation | undefined {
|
|
2397
|
+
return runtimeRelationMap[tableName]?.[relationName];
|
|
2398
|
+
}
|
|
2399
|
+
|
|
2400
|
+
type ManyToManyRuntimeMap = Record<
|
|
2401
|
+
string,
|
|
2402
|
+
Record<string, ManyToManyRuntimeRelation>
|
|
2403
|
+
>;
|
|
2404
|
+
|
|
2405
|
+
function getManyToManyRuntimeMap(): ManyToManyRuntimeMap {
|
|
2406
|
+
const rawValue = (mergedSchema as Record<string, unknown>)[
|
|
2407
|
+
"__appflareManyToMany"
|
|
2408
|
+
];
|
|
2409
|
+
if (!isRecord(rawValue)) {
|
|
2410
|
+
return {};
|
|
2411
|
+
}
|
|
2412
|
+
|
|
2413
|
+
const map: ManyToManyRuntimeMap = {};
|
|
2414
|
+
for (const [tableName, tableValue] of Object.entries(rawValue)) {
|
|
2415
|
+
if (!isRecord(tableValue)) {
|
|
2416
|
+
continue;
|
|
2417
|
+
}
|
|
2418
|
+
|
|
2419
|
+
const relationMap: Record<string, ManyToManyRuntimeRelation> = {};
|
|
2420
|
+
for (const [relationName, relationValue] of Object.entries(tableValue)) {
|
|
2421
|
+
const runtimeRelation = getRuntimeRelation(tableName, relationName);
|
|
2422
|
+
if (!runtimeRelation || runtimeRelation.kind !== "manyToMany") {
|
|
2423
|
+
continue;
|
|
2424
|
+
}
|
|
2425
|
+
|
|
2426
|
+
relationMap[relationName] = {
|
|
2427
|
+
targetTable: runtimeRelation.targetTable,
|
|
2428
|
+
junctionTable: runtimeRelation.junctionTable,
|
|
2429
|
+
sourceField: runtimeRelation.sourceField,
|
|
2430
|
+
targetField: runtimeRelation.targetField,
|
|
2431
|
+
referenceField: runtimeRelation.referenceField,
|
|
2432
|
+
targetReferenceField: runtimeRelation.targetReferenceField,
|
|
2433
|
+
};
|
|
2434
|
+
}
|
|
2435
|
+
|
|
2436
|
+
if (Object.keys(relationMap).length > 0) {
|
|
2437
|
+
map[tableName] = relationMap;
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2441
|
+
return map;
|
|
2442
|
+
}
|
|
2443
|
+
|
|
2444
|
+
const manyToManyRuntimeMap = getManyToManyRuntimeMap();
|
|
2445
|
+
|
|
2446
|
+
function getManyToManyRelation(
|
|
2447
|
+
tableName: string,
|
|
2448
|
+
relationName: string,
|
|
2449
|
+
): ManyToManyRuntimeRelation | undefined {
|
|
2450
|
+
return manyToManyRuntimeMap[tableName]?.[relationName];
|
|
2451
|
+
}
|
|
2452
|
+
|
|
2453
|
+
function hasManyToManyRelationsInWith(
|
|
2454
|
+
tableName: string,
|
|
2455
|
+
withValue: unknown,
|
|
2456
|
+
): boolean {
|
|
2457
|
+
if (!isRecord(withValue)) {
|
|
2458
|
+
return false;
|
|
2459
|
+
}
|
|
2460
|
+
|
|
2461
|
+
for (const [relationName, relationValue] of Object.entries(withValue)) {
|
|
2462
|
+
const manyToMany = getManyToManyRelation(tableName, relationName);
|
|
2463
|
+
if (manyToMany) {
|
|
2464
|
+
return true;
|
|
2465
|
+
}
|
|
2466
|
+
|
|
2467
|
+
if (!isRecord(relationValue)) {
|
|
2468
|
+
continue;
|
|
2469
|
+
}
|
|
2470
|
+
|
|
2471
|
+
const nestedWith = relationValue.with;
|
|
2472
|
+
if (
|
|
2473
|
+
hasManyToManyRelationsInWith(relationName, nestedWith) ||
|
|
2474
|
+
(manyToMany &&
|
|
2475
|
+
hasManyToManyRelationsInWith(manyToMany.targetTable, nestedWith))
|
|
2476
|
+
) {
|
|
2477
|
+
return true;
|
|
2478
|
+
}
|
|
2479
|
+
}
|
|
2480
|
+
|
|
2481
|
+
return false;
|
|
2482
|
+
}
|
|
2483
|
+
|
|
2484
|
+
function flattenManyToManyResult(
|
|
2485
|
+
tableName: string,
|
|
2486
|
+
result: unknown,
|
|
2487
|
+
withValue: unknown,
|
|
2488
|
+
): unknown {
|
|
2489
|
+
if (!isRecord(withValue)) {
|
|
2490
|
+
return result;
|
|
2491
|
+
}
|
|
2492
|
+
|
|
2493
|
+
if (Array.isArray(result)) {
|
|
2494
|
+
return result.map((entry) =>
|
|
2495
|
+
flattenManyToManyResult(tableName, entry, withValue),
|
|
2496
|
+
);
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2499
|
+
if (!isRecord(result)) {
|
|
2500
|
+
return result;
|
|
2501
|
+
}
|
|
2502
|
+
|
|
2503
|
+
const nextRow: Record<string, unknown> = {
|
|
2504
|
+
...result,
|
|
2505
|
+
};
|
|
2506
|
+
|
|
2507
|
+
for (const [relationName, relationValue] of Object.entries(withValue)) {
|
|
2508
|
+
const manyToMany = getManyToManyRelation(tableName, relationName);
|
|
2509
|
+
const currentValue = nextRow[relationName];
|
|
2510
|
+
|
|
2511
|
+
if (manyToMany) {
|
|
2512
|
+
const relationEntries = Array.isArray(currentValue)
|
|
2513
|
+
? currentValue
|
|
2514
|
+
: currentValue === null || currentValue === undefined
|
|
2515
|
+
? []
|
|
2516
|
+
: [currentValue];
|
|
2517
|
+
|
|
2518
|
+
const nestedWith =
|
|
2519
|
+
isRecord(relationValue) && relationValue.with !== undefined
|
|
2520
|
+
? relationValue.with
|
|
2521
|
+
: undefined;
|
|
2522
|
+
|
|
2523
|
+
const flattened = relationEntries
|
|
2524
|
+
.map((entry) => {
|
|
2525
|
+
if (!isRecord(entry)) {
|
|
2526
|
+
return undefined;
|
|
2527
|
+
}
|
|
2528
|
+
|
|
2529
|
+
const targetValue = entry[manyToMany.targetTable];
|
|
2530
|
+
return flattenManyToManyResult(
|
|
2531
|
+
manyToMany.targetTable,
|
|
2532
|
+
targetValue,
|
|
2533
|
+
nestedWith,
|
|
2534
|
+
);
|
|
2535
|
+
})
|
|
2536
|
+
.filter((entry) => entry !== undefined && entry !== null);
|
|
2537
|
+
|
|
2538
|
+
nextRow[relationName] = flattened;
|
|
2539
|
+
continue;
|
|
2540
|
+
}
|
|
2541
|
+
|
|
2542
|
+
if (isRecord(relationValue) && relationValue.with !== undefined) {
|
|
2543
|
+
nextRow[relationName] = flattenManyToManyResult(
|
|
2544
|
+
relationName,
|
|
2545
|
+
currentValue,
|
|
2546
|
+
relationValue.with,
|
|
2547
|
+
);
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
|
|
2551
|
+
return nextRow;
|
|
2552
|
+
}
|
|
2553
|
+
|
|
2554
|
+
function transformWithRelations(withValue: unknown, tableName?: string): unknown {
|
|
2555
|
+
return transformWithRelationsAndExtractAggregates(withValue, tableName).with;
|
|
2191
2556
|
}
|
|
2192
2557
|
|
|
2193
2558
|
type RelationWithAggregatePlanEntry = {
|
|
@@ -2214,7 +2579,10 @@ function extractRelationAvgFieldNames(value: unknown): string[] {
|
|
|
2214
2579
|
.map(([fieldName]) => fieldName);
|
|
2215
2580
|
}
|
|
2216
2581
|
|
|
2217
|
-
function transformWithRelationsAndExtractAggregates(
|
|
2582
|
+
function transformWithRelationsAndExtractAggregates(
|
|
2583
|
+
withValue: unknown,
|
|
2584
|
+
tableName?: string,
|
|
2585
|
+
): {
|
|
2218
2586
|
with: unknown;
|
|
2219
2587
|
aggregatePlan: RelationWithAggregatePlan | undefined;
|
|
2220
2588
|
} {
|
|
@@ -2228,8 +2596,21 @@ function transformWithRelationsAndExtractAggregates(withValue: unknown): {
|
|
|
2228
2596
|
const transformed: Record<string, unknown> = {};
|
|
2229
2597
|
const aggregatePlan: RelationWithAggregatePlan = {};
|
|
2230
2598
|
for (const [relationName, relationValue] of Object.entries(withValue)) {
|
|
2599
|
+
const manyToMany =
|
|
2600
|
+
tableName === undefined
|
|
2601
|
+
? undefined
|
|
2602
|
+
: getManyToManyRelation(tableName, relationName);
|
|
2603
|
+
|
|
2231
2604
|
if (typeof relationValue === "boolean") {
|
|
2232
|
-
|
|
2605
|
+
if (manyToMany && relationValue) {
|
|
2606
|
+
transformed[relationName] = {
|
|
2607
|
+
with: {
|
|
2608
|
+
[manyToMany.targetTable]: true,
|
|
2609
|
+
},
|
|
2610
|
+
};
|
|
2611
|
+
} else {
|
|
2612
|
+
transformed[relationName] = relationValue;
|
|
2613
|
+
}
|
|
2233
2614
|
continue;
|
|
2234
2615
|
}
|
|
2235
2616
|
|
|
@@ -2238,13 +2619,19 @@ function transformWithRelationsAndExtractAggregates(withValue: unknown): {
|
|
|
2238
2619
|
continue;
|
|
2239
2620
|
}
|
|
2240
2621
|
|
|
2241
|
-
const
|
|
2622
|
+
const relationConfigInput: Record<string, unknown> = {
|
|
2242
2623
|
...relationValue,
|
|
2243
2624
|
};
|
|
2244
|
-
const countRequested =
|
|
2245
|
-
const avgFieldNames = extractRelationAvgFieldNames(
|
|
2246
|
-
delete
|
|
2247
|
-
delete
|
|
2625
|
+
const countRequested = relationConfigInput._count === true;
|
|
2626
|
+
const avgFieldNames = extractRelationAvgFieldNames(relationConfigInput._avg);
|
|
2627
|
+
delete relationConfigInput._count;
|
|
2628
|
+
delete relationConfigInput._avg;
|
|
2629
|
+
|
|
2630
|
+
const relationConfig: Record<string, unknown> = manyToMany
|
|
2631
|
+
? {
|
|
2632
|
+
...relationConfigInput,
|
|
2633
|
+
}
|
|
2634
|
+
: relationConfigInput;
|
|
2248
2635
|
|
|
2249
2636
|
let nestedAggregatePlan: RelationWithAggregatePlan | undefined;
|
|
2250
2637
|
|
|
@@ -2257,7 +2644,7 @@ function transformWithRelationsAndExtractAggregates(withValue: unknown): {
|
|
|
2257
2644
|
);
|
|
2258
2645
|
}
|
|
2259
2646
|
|
|
2260
|
-
if (isRecord(relationWhere)) {
|
|
2647
|
+
if (isRecord(relationWhere) && !manyToMany) {
|
|
2261
2648
|
relationConfig.where = (fields: Record<string, unknown>) => {
|
|
2262
2649
|
const filter = buildWhereFilterFromFields(
|
|
2263
2650
|
fields,
|
|
@@ -2272,9 +2659,52 @@ function transformWithRelationsAndExtractAggregates(withValue: unknown): {
|
|
|
2272
2659
|
};
|
|
2273
2660
|
}
|
|
2274
2661
|
|
|
2275
|
-
if (
|
|
2662
|
+
if (manyToMany) {
|
|
2663
|
+
const targetRelationConfig: Record<string, unknown> = {};
|
|
2664
|
+
for (const [configKey, configValue] of Object.entries(relationConfig)) {
|
|
2665
|
+
if (configKey === "with" || configKey === "where") {
|
|
2666
|
+
continue;
|
|
2667
|
+
}
|
|
2668
|
+
targetRelationConfig[configKey] = configValue;
|
|
2669
|
+
}
|
|
2670
|
+
|
|
2671
|
+
if (isRecord(relationWhere)) {
|
|
2672
|
+
targetRelationConfig.where = (fields: Record<string, unknown>) => {
|
|
2673
|
+
const filter = buildWhereFilterFromFields(
|
|
2674
|
+
fields,
|
|
2675
|
+
relationWhere,
|
|
2676
|
+
manyToMany.targetTable,
|
|
2677
|
+
);
|
|
2678
|
+
if (filter) {
|
|
2679
|
+
return filter;
|
|
2680
|
+
}
|
|
2681
|
+
|
|
2682
|
+
return sql\`1 = 1\`;
|
|
2683
|
+
};
|
|
2684
|
+
}
|
|
2685
|
+
|
|
2686
|
+
if (relationConfig.with !== undefined) {
|
|
2687
|
+
const nestedTransform = transformWithRelationsAndExtractAggregates(
|
|
2688
|
+
relationConfig.with,
|
|
2689
|
+
manyToMany.targetTable,
|
|
2690
|
+
);
|
|
2691
|
+
targetRelationConfig.with = nestedTransform.with;
|
|
2692
|
+
nestedAggregatePlan = nestedTransform.aggregatePlan;
|
|
2693
|
+
}
|
|
2694
|
+
|
|
2695
|
+
const targetConfigValue =
|
|
2696
|
+
Object.keys(targetRelationConfig).length === 0
|
|
2697
|
+
? true
|
|
2698
|
+
: targetRelationConfig;
|
|
2699
|
+
|
|
2700
|
+
relationConfig.with = {
|
|
2701
|
+
[manyToMany.targetTable]: targetConfigValue,
|
|
2702
|
+
};
|
|
2703
|
+
delete relationConfig.where;
|
|
2704
|
+
} else if (relationConfig.with !== undefined) {
|
|
2276
2705
|
const nestedTransform = transformWithRelationsAndExtractAggregates(
|
|
2277
2706
|
relationConfig.with,
|
|
2707
|
+
relationName,
|
|
2278
2708
|
);
|
|
2279
2709
|
relationConfig.with = nestedTransform.with;
|
|
2280
2710
|
nestedAggregatePlan = nestedTransform.aggregatePlan;
|
|
@@ -2589,7 +3019,7 @@ function inferConflictTarget(table: unknown): string[] {
|
|
|
2589
3019
|
|
|
2590
3020
|
return [];
|
|
2591
3021
|
}
|
|
2592
|
-
`}function
|
|
3022
|
+
`}function ke(){return `const mergedSchema = {
|
|
2593
3023
|
...authSchema,
|
|
2594
3024
|
...schema,
|
|
2595
3025
|
};
|
|
@@ -2617,7 +3047,13 @@ type ResolveNativeFindManyWith<
|
|
|
2617
3047
|
TName extends TableName,
|
|
2618
3048
|
TArgs extends QueryFindManyArgs<TName> | undefined,
|
|
2619
3049
|
> = TArgs extends { with?: infer TWith }
|
|
2620
|
-
? Extract<TWith, NativeFindManyWith<TName>>
|
|
3050
|
+
? Extract<TWith, NativeFindManyWith<TName>> extends infer TResolved
|
|
3051
|
+
? [TResolved] extends [never]
|
|
3052
|
+
? TWith extends Record<string, unknown>
|
|
3053
|
+
? NativeFindManyWith<TName>
|
|
3054
|
+
: never
|
|
3055
|
+
: TResolved
|
|
3056
|
+
: never
|
|
2621
3057
|
: never;
|
|
2622
3058
|
type ResolveTableFindManySelection<
|
|
2623
3059
|
TName extends TableName,
|
|
@@ -2628,19 +3064,159 @@ type ResolveTableFindManySelection<
|
|
|
2628
3064
|
(ResolveNativeFindManyWith<TName, TArgs> extends never
|
|
2629
3065
|
? {}
|
|
2630
3066
|
: { with: ResolveNativeFindManyWith<TName, TArgs> });
|
|
3067
|
+
type TableModel<TName extends TableName> = InferSelectModel<
|
|
3068
|
+
(typeof mergedSchema)[TName]
|
|
3069
|
+
>;
|
|
3070
|
+
type ManyToManySchemaMap = typeof schema extends {
|
|
3071
|
+
__appflareManyToMany: infer TMap;
|
|
3072
|
+
}
|
|
3073
|
+
? TMap extends Record<string, Record<string, { targetTable: string }>>
|
|
3074
|
+
? TMap
|
|
3075
|
+
: {}
|
|
3076
|
+
: {};
|
|
3077
|
+
type ManyToManyTargetTableName<
|
|
3078
|
+
TSourceTable extends TableName,
|
|
3079
|
+
TRelationName extends string,
|
|
3080
|
+
> = TSourceTable extends keyof ManyToManySchemaMap
|
|
3081
|
+
? TRelationName extends keyof ManyToManySchemaMap[TSourceTable]
|
|
3082
|
+
? ManyToManySchemaMap[TSourceTable][TRelationName] extends {
|
|
3083
|
+
targetTable: infer TTarget extends string;
|
|
3084
|
+
}
|
|
3085
|
+
? Extract<TTarget, TableName>
|
|
3086
|
+
: never
|
|
3087
|
+
: never
|
|
3088
|
+
: never;
|
|
3089
|
+
type RuntimeRelationsSchemaMap = typeof schema extends {
|
|
3090
|
+
__appflareRelations: infer TMap;
|
|
3091
|
+
}
|
|
3092
|
+
? TMap extends Record<
|
|
3093
|
+
string,
|
|
3094
|
+
Record<string, { kind: string; targetTable: string }>
|
|
3095
|
+
>
|
|
3096
|
+
? TMap
|
|
3097
|
+
: {}
|
|
3098
|
+
: {};
|
|
3099
|
+
type RuntimeRelationName<TSourceTable extends TableName> =
|
|
3100
|
+
TSourceTable extends keyof RuntimeRelationsSchemaMap
|
|
3101
|
+
? Extract<keyof RuntimeRelationsSchemaMap[TSourceTable], string>
|
|
3102
|
+
: never;
|
|
3103
|
+
type RuntimeRelationConfig<
|
|
3104
|
+
TSourceTable extends TableName,
|
|
3105
|
+
TRelationName extends string,
|
|
3106
|
+
> = TSourceTable extends keyof RuntimeRelationsSchemaMap
|
|
3107
|
+
? TRelationName extends keyof RuntimeRelationsSchemaMap[TSourceTable]
|
|
3108
|
+
? RuntimeRelationsSchemaMap[TSourceTable][TRelationName]
|
|
3109
|
+
: never
|
|
3110
|
+
: never;
|
|
3111
|
+
type RuntimeRelationKind<
|
|
3112
|
+
TSourceTable extends TableName,
|
|
3113
|
+
TRelationName extends string,
|
|
3114
|
+
> = RuntimeRelationConfig<TSourceTable, TRelationName> extends {
|
|
3115
|
+
kind: infer TKind extends string;
|
|
3116
|
+
}
|
|
3117
|
+
? TKind
|
|
3118
|
+
: never;
|
|
3119
|
+
type RuntimeRelationTargetTable<
|
|
3120
|
+
TSourceTable extends TableName,
|
|
3121
|
+
TRelationName extends string,
|
|
3122
|
+
> = RuntimeRelationConfig<TSourceTable, TRelationName> extends {
|
|
3123
|
+
targetTable: infer TTarget extends string;
|
|
3124
|
+
}
|
|
3125
|
+
? Extract<TTarget, TableName>
|
|
3126
|
+
: never;
|
|
3127
|
+
type TableInsertScalarModel<TName extends TableName> = Omit<
|
|
3128
|
+
TableInsertModel<TName>,
|
|
3129
|
+
RuntimeRelationName<TName>
|
|
3130
|
+
>;
|
|
3131
|
+
type FindManyWithFromArgs<TArgs> = TArgs extends { with?: infer TWith }
|
|
3132
|
+
? TWith
|
|
3133
|
+
: undefined;
|
|
3134
|
+
type ManyToManyRelationRows<
|
|
3135
|
+
TTargetTable extends TableName,
|
|
3136
|
+
TRelationArgs,
|
|
3137
|
+
> = TRelationArgs extends true
|
|
3138
|
+
? Array<TableModel<TTargetTable>>
|
|
3139
|
+
: TRelationArgs extends Record<string, unknown>
|
|
3140
|
+
? Awaited<
|
|
3141
|
+
TableFindManyResult<
|
|
3142
|
+
TTargetTable,
|
|
3143
|
+
Extract<
|
|
3144
|
+
Omit<TRelationArgs, "_count" | "_avg">,
|
|
3145
|
+
QueryFindManyArgs<TTargetTable>
|
|
3146
|
+
>
|
|
3147
|
+
>
|
|
3148
|
+
>
|
|
3149
|
+
: Array<TableModel<TTargetTable>>;
|
|
3150
|
+
type ReplaceManyToManyRelationsInRow<
|
|
3151
|
+
TSourceTable extends TableName,
|
|
3152
|
+
TRow,
|
|
3153
|
+
TWith,
|
|
3154
|
+
> = TRow extends Record<string, unknown>
|
|
3155
|
+
? {
|
|
3156
|
+
[K in keyof TRow]: K extends string
|
|
3157
|
+
? TWith extends Record<string, unknown>
|
|
3158
|
+
? K extends keyof TWith
|
|
3159
|
+
? ManyToManyTargetTableName<TSourceTable, K> extends infer TTarget
|
|
3160
|
+
? TTarget extends TableName
|
|
3161
|
+
? ManyToManyRelationRows<TTarget, TWith[K]>
|
|
3162
|
+
: TRow[K]
|
|
3163
|
+
: TRow[K]
|
|
3164
|
+
: TRow[K]
|
|
3165
|
+
: TRow[K]
|
|
3166
|
+
: TRow[K];
|
|
3167
|
+
}
|
|
3168
|
+
: TRow;
|
|
3169
|
+
type ApplyManyToManyFindManyResult<
|
|
3170
|
+
TSourceTable extends TableName,
|
|
3171
|
+
TArgs extends QueryFindManyArgs<TSourceTable> | undefined,
|
|
3172
|
+
TResult,
|
|
3173
|
+
> = TResult extends Promise<infer TRows>
|
|
3174
|
+
? TRows extends Array<infer TRow>
|
|
3175
|
+
? Promise<
|
|
3176
|
+
Array<
|
|
3177
|
+
ReplaceManyToManyRelationsInRow<
|
|
3178
|
+
TSourceTable,
|
|
3179
|
+
TRow,
|
|
3180
|
+
FindManyWithFromArgs<TArgs>
|
|
3181
|
+
>
|
|
3182
|
+
>
|
|
3183
|
+
>
|
|
3184
|
+
: TResult
|
|
3185
|
+
: TResult;
|
|
3186
|
+
type ApplyManyToManyFindFirstResult<
|
|
3187
|
+
TSourceTable extends TableName,
|
|
3188
|
+
TArgs extends QueryFindFirstArgs<TSourceTable> | undefined,
|
|
3189
|
+
TResult,
|
|
3190
|
+
> = TResult extends Promise<infer TRow>
|
|
3191
|
+
? Promise<
|
|
3192
|
+
TRow extends null
|
|
3193
|
+
? null
|
|
3194
|
+
: ReplaceManyToManyRelationsInRow<
|
|
3195
|
+
TSourceTable,
|
|
3196
|
+
TRow,
|
|
3197
|
+
FindManyWithFromArgs<TArgs>
|
|
3198
|
+
>
|
|
3199
|
+
>
|
|
3200
|
+
: TResult;
|
|
2631
3201
|
type TableFindManyResult<
|
|
2632
3202
|
TName extends TableName,
|
|
2633
3203
|
TArgs extends QueryFindManyArgs<TName> | undefined =
|
|
2634
3204
|
| QueryFindManyArgs<TName>
|
|
2635
3205
|
| undefined,
|
|
2636
|
-
> =
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
3206
|
+
> = ApplyManyToManyFindManyResult<
|
|
3207
|
+
TName,
|
|
3208
|
+
TArgs,
|
|
3209
|
+
TArgs extends undefined
|
|
3210
|
+
? Promise<Array<TableModel<TName>>>
|
|
3211
|
+
: Promise<
|
|
3212
|
+
Array<
|
|
3213
|
+
BuildQueryResult<
|
|
3214
|
+
SchemaRelations,
|
|
3215
|
+
TableRelationConfig<TName>,
|
|
3216
|
+
ResolveTableFindManySelection<TName, TArgs>
|
|
3217
|
+
>
|
|
3218
|
+
>
|
|
3219
|
+
>
|
|
2644
3220
|
>;
|
|
2645
3221
|
type TableFindFirstArgs<TName extends TableName> = Omit<
|
|
2646
3222
|
TableFindManyArgs<TName>,
|
|
@@ -2654,7 +3230,13 @@ type ResolveNativeFindFirstWith<
|
|
|
2654
3230
|
TName extends TableName,
|
|
2655
3231
|
TArgs extends QueryFindFirstArgs<TName> | undefined,
|
|
2656
3232
|
> = TArgs extends { with?: infer TWith }
|
|
2657
|
-
? Extract<TWith, NativeFindFirstWith<TName>>
|
|
3233
|
+
? Extract<TWith, NativeFindFirstWith<TName>> extends infer TResolved
|
|
3234
|
+
? [TResolved] extends [never]
|
|
3235
|
+
? TWith extends Record<string, unknown>
|
|
3236
|
+
? NativeFindFirstWith<TName>
|
|
3237
|
+
: never
|
|
3238
|
+
: TResolved
|
|
3239
|
+
: never
|
|
2658
3240
|
: never;
|
|
2659
3241
|
type ResolveTableFindFirstSelection<
|
|
2660
3242
|
TName extends TableName,
|
|
@@ -2670,22 +3252,25 @@ type TableFindFirstResult<
|
|
|
2670
3252
|
TArgs extends QueryFindFirstArgs<TName> | undefined =
|
|
2671
3253
|
| QueryFindFirstArgs<TName>
|
|
2672
3254
|
| undefined,
|
|
2673
|
-
> =
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
3255
|
+
> = ApplyManyToManyFindFirstResult<
|
|
3256
|
+
TName,
|
|
3257
|
+
TArgs,
|
|
3258
|
+
TArgs extends undefined
|
|
3259
|
+
? Promise<TableModel<TName> | null>
|
|
3260
|
+
: Promise<
|
|
3261
|
+
BuildQueryResult<
|
|
3262
|
+
SchemaRelations,
|
|
3263
|
+
TableRelationConfig<TName>,
|
|
3264
|
+
ResolveTableFindFirstSelection<TName, TArgs>
|
|
3265
|
+
> | null
|
|
3266
|
+
>
|
|
2682
3267
|
>;
|
|
2683
3268
|
type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
2684
3269
|
(typeof mergedSchema)[TName]
|
|
2685
3270
|
>;
|
|
2686
|
-
`}function
|
|
3271
|
+
`}function Se(){return [ke(),ve(),Te(),Re()].join(`
|
|
2687
3272
|
|
|
2688
|
-
`)}function
|
|
3273
|
+
`)}function Ae(){return ` count: async (args?: QueryCountArgs<TableName>) => {
|
|
2689
3274
|
const withValue = args?.with;
|
|
2690
3275
|
const pathSegments = args?.field
|
|
2691
3276
|
? splitAggregateFieldPath(String(args.field))
|
|
@@ -2705,12 +3290,17 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
2705
3290
|
const transformedWith =
|
|
2706
3291
|
withValue === undefined
|
|
2707
3292
|
? undefined
|
|
2708
|
-
: transformWithRelations(withValue);
|
|
3293
|
+
: transformWithRelations(withValue, tableName);
|
|
2709
3294
|
const rawRows = await queryTable.findMany({
|
|
2710
3295
|
...(whereFilter ? { where: () => whereFilter } : {}),
|
|
2711
3296
|
...(transformedWith !== undefined ? { with: transformedWith } : {}),
|
|
2712
3297
|
});
|
|
2713
|
-
const
|
|
3298
|
+
const flattenedRows = flattenManyToManyResult(
|
|
3299
|
+
tableName,
|
|
3300
|
+
rawRows,
|
|
3301
|
+
withValue,
|
|
3302
|
+
);
|
|
3303
|
+
const rows = Array.isArray(flattenedRows) ? flattenedRows : [];
|
|
2714
3304
|
const constrainedRows = hasAggregateWithConstraints(withValue)
|
|
2715
3305
|
? rows.filter((row) =>
|
|
2716
3306
|
rowMatchesAggregateWithConstraints(row, withValue),
|
|
@@ -2783,12 +3373,17 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
2783
3373
|
const transformedWith =
|
|
2784
3374
|
withValue === undefined
|
|
2785
3375
|
? undefined
|
|
2786
|
-
: transformWithRelations(withValue);
|
|
3376
|
+
: transformWithRelations(withValue, tableName);
|
|
2787
3377
|
const rawRows = await queryTable.findMany({
|
|
2788
3378
|
...(whereFilter ? { where: () => whereFilter } : {}),
|
|
2789
3379
|
...(transformedWith !== undefined ? { with: transformedWith } : {}),
|
|
2790
3380
|
});
|
|
2791
|
-
const
|
|
3381
|
+
const flattenedRows = flattenManyToManyResult(
|
|
3382
|
+
tableName,
|
|
3383
|
+
rawRows,
|
|
3384
|
+
withValue,
|
|
3385
|
+
);
|
|
3386
|
+
const rows = Array.isArray(flattenedRows) ? flattenedRows : [];
|
|
2792
3387
|
const constrainedRows = hasAggregateWithConstraints(withValue)
|
|
2793
3388
|
? rows.filter((row) =>
|
|
2794
3389
|
rowMatchesAggregateWithConstraints(row, withValue),
|
|
@@ -2846,7 +3441,7 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
2846
3441
|
},
|
|
2847
3442
|
}) as AppflareQueryDb;
|
|
2848
3443
|
}
|
|
2849
|
-
`}function
|
|
3444
|
+
`}function Ne(){return `export class AppflareHandledError extends Error {
|
|
2850
3445
|
public readonly status: number;
|
|
2851
3446
|
public readonly payload: unknown;
|
|
2852
3447
|
|
|
@@ -2856,7 +3451,7 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
2856
3451
|
this.payload = payload;
|
|
2857
3452
|
}
|
|
2858
3453
|
}
|
|
2859
|
-
`}function
|
|
3454
|
+
`}function $e(){return ` findMany: (args?: Record<string, unknown>) => {
|
|
2860
3455
|
const where = isRecord(args?.where)
|
|
2861
3456
|
? (args?.where as Record<string, unknown>)
|
|
2862
3457
|
: undefined;
|
|
@@ -2876,10 +3471,19 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
2876
3471
|
with: undefined,
|
|
2877
3472
|
aggregatePlan: undefined,
|
|
2878
3473
|
}
|
|
2879
|
-
: transformWithRelationsAndExtractAggregates(withValue);
|
|
3474
|
+
: transformWithRelationsAndExtractAggregates(withValue, tableName);
|
|
2880
3475
|
const transformedWith = transformedWithResult.with;
|
|
2881
3476
|
const aggregatePlan = transformedWithResult.aggregatePlan;
|
|
2882
|
-
|
|
3477
|
+
const requiresManyToManyFlatten = hasManyToManyRelationsInWith(
|
|
3478
|
+
tableName,
|
|
3479
|
+
withValue,
|
|
3480
|
+
);
|
|
3481
|
+
if (
|
|
3482
|
+
!whereFilter &&
|
|
3483
|
+
transformedWith === withValue &&
|
|
3484
|
+
!aggregatePlan &&
|
|
3485
|
+
!requiresManyToManyFlatten
|
|
3486
|
+
) {
|
|
2883
3487
|
return queryTable.findMany(passthroughArgs);
|
|
2884
3488
|
}
|
|
2885
3489
|
|
|
@@ -2889,13 +3493,22 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
2889
3493
|
...(transformedWith !== undefined ? { with: transformedWith } : {}),
|
|
2890
3494
|
});
|
|
2891
3495
|
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
3496
|
+
return queryPromise.then((result) => {
|
|
3497
|
+
const flattenedResult = flattenManyToManyResult(
|
|
3498
|
+
tableName,
|
|
3499
|
+
result,
|
|
3500
|
+
withValue,
|
|
3501
|
+
);
|
|
2895
3502
|
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
3503
|
+
if (!aggregatePlan) {
|
|
3504
|
+
return flattenedResult;
|
|
3505
|
+
}
|
|
3506
|
+
|
|
3507
|
+
return applyRelationAggregatePlanToResult(
|
|
3508
|
+
flattenedResult,
|
|
3509
|
+
aggregatePlan,
|
|
3510
|
+
);
|
|
3511
|
+
});
|
|
2899
3512
|
},
|
|
2900
3513
|
findFirst: (args?: Record<string, unknown>) => {
|
|
2901
3514
|
const where = isRecord(args?.where)
|
|
@@ -2917,10 +3530,19 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
2917
3530
|
with: undefined,
|
|
2918
3531
|
aggregatePlan: undefined,
|
|
2919
3532
|
}
|
|
2920
|
-
: transformWithRelationsAndExtractAggregates(withValue);
|
|
3533
|
+
: transformWithRelationsAndExtractAggregates(withValue, tableName);
|
|
2921
3534
|
const transformedWith = transformedWithResult.with;
|
|
2922
3535
|
const aggregatePlan = transformedWithResult.aggregatePlan;
|
|
2923
|
-
|
|
3536
|
+
const requiresManyToManyFlatten = hasManyToManyRelationsInWith(
|
|
3537
|
+
tableName,
|
|
3538
|
+
withValue,
|
|
3539
|
+
);
|
|
3540
|
+
if (
|
|
3541
|
+
!whereFilter &&
|
|
3542
|
+
transformedWith === withValue &&
|
|
3543
|
+
!aggregatePlan &&
|
|
3544
|
+
!requiresManyToManyFlatten
|
|
3545
|
+
) {
|
|
2924
3546
|
return queryTable.findFirst(passthroughArgs);
|
|
2925
3547
|
}
|
|
2926
3548
|
|
|
@@ -2930,15 +3552,24 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
2930
3552
|
...(transformedWith !== undefined ? { with: transformedWith } : {}),
|
|
2931
3553
|
});
|
|
2932
3554
|
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
3555
|
+
return queryPromise.then((result) => {
|
|
3556
|
+
const flattenedResult = flattenManyToManyResult(
|
|
3557
|
+
tableName,
|
|
3558
|
+
result,
|
|
3559
|
+
withValue,
|
|
3560
|
+
);
|
|
2936
3561
|
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
3562
|
+
if (!aggregatePlan) {
|
|
3563
|
+
return flattenedResult;
|
|
3564
|
+
}
|
|
3565
|
+
|
|
3566
|
+
return applyRelationAggregatePlanToResult(
|
|
3567
|
+
flattenedResult,
|
|
3568
|
+
aggregatePlan,
|
|
3569
|
+
);
|
|
3570
|
+
});
|
|
2940
3571
|
},
|
|
2941
|
-
`}function
|
|
3572
|
+
`}function qe(){return `export function createQueryDb(
|
|
2942
3573
|
$db: AppflareDb,
|
|
2943
3574
|
options?: QueryDbOptions,
|
|
2944
3575
|
): AppflareQueryDb {
|
|
@@ -2980,16 +3611,435 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
2980
3611
|
};
|
|
2981
3612
|
|
|
2982
3613
|
const tableApi = {
|
|
2983
|
-
`}function
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
3614
|
+
`}function Ce(){return ` insert: async (args: QueryInsertArgs<TableName>) => {
|
|
3615
|
+
const transaction = ($db as any).transaction;
|
|
3616
|
+
|
|
3617
|
+
const valuesArray = Array.isArray(args.values)
|
|
3618
|
+
? args.values
|
|
3619
|
+
: [args.values];
|
|
3620
|
+
const baseValuesArray: Array<Record<string, unknown>> = [];
|
|
3621
|
+
const postInsertRelations: Array<
|
|
3622
|
+
Array<{
|
|
3623
|
+
relationName: string;
|
|
3624
|
+
relation: RuntimeRelation;
|
|
3625
|
+
value: unknown;
|
|
3626
|
+
}>
|
|
3627
|
+
> = [];
|
|
3628
|
+
|
|
3629
|
+
const resolveSingularAlias = (relationName: string): string => {
|
|
3630
|
+
if (relationName.endsWith("ies")) {
|
|
3631
|
+
return relationName.slice(0, -3) + "yId";
|
|
3632
|
+
}
|
|
3633
|
+
if (relationName.endsWith("s") && relationName.length > 1) {
|
|
3634
|
+
return relationName.slice(0, -1) + "Id";
|
|
3635
|
+
}
|
|
3636
|
+
return relationName + "Id";
|
|
3637
|
+
};
|
|
3638
|
+
|
|
3639
|
+
const toRelationItems = (
|
|
3640
|
+
relation: RuntimeRelation,
|
|
3641
|
+
relationName: string,
|
|
3642
|
+
value: unknown,
|
|
3643
|
+
): unknown[] => {
|
|
3644
|
+
if (value === undefined || value === null) {
|
|
3645
|
+
return [];
|
|
3646
|
+
}
|
|
3647
|
+
|
|
3648
|
+
if (relation.kind === "one") {
|
|
3649
|
+
if (Array.isArray(value)) {
|
|
3650
|
+
throw new Error(
|
|
3651
|
+
"Relation '" +
|
|
3652
|
+
tableName +
|
|
3653
|
+
"." +
|
|
3654
|
+
relationName +
|
|
3655
|
+
"' expects a single value.",
|
|
3656
|
+
);
|
|
3657
|
+
}
|
|
3658
|
+
return [value];
|
|
3659
|
+
}
|
|
3660
|
+
|
|
3661
|
+
return Array.isArray(value) ? value : [value];
|
|
3662
|
+
};
|
|
3663
|
+
|
|
3664
|
+
const resolveRelationIdentifier = async (
|
|
3665
|
+
tx: any,
|
|
3666
|
+
relation: RuntimeRelation,
|
|
3667
|
+
relationName: string,
|
|
3668
|
+
input: unknown,
|
|
3669
|
+
): Promise<unknown> => {
|
|
3670
|
+
if (
|
|
3671
|
+
typeof input === "string" ||
|
|
3672
|
+
typeof input === "number" ||
|
|
3673
|
+
typeof input === "bigint"
|
|
3674
|
+
) {
|
|
3675
|
+
return input;
|
|
3676
|
+
}
|
|
3677
|
+
|
|
3678
|
+
if (!isRecord(input)) {
|
|
3679
|
+
throw new Error(
|
|
3680
|
+
"Relation '" +
|
|
3681
|
+
tableName +
|
|
3682
|
+
"." +
|
|
3683
|
+
relationName +
|
|
3684
|
+
"' expects an id or object payload.",
|
|
3685
|
+
);
|
|
3686
|
+
}
|
|
3687
|
+
|
|
3688
|
+
const referenceField =
|
|
3689
|
+
relation.kind === "manyToMany"
|
|
3690
|
+
? (relation.targetReferenceField ?? "id")
|
|
3691
|
+
: "id";
|
|
3692
|
+
const existingId = input[referenceField];
|
|
3693
|
+
if (existingId !== undefined && existingId !== null) {
|
|
3694
|
+
return existingId;
|
|
3695
|
+
}
|
|
2987
3696
|
|
|
2988
|
-
|
|
2989
|
-
|
|
3697
|
+
const targetTable = (mergedSchema as Record<string, unknown>)[
|
|
3698
|
+
relation.targetTable
|
|
3699
|
+
];
|
|
3700
|
+
if (!targetTable) {
|
|
3701
|
+
throw new Error(
|
|
3702
|
+
"Unknown target table '" +
|
|
3703
|
+
relation.targetTable +
|
|
3704
|
+
"' for relation '" +
|
|
3705
|
+
tableName +
|
|
3706
|
+
"." +
|
|
3707
|
+
relationName +
|
|
3708
|
+
"'.",
|
|
3709
|
+
);
|
|
3710
|
+
}
|
|
3711
|
+
|
|
3712
|
+
let createQuery: any = tx.insert(targetTable as any).values(input as any);
|
|
3713
|
+
if (typeof createQuery.returning === "function") {
|
|
3714
|
+
createQuery = createQuery.returning();
|
|
3715
|
+
}
|
|
3716
|
+
const createdRows = (await createQuery) as Array<Record<string, unknown>>;
|
|
3717
|
+
const created = createdRows[0];
|
|
3718
|
+
if (!created) {
|
|
3719
|
+
throw new Error(
|
|
3720
|
+
"Failed to create relation target for '" +
|
|
3721
|
+
tableName +
|
|
3722
|
+
"." +
|
|
3723
|
+
relationName +
|
|
3724
|
+
"'.",
|
|
3725
|
+
);
|
|
3726
|
+
}
|
|
3727
|
+
|
|
3728
|
+
const createdId = created[referenceField];
|
|
3729
|
+
if (createdId === undefined || createdId === null) {
|
|
3730
|
+
throw new Error(
|
|
3731
|
+
"Created relation target for '" +
|
|
3732
|
+
tableName +
|
|
3733
|
+
"." +
|
|
3734
|
+
relationName +
|
|
3735
|
+
"' is missing '" +
|
|
3736
|
+
referenceField +
|
|
3737
|
+
"'.",
|
|
3738
|
+
);
|
|
3739
|
+
}
|
|
3740
|
+
|
|
3741
|
+
return createdId;
|
|
3742
|
+
};
|
|
3743
|
+
|
|
3744
|
+
for (const inputValue of valuesArray) {
|
|
3745
|
+
const scalarValues: Record<string, unknown> = {};
|
|
3746
|
+
const relationInputs: Array<{
|
|
3747
|
+
relationName: string;
|
|
3748
|
+
relation: RuntimeRelation;
|
|
3749
|
+
value: unknown;
|
|
3750
|
+
}> = [];
|
|
3751
|
+
|
|
3752
|
+
const valueRecord = (inputValue ?? {}) as Record<string, unknown>;
|
|
3753
|
+
for (const [fieldName, fieldValue] of Object.entries(valueRecord)) {
|
|
3754
|
+
const runtimeRelation = getRuntimeRelation(tableName, fieldName);
|
|
3755
|
+
if (runtimeRelation) {
|
|
3756
|
+
relationInputs.push({
|
|
3757
|
+
relationName: fieldName,
|
|
3758
|
+
relation: runtimeRelation,
|
|
3759
|
+
value: fieldValue,
|
|
3760
|
+
});
|
|
3761
|
+
continue;
|
|
3762
|
+
}
|
|
3763
|
+
|
|
3764
|
+
let matchedAlias = false;
|
|
3765
|
+
if (fieldName.endsWith("Id")) {
|
|
3766
|
+
for (const [relationName, relationValue] of Object.entries(
|
|
3767
|
+
runtimeRelationMap[tableName] ?? {},
|
|
3768
|
+
)) {
|
|
3769
|
+
const pluralAlias = relationName + "Id";
|
|
3770
|
+
const singularAlias = resolveSingularAlias(relationName);
|
|
3771
|
+
if (fieldName !== pluralAlias && fieldName !== singularAlias) {
|
|
3772
|
+
continue;
|
|
3773
|
+
}
|
|
3774
|
+
|
|
3775
|
+
if (valueRecord[relationName] !== undefined) {
|
|
3776
|
+
throw new Error(
|
|
3777
|
+
"Insert payload for '" +
|
|
3778
|
+
tableName +
|
|
3779
|
+
"' cannot contain both '" +
|
|
3780
|
+
relationName +
|
|
3781
|
+
"' and '" +
|
|
3782
|
+
fieldName +
|
|
3783
|
+
"'.",
|
|
3784
|
+
);
|
|
3785
|
+
}
|
|
3786
|
+
|
|
3787
|
+
relationInputs.push({
|
|
3788
|
+
relationName,
|
|
3789
|
+
relation: relationValue,
|
|
3790
|
+
value: fieldValue,
|
|
3791
|
+
});
|
|
3792
|
+
matchedAlias = true;
|
|
3793
|
+
break;
|
|
3794
|
+
}
|
|
3795
|
+
}
|
|
3796
|
+
|
|
3797
|
+
if (!matchedAlias) {
|
|
3798
|
+
scalarValues[fieldName] = fieldValue;
|
|
3799
|
+
}
|
|
3800
|
+
}
|
|
3801
|
+
|
|
3802
|
+
baseValuesArray.push(scalarValues);
|
|
3803
|
+
postInsertRelations.push(relationInputs);
|
|
3804
|
+
}
|
|
3805
|
+
|
|
3806
|
+
const executeInsertGraph = async (tx: any): Promise<Array<TableModel<TableName>>> => {
|
|
3807
|
+
for (let index = 0; index < baseValuesArray.length; index += 1) {
|
|
3808
|
+
const relationInputs = postInsertRelations[index] ?? [];
|
|
3809
|
+
for (const relationInput of relationInputs) {
|
|
3810
|
+
if (relationInput.relation.kind !== "one") {
|
|
3811
|
+
continue;
|
|
3812
|
+
}
|
|
3813
|
+
|
|
3814
|
+
const sourceField = relationInput.relation.sourceField;
|
|
3815
|
+
if (!sourceField) {
|
|
3816
|
+
throw new Error(
|
|
3817
|
+
"Relation '" +
|
|
3818
|
+
tableName +
|
|
3819
|
+
"." +
|
|
3820
|
+
relationInput.relationName +
|
|
3821
|
+
"' is missing sourceField metadata.",
|
|
3822
|
+
);
|
|
3823
|
+
}
|
|
3824
|
+
|
|
3825
|
+
const oneItems = toRelationItems(
|
|
3826
|
+
relationInput.relation,
|
|
3827
|
+
relationInput.relationName,
|
|
3828
|
+
relationInput.value,
|
|
3829
|
+
);
|
|
3830
|
+
if (oneItems.length === 0) {
|
|
3831
|
+
continue;
|
|
3832
|
+
}
|
|
3833
|
+
|
|
3834
|
+
const relationId = await resolveRelationIdentifier(
|
|
3835
|
+
tx,
|
|
3836
|
+
relationInput.relation,
|
|
3837
|
+
relationInput.relationName,
|
|
3838
|
+
oneItems[0],
|
|
3839
|
+
);
|
|
3840
|
+
const existingValue = baseValuesArray[index][sourceField];
|
|
3841
|
+
if (
|
|
3842
|
+
existingValue !== undefined &&
|
|
3843
|
+
existingValue !== relationId
|
|
3844
|
+
) {
|
|
3845
|
+
throw new Error(
|
|
3846
|
+
"Insert payload for '" +
|
|
3847
|
+
tableName +
|
|
3848
|
+
"' has conflicting values for '" +
|
|
3849
|
+
sourceField +
|
|
3850
|
+
"'.",
|
|
3851
|
+
);
|
|
3852
|
+
}
|
|
3853
|
+
baseValuesArray[index][sourceField] = relationId;
|
|
3854
|
+
}
|
|
3855
|
+
}
|
|
3856
|
+
|
|
3857
|
+
let insertQuery: any = tx.insert(table as any).values(baseValuesArray as any);
|
|
3858
|
+
if (typeof insertQuery.returning === "function") {
|
|
3859
|
+
insertQuery = insertQuery.returning();
|
|
3860
|
+
}
|
|
3861
|
+
const insertedRows = (await insertQuery) as Array<TableModel<TableName>>;
|
|
3862
|
+
|
|
3863
|
+
for (let index = 0; index < insertedRows.length; index += 1) {
|
|
3864
|
+
const parentRow = insertedRows[index] as unknown as Record<string, unknown>;
|
|
3865
|
+
const relationInputs = postInsertRelations[index] ?? [];
|
|
3866
|
+
|
|
3867
|
+
for (const relationInput of relationInputs) {
|
|
3868
|
+
if (relationInput.relation.kind === "one") {
|
|
3869
|
+
continue;
|
|
3870
|
+
}
|
|
3871
|
+
|
|
3872
|
+
const sourceReferenceField = relationInput.relation.referenceField ?? "id";
|
|
3873
|
+
const parentReferenceValue = parentRow[sourceReferenceField];
|
|
3874
|
+
if (
|
|
3875
|
+
parentReferenceValue === undefined ||
|
|
3876
|
+
parentReferenceValue === null
|
|
3877
|
+
) {
|
|
3878
|
+
throw new Error(
|
|
3879
|
+
"Inserted row for '" +
|
|
3880
|
+
tableName +
|
|
3881
|
+
"' is missing '" +
|
|
3882
|
+
sourceReferenceField +
|
|
3883
|
+
"' required by relation '" +
|
|
3884
|
+
relationInput.relationName +
|
|
3885
|
+
"'.",
|
|
3886
|
+
);
|
|
3887
|
+
}
|
|
3888
|
+
|
|
3889
|
+
const relationItems = toRelationItems(
|
|
3890
|
+
relationInput.relation,
|
|
3891
|
+
relationInput.relationName,
|
|
3892
|
+
relationInput.value,
|
|
3893
|
+
);
|
|
3894
|
+
if (relationItems.length === 0) {
|
|
3895
|
+
continue;
|
|
3896
|
+
}
|
|
3897
|
+
|
|
3898
|
+
if (relationInput.relation.kind === "many") {
|
|
3899
|
+
const targetTable = (mergedSchema as Record<string, unknown>)[
|
|
3900
|
+
relationInput.relation.targetTable
|
|
3901
|
+
];
|
|
3902
|
+
if (!targetTable) {
|
|
3903
|
+
throw new Error(
|
|
3904
|
+
"Unknown target table '" +
|
|
3905
|
+
relationInput.relation.targetTable +
|
|
3906
|
+
"' for relation '" +
|
|
3907
|
+
tableName +
|
|
3908
|
+
"." +
|
|
3909
|
+
relationInput.relationName +
|
|
3910
|
+
"'.",
|
|
3911
|
+
);
|
|
3912
|
+
}
|
|
3913
|
+
|
|
3914
|
+
const sourceField = relationInput.relation.sourceField;
|
|
3915
|
+
if (!sourceField) {
|
|
3916
|
+
throw new Error(
|
|
3917
|
+
"Relation '" +
|
|
3918
|
+
tableName +
|
|
3919
|
+
"." +
|
|
3920
|
+
relationInput.relationName +
|
|
3921
|
+
"' is missing sourceField metadata.",
|
|
3922
|
+
);
|
|
3923
|
+
}
|
|
3924
|
+
|
|
3925
|
+
for (const relationItem of relationItems) {
|
|
3926
|
+
if (
|
|
3927
|
+
typeof relationItem === "string" ||
|
|
3928
|
+
typeof relationItem === "number" ||
|
|
3929
|
+
typeof relationItem === "bigint"
|
|
3930
|
+
) {
|
|
3931
|
+
await tx
|
|
3932
|
+
.update(targetTable as any)
|
|
3933
|
+
.set({ [sourceField]: parentReferenceValue } as any)
|
|
3934
|
+
.where(eq((targetTable as any).id, relationItem as any));
|
|
3935
|
+
continue;
|
|
3936
|
+
}
|
|
3937
|
+
|
|
3938
|
+
if (!isRecord(relationItem)) {
|
|
3939
|
+
throw new Error(
|
|
3940
|
+
"Relation '" +
|
|
3941
|
+
tableName +
|
|
3942
|
+
"." +
|
|
3943
|
+
relationInput.relationName +
|
|
3944
|
+
"' expects id or object payloads.",
|
|
3945
|
+
);
|
|
3946
|
+
}
|
|
3947
|
+
|
|
3948
|
+
const existingId = relationItem.id;
|
|
3949
|
+
const payload = {
|
|
3950
|
+
...relationItem,
|
|
3951
|
+
[sourceField]: parentReferenceValue,
|
|
3952
|
+
};
|
|
3953
|
+
|
|
3954
|
+
if (existingId !== undefined && existingId !== null) {
|
|
3955
|
+
const { id: _ignored, ...setPayload } = payload;
|
|
3956
|
+
await tx
|
|
3957
|
+
.update(targetTable as any)
|
|
3958
|
+
.set(setPayload as any)
|
|
3959
|
+
.where(eq((targetTable as any).id, existingId as any));
|
|
3960
|
+
continue;
|
|
3961
|
+
}
|
|
3962
|
+
|
|
3963
|
+
await tx.insert(targetTable as any).values(payload as any);
|
|
3964
|
+
}
|
|
3965
|
+
continue;
|
|
3966
|
+
}
|
|
3967
|
+
|
|
3968
|
+
const junctionTable = (mergedSchema as Record<string, unknown>)[
|
|
3969
|
+
relationInput.relation.junctionTable
|
|
3970
|
+
];
|
|
3971
|
+
if (!junctionTable) {
|
|
3972
|
+
throw new Error(
|
|
3973
|
+
"Unknown junction table '" +
|
|
3974
|
+
relationInput.relation.junctionTable +
|
|
3975
|
+
"' for relation '" +
|
|
3976
|
+
tableName +
|
|
3977
|
+
"." +
|
|
3978
|
+
relationInput.relationName +
|
|
3979
|
+
"'.",
|
|
3980
|
+
);
|
|
3981
|
+
}
|
|
3982
|
+
|
|
3983
|
+
const sourceField = relationInput.relation.sourceField;
|
|
3984
|
+
const targetField = relationInput.relation.targetField;
|
|
3985
|
+
if (!sourceField || !targetField) {
|
|
3986
|
+
throw new Error(
|
|
3987
|
+
"Relation '" +
|
|
3988
|
+
tableName +
|
|
3989
|
+
"." +
|
|
3990
|
+
relationInput.relationName +
|
|
3991
|
+
"' is missing junction metadata fields.",
|
|
3992
|
+
);
|
|
3993
|
+
}
|
|
3994
|
+
|
|
3995
|
+
const linkValues: Array<Record<string, unknown>> = [];
|
|
3996
|
+
for (const relationItem of relationItems) {
|
|
3997
|
+
const targetId = await resolveRelationIdentifier(
|
|
3998
|
+
tx,
|
|
3999
|
+
relationInput.relation,
|
|
4000
|
+
relationInput.relationName,
|
|
4001
|
+
relationItem,
|
|
4002
|
+
);
|
|
4003
|
+
|
|
4004
|
+
linkValues.push({
|
|
4005
|
+
[sourceField]: parentReferenceValue,
|
|
4006
|
+
[targetField]: targetId,
|
|
4007
|
+
});
|
|
4008
|
+
}
|
|
4009
|
+
|
|
4010
|
+
if (linkValues.length > 0) {
|
|
4011
|
+
await tx.insert(junctionTable as any).values(linkValues as any);
|
|
4012
|
+
}
|
|
4013
|
+
}
|
|
4014
|
+
}
|
|
4015
|
+
|
|
4016
|
+
return insertedRows;
|
|
4017
|
+
};
|
|
4018
|
+
|
|
4019
|
+
let rows: Array<TableModel<TableName>>;
|
|
4020
|
+
if (typeof transaction === "function") {
|
|
4021
|
+
try {
|
|
4022
|
+
rows = await transaction.call($db, (tx: any) =>
|
|
4023
|
+
executeInsertGraph(tx),
|
|
4024
|
+
);
|
|
4025
|
+
} catch (error) {
|
|
4026
|
+
const message =
|
|
4027
|
+
error instanceof Error ? error.message : String(error);
|
|
4028
|
+
const lowered = message.toLowerCase();
|
|
4029
|
+
if (
|
|
4030
|
+
lowered.includes("failed query: begin") ||
|
|
4031
|
+
lowered.includes('near "begin"') ||
|
|
4032
|
+
lowered.includes("cannot start a transaction")
|
|
4033
|
+
) {
|
|
4034
|
+
rows = await executeInsertGraph($db as any);
|
|
4035
|
+
} else {
|
|
4036
|
+
throw error;
|
|
4037
|
+
}
|
|
4038
|
+
}
|
|
4039
|
+
} else {
|
|
4040
|
+
rows = await executeInsertGraph($db as any);
|
|
2990
4041
|
}
|
|
2991
4042
|
|
|
2992
|
-
const rows = (await insertQuery) as Array<TableModel<TableName>>;
|
|
2993
4043
|
emitMutation(
|
|
2994
4044
|
"insert",
|
|
2995
4045
|
{ values: args.values as unknown as Record<string, unknown> },
|
|
@@ -3114,9 +4164,9 @@ type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
|
3114
4164
|
);
|
|
3115
4165
|
return rows;
|
|
3116
4166
|
},
|
|
3117
|
-
`}function
|
|
4167
|
+
`}function Me(){return [qe(),$e(),Ce(),Ae(),Ne()].join(`
|
|
3118
4168
|
|
|
3119
|
-
`)}function
|
|
4169
|
+
`)}function Pe(){return `type AuthSession = typeof auth.$Infer.Session;
|
|
3120
4170
|
type User = AuthSession['user']
|
|
3121
4171
|
type Session = AuthSession['session']
|
|
3122
4172
|
|
|
@@ -3177,7 +4227,7 @@ export type AppflareContext = {
|
|
|
3177
4227
|
storage: AppflareStorage;
|
|
3178
4228
|
error: (status: number, message: string, details?: unknown) => never;
|
|
3179
4229
|
};
|
|
3180
|
-
`}function
|
|
4230
|
+
`}function Ie(){return `type InferOperationArgs<TShape extends ZodRawShape> = z.output<z.ZodObject<TShape>>;
|
|
3181
4231
|
|
|
3182
4232
|
export type SchedulerEnqueueOptions = {
|
|
3183
4233
|
delaySeconds?: number;
|
|
@@ -3309,22 +4359,22 @@ export function cron(definition: CronDefinition): RegisteredCron {
|
|
|
3309
4359
|
definition,
|
|
3310
4360
|
};
|
|
3311
4361
|
}
|
|
3312
|
-
`}function
|
|
4362
|
+
`}function De(){return [xe(),Se(),Me(),Pe(),Ie()].join(`
|
|
3313
4363
|
|
|
3314
|
-
`)}function
|
|
4364
|
+
`)}function Ee(e){return `import type { Context } from "hono";
|
|
3315
4365
|
import type { D1Database } from "@cloudflare/workers-types";
|
|
3316
4366
|
import { drizzle } from "drizzle-orm/d1";
|
|
3317
4367
|
import { z, type ZodRawShape } from "zod";
|
|
3318
4368
|
import * as authSchema from "./auth.schema";
|
|
3319
|
-
import * as schema from "${
|
|
4369
|
+
import * as schema from "${e}";
|
|
3320
4370
|
|
|
3321
|
-
${
|
|
3322
|
-
`}function
|
|
3323
|
-
`)}function
|
|
3324
|
-
`)}function
|
|
3325
|
-
`)}function
|
|
4371
|
+
${De()}
|
|
4372
|
+
`}function On(e){let t=e.replace(/[^A-Za-z0-9_]/g,"_");return /^[0-9]/.test(t)?`_${t}`:t}function Fn(e,t){let n=e.routePath.replace(/^\//,"").replace(/\//g,"_");return On(`op_${t}_${n}`)}function jn(e){return e.map((t,n)=>({operation:t,index:n,alias:Fn(t,n)}))}function Vn(e){return e.map(({operation:t,alias:n})=>`import { ${t.exportName} as ${n} } from "${t.importPath}";`).join(`
|
|
4373
|
+
`)}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(`
|
|
4374
|
+
`)}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(`
|
|
4375
|
+
`)}function Wn(e){return e.filter(({operation:t})=>t.kind==="query").map(({operation:t,alias:n})=>{let r=`${n}Schema`;return `
|
|
3326
4376
|
app.get(
|
|
3327
|
-
"${
|
|
4377
|
+
"${t.routePath}",
|
|
3328
4378
|
sValidator("query", ${r}),
|
|
3329
4379
|
async (c) => {
|
|
3330
4380
|
const ctx = await createExecutionContext(c, options);
|
|
@@ -3335,9 +4385,9 @@ ${qt()}
|
|
|
3335
4385
|
}
|
|
3336
4386
|
},
|
|
3337
4387
|
);`}).join(`
|
|
3338
|
-
`)}function
|
|
4388
|
+
`)}function Ln(e){return e.filter(({operation:t})=>t.kind==="mutation").map(({operation:t,alias:n})=>{let r=`${n}Schema`;return `
|
|
3339
4389
|
app.post(
|
|
3340
|
-
"${
|
|
4390
|
+
"${t.routePath}",
|
|
3341
4391
|
sValidator("json", ${r}),
|
|
3342
4392
|
async (c) => {
|
|
3343
4393
|
const ctx = await createExecutionContext(c, options);
|
|
@@ -3350,26 +4400,26 @@ ${qt()}
|
|
|
3350
4400
|
}
|
|
3351
4401
|
},
|
|
3352
4402
|
);`}).join(`
|
|
3353
|
-
`)}function
|
|
4403
|
+
`)}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 `
|
|
3354
4404
|
${JSON.stringify(a)}: {
|
|
3355
4405
|
definition: ${n}.definition,
|
|
3356
4406
|
schema: ${r},
|
|
3357
4407
|
},`}).join(`
|
|
3358
|
-
`)}function
|
|
4408
|
+
`)}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 `
|
|
3359
4409
|
${JSON.stringify(a)}: {
|
|
3360
4410
|
definition: ${n}.definition,
|
|
3361
4411
|
schema: ${r},
|
|
3362
4412
|
},`}).join(`
|
|
3363
|
-
`)}function
|
|
3364
|
-
`)}function
|
|
4413
|
+
`)}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(`
|
|
4414
|
+
`)}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 `
|
|
3365
4415
|
{
|
|
3366
4416
|
taskName: ${JSON.stringify(r)},
|
|
3367
4417
|
cronTriggers: ${JSON.stringify(a)},
|
|
3368
4418
|
definition: ${n}.definition,
|
|
3369
4419
|
},`}).join(`
|
|
3370
|
-
`)}function
|
|
3371
|
-
${
|
|
3372
|
-
`)}function
|
|
4420
|
+
`)}function Kn(e){return e.filter(({operation:t})=>t.kind==="storage").map(({alias:t})=>`
|
|
4421
|
+
${t}.definition.handler,`).join(`
|
|
4422
|
+
`)}function Oe(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 Fe=`
|
|
3373
4423
|
function getRealtimeStub(
|
|
3374
4424
|
env: Record<string, unknown>,
|
|
3375
4425
|
options: RegisterHandlersOptions,
|
|
@@ -3443,7 +4493,7 @@ function buildRealtimeWsUrl(requestUrl: string, websocketPath: string): string {
|
|
|
3443
4493
|
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
3444
4494
|
return url.toString();
|
|
3445
4495
|
}
|
|
3446
|
-
`;var
|
|
4496
|
+
`;var je=`
|
|
3447
4497
|
export class AppflareRealtimeDurableObject {
|
|
3448
4498
|
private readonly subscriptions = new Map<string, RealtimeSubscription>();
|
|
3449
4499
|
private readonly sockets = new Map<string, WebSocket>();
|
|
@@ -3586,7 +4636,7 @@ export class AppflareRealtimeDurableObject {
|
|
|
3586
4636
|
return new Response("Not found", { status: 404 });
|
|
3587
4637
|
}
|
|
3588
4638
|
}
|
|
3589
|
-
`;var
|
|
4639
|
+
`;var Ve=`
|
|
3590
4640
|
async function publishMutationEvents(
|
|
3591
4641
|
c: { req: { raw: Request }; env: Record<string, unknown> },
|
|
3592
4642
|
options: RegisterHandlersOptions,
|
|
@@ -3687,7 +4737,7 @@ async function publishMutationEvents(
|
|
|
3687
4737
|
}
|
|
3688
4738
|
}
|
|
3689
4739
|
}
|
|
3690
|
-
`;var
|
|
4740
|
+
`;var Be=`
|
|
3691
4741
|
function registerRealtimeRoutes(
|
|
3692
4742
|
app: Hono<WorkerEnv>,
|
|
3693
4743
|
options: RegisterHandlersOptions,
|
|
@@ -3850,7 +4900,7 @@ function registerRealtimeRoutes(
|
|
|
3850
4900
|
return stub.fetch(c.req.raw);
|
|
3851
4901
|
});
|
|
3852
4902
|
}
|
|
3853
|
-
`;var
|
|
4903
|
+
`;var He=`
|
|
3854
4904
|
type RealtimeSubscription = {
|
|
3855
4905
|
token: string;
|
|
3856
4906
|
signature: string;
|
|
@@ -3879,7 +4929,7 @@ type RealtimeDurableObjectNamespace = {
|
|
|
3879
4929
|
type RealtimeQueryName = keyof typeof realtimeQueryHandlers extends never
|
|
3880
4930
|
? string
|
|
3881
4931
|
: Extract<keyof typeof realtimeQueryHandlers, string>;
|
|
3882
|
-
`;var
|
|
4932
|
+
`;var We=`
|
|
3883
4933
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
3884
4934
|
return typeof value === "object" && value !== null;
|
|
3885
4935
|
}
|
|
@@ -4394,9 +5444,9 @@ function doesSubscriptionMatchMutation(
|
|
|
4394
5444
|
|
|
4395
5445
|
return false;
|
|
4396
5446
|
}
|
|
4397
|
-
`;var
|
|
5447
|
+
`;var Le=[He,We,Fe,Ve,Be,je].join(`
|
|
4398
5448
|
|
|
4399
|
-
`);var
|
|
5449
|
+
`);var ze=`
|
|
4400
5450
|
function parseExpiresIn(value: string | undefined): number | undefined {
|
|
4401
5451
|
if (!value) {
|
|
4402
5452
|
return undefined;
|
|
@@ -4589,7 +5639,7 @@ export function registerGeneratedStorageRoutes(
|
|
|
4589
5639
|
}
|
|
4590
5640
|
});
|
|
4591
5641
|
}
|
|
4592
|
-
`;var
|
|
5642
|
+
`;var Ue=`
|
|
4593
5643
|
type SchedulerTaskName = keyof typeof schedulerHandlers extends never
|
|
4594
5644
|
? string
|
|
4595
5645
|
: keyof typeof schedulerHandlers;
|
|
@@ -4644,7 +5694,7 @@ export async function executeScheduledBatch(
|
|
|
4644
5694
|
}
|
|
4645
5695
|
}
|
|
4646
5696
|
}
|
|
4647
|
-
`;var
|
|
5697
|
+
`;var Qe=`
|
|
4648
5698
|
export async function executeCronTriggers(
|
|
4649
5699
|
controller: { cron: string },
|
|
4650
5700
|
env: Record<string, unknown>,
|
|
@@ -4673,7 +5723,7 @@ export async function executeCronTriggers(
|
|
|
4673
5723
|
}
|
|
4674
5724
|
}
|
|
4675
5725
|
}
|
|
4676
|
-
`;function
|
|
5726
|
+
`;function _e(e){let{imports:t,operationSchemas:n,schedulerSchemas:r,queryRoutes:a,mutationRoutes:o,queryRegistryEntries:i,schedulerEntries:s,schedulerPayloadMapEntries:l,cronEntries:u,storageHandlersEntries:c}=Oe(e);return `import { sValidator } from "@hono/standard-validator";
|
|
4677
5727
|
import type { Hono } from "hono";
|
|
4678
5728
|
import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@cloudflare/workers-types";
|
|
4679
5729
|
import { ZodError, z } from "zod";
|
|
@@ -4690,8 +5740,8 @@ import {
|
|
|
4690
5740
|
} from "./handlers";
|
|
4691
5741
|
import { createExecutionContext, createSchedulerExecutionContext, resolveSession } from "./handlers.context";
|
|
4692
5742
|
import { executeOperation, handleOperationError } from "./handlers.execution";
|
|
4693
|
-
${
|
|
4694
|
-
${
|
|
5743
|
+
${t?`
|
|
5744
|
+
${t}`:""}
|
|
4695
5745
|
|
|
4696
5746
|
${n}
|
|
4697
5747
|
${r}
|
|
@@ -4712,19 +5762,19 @@ declare global {
|
|
|
4712
5762
|
interface AppflareSchedulerHandlerMap extends GeneratedSchedulerPayloadMap {}
|
|
4713
5763
|
}
|
|
4714
5764
|
|
|
4715
|
-
const cronHandlers = [${
|
|
5765
|
+
const cronHandlers = [${u||`
|
|
4716
5766
|
`}
|
|
4717
5767
|
] as const;
|
|
4718
5768
|
|
|
4719
|
-
const storageHandlers = [${
|
|
5769
|
+
const storageHandlers = [${c||`
|
|
4720
5770
|
`}
|
|
4721
5771
|
] as const;
|
|
4722
5772
|
|
|
4723
5773
|
setStorageHandlers([...storageHandlers]);
|
|
4724
5774
|
|
|
4725
|
-
${
|
|
5775
|
+
${Ue}
|
|
4726
5776
|
|
|
4727
|
-
${
|
|
5777
|
+
${Le}
|
|
4728
5778
|
|
|
4729
5779
|
export function registerGeneratedHandlers(
|
|
4730
5780
|
app: Hono<WorkerEnv>,
|
|
@@ -4737,20 +5787,20 @@ export function registerGeneratedHandlers(
|
|
|
4737
5787
|
`}
|
|
4738
5788
|
}
|
|
4739
5789
|
|
|
4740
|
-
${
|
|
5790
|
+
${ze}
|
|
4741
5791
|
|
|
4742
|
-
${
|
|
4743
|
-
`}function
|
|
4744
|
-
KV: c.env["${
|
|
4745
|
-
DATABASE: c.env["${
|
|
4746
|
-
}`}function
|
|
5792
|
+
${Qe}
|
|
5793
|
+
`}function H(e,t,n){let r=Ee(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?`,
|
|
5794
|
+
KV: c.env["${e}"] as KVNamespace`:""}function Ke(e,t){return `{
|
|
5795
|
+
DATABASE: c.env["${e}"] as D1Database${Gn(t)}
|
|
5796
|
+
}`}function Ge(e,t,n){return `app.on(["GET", "POST"], "${e}/*", async (c) => {
|
|
4747
5797
|
const auth = createAuth(
|
|
4748
|
-
${
|
|
5798
|
+
${Ke(t,n)},
|
|
4749
5799
|
c.req.raw.cf as IncomingRequestCfProperties | undefined,
|
|
4750
5800
|
);
|
|
4751
5801
|
return auth.handler(getSanitizedRequest(c.req.raw));
|
|
4752
5802
|
});
|
|
4753
|
-
`}function
|
|
5803
|
+
`}function Jn(){return `export const getHeaders = (headers: Headers) => {
|
|
4754
5804
|
const newHeaders = Object.fromEntries(headers as any);
|
|
4755
5805
|
const headerObject: Record<string, any> = {};
|
|
4756
5806
|
let hasCookie = false;
|
|
@@ -4780,15 +5830,15 @@ ${Vt}
|
|
|
4780
5830
|
|
|
4781
5831
|
return headerObject as any as Headers;
|
|
4782
5832
|
};
|
|
4783
|
-
`}function
|
|
5833
|
+
`}function Zn(){return `export const getSanitizedRequest = (req: Request) => {
|
|
4784
5834
|
const newRequest = new Request(req, {
|
|
4785
5835
|
headers: getHeaders(req.headers),
|
|
4786
5836
|
});
|
|
4787
5837
|
return newRequest;
|
|
4788
5838
|
};
|
|
4789
|
-
`}function
|
|
4790
|
-
`+
|
|
4791
|
-
`+
|
|
5839
|
+
`}function Je(){return Jn()+`
|
|
5840
|
+
`+Zn()}function Ze(e,t,n){return Ge(e,t,n)+`
|
|
5841
|
+
`+Je()}function Ye(){return `const app = new Hono<WorkerEnv>();
|
|
4792
5842
|
|
|
4793
5843
|
app.use('*', cors({
|
|
4794
5844
|
origin: (origin, c) => {
|
|
@@ -4804,7 +5854,7 @@ app.use('*', cors({
|
|
|
4804
5854
|
},
|
|
4805
5855
|
credentials: true
|
|
4806
5856
|
}));
|
|
4807
|
-
`}function
|
|
5857
|
+
`}function Xe(){return `export { AppflareRealtimeDurableObject };
|
|
4808
5858
|
|
|
4809
5859
|
export default {
|
|
4810
5860
|
fetch: app.fetch,
|
|
@@ -4815,42 +5865,42 @@ export default {
|
|
|
4815
5865
|
await executeCronTriggers(controller, env, generatedHandlerOptions);
|
|
4816
5866
|
},
|
|
4817
5867
|
};
|
|
4818
|
-
`}function
|
|
4819
|
-
kvBinding: "${
|
|
4820
|
-
r2Binding: "${r}",`:"",
|
|
5868
|
+
`}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?`
|
|
5869
|
+
kvBinding: "${t}",`:"",c=r?`
|
|
5870
|
+
r2Binding: "${r}",`:"",f=`
|
|
4821
5871
|
realtimeBinding: "${a}",
|
|
4822
5872
|
realtimeObjectName: "${o}",
|
|
4823
5873
|
realtimeSubscribePath: "${i}",
|
|
4824
5874
|
realtimeWebsocketPath: "${s}",
|
|
4825
5875
|
realtimeProtocol: "${l}",`;return `const generatedHandlerOptions = {
|
|
4826
|
-
databaseBinding: "${
|
|
4827
|
-
schedulerBinding: "${n}",${
|
|
5876
|
+
databaseBinding: "${e}",${u}
|
|
5877
|
+
schedulerBinding: "${n}",${c}${f}
|
|
4828
5878
|
};
|
|
4829
5879
|
registerGeneratedHandlers(app, generatedHandlerOptions);
|
|
4830
5880
|
registerGeneratedStorageRoutes(app, generatedHandlerOptions);
|
|
4831
5881
|
registerAdminDashboard(app, generatedHandlerOptions);
|
|
4832
|
-
`}function
|
|
5882
|
+
`}function tt(){return `import { createAuth } from "./auth.config";
|
|
4833
5883
|
import { AppflareRealtimeDurableObject, executeCronTriggers, executeScheduledBatch, registerGeneratedHandlers, registerGeneratedStorageRoutes } from "./handlers.routes";
|
|
4834
5884
|
import { registerAdminDashboard } from "./admin.routes";
|
|
4835
5885
|
import { Hono } from "hono";
|
|
4836
5886
|
import { cors } from "hono/cors";
|
|
4837
5887
|
import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@cloudflare/workers-types";
|
|
4838
|
-
`}function
|
|
5888
|
+
`}function nt(){return `type WorkerEnv = {
|
|
4839
5889
|
Bindings: Record<string, unknown>;
|
|
4840
5890
|
};
|
|
4841
|
-
`}function
|
|
5891
|
+
`}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">
|
|
4842
5892
|
<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">
|
|
4843
5893
|
<iconify-icon icon="mdi:account-group" width="16" height="16" class="opacity-50 shrink-0"></iconify-icon>
|
|
4844
5894
|
<span class="truncate">users</span>
|
|
4845
5895
|
</a>
|
|
4846
5896
|
</li>
|
|
4847
|
-
${
|
|
5897
|
+
${e.map(n=>`<li data-name="${n.tableName}">
|
|
4848
5898
|
<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">
|
|
4849
5899
|
<iconify-icon icon="mdi:table" width="16" height="16" class="opacity-50 shrink-0"></iconify-icon>
|
|
4850
5900
|
<span class="truncate">${n.tableName}</span>
|
|
4851
5901
|
</a>
|
|
4852
5902
|
</li>`).join(`
|
|
4853
|
-
`)}`}function
|
|
5903
|
+
`)}`}function lt(e){let t=e.filter(o=>o.kind==="query"),n=e.filter(o=>o.kind==="mutation"),r=t.map(o=>`
|
|
4854
5904
|
<li data-name="${o.exportName}">
|
|
4855
5905
|
<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">
|
|
4856
5906
|
<iconify-icon icon="solar:reorder-linear" width="16" height="16" class="opacity-50 shrink-0"></iconify-icon>
|
|
@@ -4878,15 +5928,15 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
4878
5928
|
</div>
|
|
4879
5929
|
</div>
|
|
4880
5930
|
<nav class="flex-1 overflow-y-auto px-2 pb-4">
|
|
4881
|
-
${
|
|
5931
|
+
${t.length>0?`<p class="text-[9px] font-bold uppercase tracking-wider opacity-25 mt-4 mb-1 px-2">Queries</p>
|
|
4882
5932
|
<ul class="flex flex-col gap-0.5">${r}</ul>`:""}
|
|
4883
5933
|
${n.length>0?`<p class="text-[9px] font-bold uppercase tracking-wider opacity-25 mt-4 mb-1 px-2">Mutations</p>
|
|
4884
5934
|
<ul class="flex flex-col gap-0.5">${a}</ul>`:""}
|
|
4885
5935
|
</nav>
|
|
4886
5936
|
</div>
|
|
4887
|
-
`}function
|
|
5937
|
+
`}function ct(e){return e.map(t=>`
|
|
4888
5938
|
<a
|
|
4889
|
-
href="/admin/table/${
|
|
5939
|
+
href="/admin/table/${t.exportName}"
|
|
4890
5940
|
class="card bg-base-100 border border-base-200 hover:border-primary/30 hover:shadow-md transition-all cursor-pointer group"
|
|
4891
5941
|
>
|
|
4892
5942
|
<div class="card-body p-5">
|
|
@@ -4895,18 +5945,18 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
4895
5945
|
<iconify-icon icon="mdi:table" width="20" height="20" class="text-primary"></iconify-icon>
|
|
4896
5946
|
</div>
|
|
4897
5947
|
<div>
|
|
4898
|
-
<h2 class="font-semibold text-sm capitalize group-hover:text-primary transition-colors">${
|
|
5948
|
+
<h2 class="font-semibold text-sm capitalize group-hover:text-primary transition-colors">${t.tableName}</h2>
|
|
4899
5949
|
<p class="text-xs opacity-40 mt-0.5">Manage records</p>
|
|
4900
5950
|
</div>
|
|
4901
5951
|
</div>
|
|
4902
5952
|
</div>
|
|
4903
5953
|
</a>
|
|
4904
|
-
`.replace(/\n/g,"\\n")).join("")}function
|
|
4905
|
-
try { searchConditions.push(like(tableSchema.${
|
|
4906
|
-
`).join("")}function
|
|
5954
|
+
`.replace(/\n/g,"\\n")).join("")}function ut(e){return e.columns.filter(t=>t.type==="string").map(t=>`
|
|
5955
|
+
try { searchConditions.push(like(tableSchema.${t.name}, \`%\${search}%\`)); } catch (e) {}
|
|
5956
|
+
`).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 `
|
|
4907
5957
|
<th>
|
|
4908
5958
|
<a href="#"
|
|
4909
|
-
hx-get="/admin/table/${
|
|
5959
|
+
hx-get="/admin/table/${e.exportName}?page=\${page}&search=\${search}&sort=${n}&order=\${sort === '${n}' && order === 'asc' ? 'desc' : 'asc'}"
|
|
4910
5960
|
hx-target="#main-content"
|
|
4911
5961
|
hx-push-url="true"
|
|
4912
5962
|
class="hover:text-primary flex items-center gap-1.5 transition-colors whitespace-nowrap">
|
|
@@ -4915,22 +5965,22 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
4915
5965
|
<span class="text-[10px] opacity-30">\${sort === '${n}' ? (order === 'asc' ? '\u25B2' : '\u25BC') : ''}</span>
|
|
4916
5966
|
</a>
|
|
4917
5967
|
</th>
|
|
4918
|
-
`}).join("")}function
|
|
5968
|
+
`}).join("")}function pt(e){return e.map(t=>`<td><div class="truncate max-w-[200px] text-sm" title="\${String((row as any).${t} ?? '')}">\${String((row as any).${t} ?? '')}</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"?`
|
|
4919
5969
|
<div class="form-control">
|
|
4920
5970
|
<label class="label cursor-pointer justify-start gap-3">
|
|
4921
|
-
<input type="checkbox" name="${
|
|
4922
|
-
<span class="label-text text-sm">${
|
|
5971
|
+
<input type="checkbox" name="${t}" value="true" class="checkbox checkbox-sm checkbox-primary" \${(row as any).${t} ? 'checked' : ''} />
|
|
5972
|
+
<span class="label-text text-sm">${t}</span>
|
|
4923
5973
|
</label>
|
|
4924
5974
|
</div>
|
|
4925
5975
|
`:`
|
|
4926
5976
|
<div class="form-control">
|
|
4927
5977
|
<label class="label cursor-pointer justify-start gap-3">
|
|
4928
|
-
<input type="checkbox" name="${
|
|
4929
|
-
<span class="label-text text-sm">${
|
|
5978
|
+
<input type="checkbox" name="${t}" value="true" class="checkbox checkbox-sm checkbox-primary" />
|
|
5979
|
+
<span class="label-text text-sm">${t}</span>
|
|
4930
5980
|
</label>
|
|
4931
5981
|
</div>
|
|
4932
5982
|
`;if(n==="edit"){let i=r.type==="date"?`\${(() => {
|
|
4933
|
-
const value = (row as any).${
|
|
5983
|
+
const value = (row as any).${t};
|
|
4934
5984
|
if (value == null || value === '') return '';
|
|
4935
5985
|
|
|
4936
5986
|
const date =
|
|
@@ -4943,17 +5993,17 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
4943
5993
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
4944
5994
|
const day = String(date.getDate()).padStart(2, '0');
|
|
4945
5995
|
return String(year) + '-' + month + '-' + day;
|
|
4946
|
-
})()}`:`\${String((row as any).${
|
|
5996
|
+
})()}`:`\${String((row as any).${t} ?? '')}`;return `
|
|
4947
5997
|
<div class="form-control">
|
|
4948
|
-
<label class="label"><span class="label-text text-sm font-medium">${
|
|
4949
|
-
<input type="${o}" name="${
|
|
5998
|
+
<label class="label"><span class="label-text text-sm font-medium">${t}</span></label>
|
|
5999
|
+
<input type="${o}" name="${t}" class="input input-bordered w-full text-sm" value="${i}"${a} />
|
|
4950
6000
|
</div>
|
|
4951
6001
|
`}return `
|
|
4952
6002
|
<div class="form-control">
|
|
4953
|
-
<label class="label"><span class="label-text text-sm font-medium">${
|
|
4954
|
-
<input type="${o}" name="${
|
|
6003
|
+
<label class="label"><span class="label-text text-sm font-medium">${t}</span></label>
|
|
6004
|
+
<input type="${o}" name="${t}" class="input input-bordered w-full text-sm"${a} />
|
|
4955
6005
|
</div>
|
|
4956
|
-
`}function
|
|
6006
|
+
`}function z(e,t){return t.map(n=>{let r=e.columns.find(o=>o.name===n);if(!r)return "";let a=r.optional?"":`
|
|
4957
6007
|
if (raw_${n} === '') {
|
|
4958
6008
|
return c.text('${n} is required', 400);
|
|
4959
6009
|
}
|
|
@@ -4998,19 +6048,19 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
4998
6048
|
payload.${n} = raw_${n};
|
|
4999
6049
|
}
|
|
5000
6050
|
`}).join(`
|
|
5001
|
-
`)}function
|
|
6051
|
+
`)}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">
|
|
5002
6052
|
<div class="drawer drawer-end">
|
|
5003
|
-
<input id="edit-drawer-${
|
|
6053
|
+
<input id="edit-drawer-${e.exportName}-\${rowIndex}" type="checkbox" class="drawer-toggle" />
|
|
5004
6054
|
<div class="drawer-content">
|
|
5005
6055
|
<div class="flex items-center justify-end gap-1">
|
|
5006
|
-
<label for="edit-drawer-${
|
|
6056
|
+
<label for="edit-drawer-${e.exportName}-\${rowIndex}" class="btn btn-ghost btn-xs btn-square" title="Edit">
|
|
5007
6057
|
<iconify-icon icon="mdi:pencil-outline" width="15" height="15" class="opacity-50"></iconify-icon>
|
|
5008
6058
|
</label>
|
|
5009
|
-
<button type="button" class="btn btn-ghost btn-xs btn-square" title="Delete" onclick="document.getElementById('delete-dialog-${
|
|
6059
|
+
<button type="button" class="btn btn-ghost btn-xs btn-square" title="Delete" onclick="document.getElementById('delete-dialog-${e.exportName}-\${rowIndex}').showModal()">
|
|
5010
6060
|
<iconify-icon icon="mdi:delete-outline" width="15" height="15" class="opacity-50 hover:text-error"></iconify-icon>
|
|
5011
6061
|
</button>
|
|
5012
6062
|
</div>
|
|
5013
|
-
<dialog id="delete-dialog-${
|
|
6063
|
+
<dialog id="delete-dialog-${e.exportName}-\${rowIndex}" class="modal">
|
|
5014
6064
|
<div class="modal-box max-w-sm">
|
|
5015
6065
|
<h3 class="font-semibold text-base">Delete record?</h3>
|
|
5016
6066
|
<p class="py-3 text-sm text-base-content/60">This action cannot be undone.</p>
|
|
@@ -5018,7 +6068,7 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5018
6068
|
<form method="dialog">
|
|
5019
6069
|
<button class="btn btn-ghost btn-sm">Cancel</button>
|
|
5020
6070
|
</form>
|
|
5021
|
-
<form hx-post="/admin/table/${
|
|
6071
|
+
<form hx-post="/admin/table/${e.exportName}/delete" hx-target="#main-content" hx-swap="outerHTML" class="inline">
|
|
5022
6072
|
<input type="hidden" name="${n}" value="\${String((row as any).${n} ?? '')}" />
|
|
5023
6073
|
<input type="hidden" name="sort" value="\${sort}" />
|
|
5024
6074
|
<input type="hidden" name="order" value="\${order}" />
|
|
@@ -5031,15 +6081,15 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5031
6081
|
</dialog>
|
|
5032
6082
|
</div>
|
|
5033
6083
|
<div class="drawer-side z-50">
|
|
5034
|
-
<label for="edit-drawer-${
|
|
6084
|
+
<label for="edit-drawer-${e.exportName}-\${rowIndex}" aria-label="close sidebar" class="drawer-overlay"></label>
|
|
5035
6085
|
<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">
|
|
5036
6086
|
<div class="flex justify-between items-center mb-5">
|
|
5037
|
-
<h3 class="text-base font-semibold">Edit ${
|
|
5038
|
-
<label for="edit-drawer-${
|
|
6087
|
+
<h3 class="text-base font-semibold">Edit ${e.tableName}</h3>
|
|
6088
|
+
<label for="edit-drawer-${e.exportName}-\${rowIndex}" class="btn btn-sm btn-ghost btn-square">
|
|
5039
6089
|
<iconify-icon icon="mdi:close" width="18" height="18"></iconify-icon>
|
|
5040
6090
|
</label>
|
|
5041
6091
|
</div>
|
|
5042
|
-
<form hx-post="/admin/table/${
|
|
6092
|
+
<form hx-post="/admin/table/${e.exportName}/edit" hx-target="#main-content" hx-swap="outerHTML" class="flex flex-col gap-4">
|
|
5043
6093
|
<input type="hidden" name="${n}" value="\${String((row as any).${n} ?? '')}" />
|
|
5044
6094
|
<input type="hidden" name="sort" value="\${sort}" />
|
|
5045
6095
|
<input type="hidden" name="order" value="\${order}" />
|
|
@@ -5051,7 +6101,7 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5051
6101
|
</div>
|
|
5052
6102
|
</div>
|
|
5053
6103
|
</div>
|
|
5054
|
-
</td>`:'<td class="text-right"><span class="text-xs opacity-30">No primary key</span></td>'}function
|
|
6104
|
+
</td>`:'<td class="text-right"><span class="text-xs opacity-30">No primary key</span></td>'}function C(e){return `
|
|
5055
6105
|
<div class="flex flex-col sm:flex-row justify-between items-center mt-4 gap-3 py-3 px-1">
|
|
5056
6106
|
<div class="text-xs text-base-content/40">
|
|
5057
6107
|
Total found: <span class="font-medium text-base-content/60">\${total}</span>
|
|
@@ -5059,7 +6109,7 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5059
6109
|
\${totalPages > 1 ? html\`
|
|
5060
6110
|
<div class="join border border-base-200 rounded-lg">
|
|
5061
6111
|
\${page > 1 ? html\`
|
|
5062
|
-
<button hx-get="${
|
|
6112
|
+
<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">
|
|
5063
6113
|
<iconify-icon icon="mdi:chevron-left" width="16" height="16"></iconify-icon>
|
|
5064
6114
|
</button>
|
|
5065
6115
|
\` : 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>\`}
|
|
@@ -5067,47 +6117,47 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5067
6117
|
<button class="join-item btn btn-sm btn-ghost no-animation pointer-events-none text-xs">\${page} / \${totalPages}</button>
|
|
5068
6118
|
|
|
5069
6119
|
\${page < totalPages ? html\`
|
|
5070
|
-
<button hx-get="${
|
|
6120
|
+
<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">
|
|
5071
6121
|
<iconify-icon icon="mdi:chevron-right" width="16" height="16"></iconify-icon>
|
|
5072
6122
|
</button>
|
|
5073
6123
|
\` : 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>\`}
|
|
5074
6124
|
</div>
|
|
5075
6125
|
\` : ''}
|
|
5076
|
-
</div>`}function
|
|
6126
|
+
</div>`}function M(e,t="Search term or filter..."){return `
|
|
5077
6127
|
<div class="form-control w-full md:w-auto relative">
|
|
5078
6128
|
<iconify-icon icon="mdi:magnify" width="18" height="18" class="absolute left-3 top-1/2 -translate-y-1/2 opacity-40"></iconify-icon>
|
|
5079
6129
|
<input type="text"
|
|
5080
6130
|
name="search"
|
|
5081
|
-
placeholder="${
|
|
6131
|
+
placeholder="${t}"
|
|
5082
6132
|
value="\${search}"
|
|
5083
|
-
hx-get="${
|
|
6133
|
+
hx-get="${e}?sort=\${sort}&order=\${order}"
|
|
5084
6134
|
hx-trigger="keyup changed delay:500ms, search"
|
|
5085
6135
|
hx-target="#main-content"
|
|
5086
6136
|
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" />
|
|
5087
|
-
</div>`}function
|
|
5088
|
-
<div id="bulk-delete-bar-${
|
|
6137
|
+
</div>`}function bt(e,t,n,r,a,o,i,s,l,u){let c=C(`/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?`
|
|
6138
|
+
<div id="bulk-delete-bar-${e.exportName}" class="fixed bottom-4 left-1/2 -translate-x-1/2 z-40 hidden">
|
|
5089
6139
|
<div class="bg-base-100 border border-base-200 rounded-xl shadow-lg px-3 py-2 flex items-center gap-3">
|
|
5090
6140
|
<div class="text-xs text-base-content/70">
|
|
5091
|
-
<span id="bulk-selected-count-${
|
|
6141
|
+
<span id="bulk-selected-count-${e.exportName}" class="font-medium text-base-content">0</span> selected
|
|
5092
6142
|
</div>
|
|
5093
6143
|
<label class="label cursor-pointer gap-2 py-0 px-1">
|
|
5094
6144
|
<span class="label-text text-xs">All matching (\${total})</span>
|
|
5095
|
-
<input id="bulk-all-matching-${
|
|
6145
|
+
<input id="bulk-all-matching-${e.exportName}" type="checkbox" class="checkbox checkbox-xs" />
|
|
5096
6146
|
</label>
|
|
5097
|
-
<button id="bulk-delete-trigger-${
|
|
6147
|
+
<button id="bulk-delete-trigger-${e.exportName}" type="button" class="btn btn-error btn-xs gap-1">
|
|
5098
6148
|
<iconify-icon icon="mdi:delete-outline" width="14" height="14"></iconify-icon>
|
|
5099
6149
|
Delete selected
|
|
5100
6150
|
</button>
|
|
5101
6151
|
</div>
|
|
5102
6152
|
</div>
|
|
5103
6153
|
|
|
5104
|
-
<dialog id="bulk-delete-modal-${
|
|
6154
|
+
<dialog id="bulk-delete-modal-${e.exportName}" class="modal">
|
|
5105
6155
|
<div class="modal-box max-w-sm p-6 space-y-4">
|
|
5106
6156
|
<h3 class="font-semibold text-base">Delete selected rows?</h3>
|
|
5107
|
-
<p class="text-sm text-base-content/70" id="bulk-delete-description-${
|
|
5108
|
-
<form id="bulk-delete-form-${
|
|
5109
|
-
<input type="hidden" name="bulkMode" id="bulk-delete-mode-${
|
|
5110
|
-
<input type="hidden" name="selectedIds" id="bulk-delete-ids-${
|
|
6157
|
+
<p class="text-sm text-base-content/70" id="bulk-delete-description-${e.exportName}">This action cannot be undone.</p>
|
|
6158
|
+
<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">
|
|
6159
|
+
<input type="hidden" name="bulkMode" id="bulk-delete-mode-${e.exportName}" value="selected" />
|
|
6160
|
+
<input type="hidden" name="selectedIds" id="bulk-delete-ids-${e.exportName}" value="" />
|
|
5111
6161
|
<input type="hidden" name="sort" value="\${sort}" />
|
|
5112
6162
|
<input type="hidden" name="order" value="\${order}" />
|
|
5113
6163
|
<input type="hidden" name="search" value="\${search}" />
|
|
@@ -5129,15 +6179,15 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5129
6179
|
const rowCheckboxes = Array.from(container.querySelectorAll('.row-select-checkbox')).filter((node) => node instanceof HTMLInputElement);
|
|
5130
6180
|
if (rowCheckboxes.length === 0) return;
|
|
5131
6181
|
|
|
5132
|
-
const selectAll = container.querySelector('#select-all-${
|
|
5133
|
-
const bar = container.querySelector('#bulk-delete-bar-${
|
|
5134
|
-
const selectedCount = container.querySelector('#bulk-selected-count-${
|
|
5135
|
-
const allMatching = container.querySelector('#bulk-all-matching-${
|
|
5136
|
-
const trigger = container.querySelector('#bulk-delete-trigger-${
|
|
5137
|
-
const modal = container.querySelector('#bulk-delete-modal-${
|
|
5138
|
-
const modeInput = container.querySelector('#bulk-delete-mode-${
|
|
5139
|
-
const idsInput = container.querySelector('#bulk-delete-ids-${
|
|
5140
|
-
const description = container.querySelector('#bulk-delete-description-${
|
|
6182
|
+
const selectAll = container.querySelector('#select-all-${e.exportName}');
|
|
6183
|
+
const bar = container.querySelector('#bulk-delete-bar-${e.exportName}');
|
|
6184
|
+
const selectedCount = container.querySelector('#bulk-selected-count-${e.exportName}');
|
|
6185
|
+
const allMatching = container.querySelector('#bulk-all-matching-${e.exportName}');
|
|
6186
|
+
const trigger = container.querySelector('#bulk-delete-trigger-${e.exportName}');
|
|
6187
|
+
const modal = container.querySelector('#bulk-delete-modal-${e.exportName}');
|
|
6188
|
+
const modeInput = container.querySelector('#bulk-delete-mode-${e.exportName}');
|
|
6189
|
+
const idsInput = container.querySelector('#bulk-delete-ids-${e.exportName}');
|
|
6190
|
+
const description = container.querySelector('#bulk-delete-description-${e.exportName}');
|
|
5141
6191
|
|
|
5142
6192
|
if (!(selectAll instanceof HTMLInputElement) ||
|
|
5143
6193
|
!(bar instanceof HTMLElement) ||
|
|
@@ -5203,16 +6253,16 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5203
6253
|
})();
|
|
5204
6254
|
</script>
|
|
5205
6255
|
`:"";return `
|
|
5206
|
-
adminApp.get('/table/${
|
|
6256
|
+
adminApp.get('/table/${e.exportName}', async (c) => {
|
|
5207
6257
|
const db = drizzle(c.env[options.databaseBinding], { schema });
|
|
5208
6258
|
const page = parseInt(c.req.query('page') || '1');
|
|
5209
6259
|
const limit = 20;
|
|
5210
6260
|
const offset = (page - 1) * limit;
|
|
5211
|
-
const sort = c.req.query('sort') || '${
|
|
6261
|
+
const sort = c.req.query('sort') || '${t}';
|
|
5212
6262
|
const order = c.req.query('order') || 'desc';
|
|
5213
6263
|
const search = c.req.query('search') || '';
|
|
5214
6264
|
|
|
5215
|
-
let tableSchema = (schema as any).${
|
|
6265
|
+
let tableSchema = (schema as any).${e.exportName};
|
|
5216
6266
|
if (!tableSchema) return c.text("Table missing", 404);
|
|
5217
6267
|
|
|
5218
6268
|
let query = db.select().from(tableSchema);
|
|
@@ -5242,7 +6292,7 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5242
6292
|
<table class="table table-sm md:table-md w-full">
|
|
5243
6293
|
<thead>
|
|
5244
6294
|
<tr class="border-b border-base-200">
|
|
5245
|
-
${
|
|
6295
|
+
${d}
|
|
5246
6296
|
${i}
|
|
5247
6297
|
<th class="w-[100px] text-right">
|
|
5248
6298
|
<iconify-icon icon="mdi:dots-horizontal" width="16" height="16" class="opacity-30"></iconify-icon>
|
|
@@ -5263,7 +6313,7 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5263
6313
|
<div class="flex flex-col items-center gap-3">
|
|
5264
6314
|
<iconify-icon icon="mdi:database-off-outline" width="40" height="40" class="opacity-20"></iconify-icon>
|
|
5265
6315
|
<p class="text-sm text-base-content/40">No records found.</p>
|
|
5266
|
-
<label for="create-drawer-${
|
|
6316
|
+
<label for="create-drawer-${e.exportName}" class="btn btn-sm btn-primary gap-1">
|
|
5267
6317
|
<iconify-icon icon="mdi:plus" width="16" height="16"></iconify-icon>
|
|
5268
6318
|
New record
|
|
5269
6319
|
</label>
|
|
@@ -5274,52 +6324,52 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5274
6324
|
</tbody>
|
|
5275
6325
|
</table>
|
|
5276
6326
|
</div>
|
|
5277
|
-
${
|
|
6327
|
+
${c}
|
|
5278
6328
|
</div>
|
|
5279
6329
|
\`;
|
|
5280
6330
|
|
|
5281
6331
|
const content = html\`
|
|
5282
6332
|
<div id="main-content">
|
|
5283
6333
|
<div class="drawer drawer-end">
|
|
5284
|
-
<input id="create-drawer-${
|
|
6334
|
+
<input id="create-drawer-${e.exportName}" type="checkbox" class="drawer-toggle" />
|
|
5285
6335
|
<div class="drawer-content">
|
|
5286
6336
|
<div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-5 gap-3">
|
|
5287
6337
|
<div class="flex items-center gap-2 text-sm">
|
|
5288
6338
|
<a href="/admin" class="text-base-content/40 hover:text-primary transition-colors">Collections</a>
|
|
5289
6339
|
<iconify-icon icon="mdi:chevron-right" width="14" height="14" class="opacity-30"></iconify-icon>
|
|
5290
|
-
<span class="font-semibold capitalize">${
|
|
6340
|
+
<span class="font-semibold capitalize">${e.tableName}</span>
|
|
5291
6341
|
<button class="btn btn-ghost btn-xs btn-square opacity-40 hover:opacity-100" onclick="window.location.reload()">
|
|
5292
6342
|
<iconify-icon icon="mdi:refresh" width="14" height="14"></iconify-icon>
|
|
5293
6343
|
</button>
|
|
5294
6344
|
</div>
|
|
5295
6345
|
<div class="flex items-center gap-2 w-full md:w-auto">
|
|
5296
|
-
<label for="create-drawer-${
|
|
6346
|
+
<label for="create-drawer-${e.exportName}" class="btn btn-primary btn-sm gap-1">
|
|
5297
6347
|
<iconify-icon icon="mdi:plus" width="16" height="16"></iconify-icon>
|
|
5298
6348
|
New record
|
|
5299
6349
|
</label>
|
|
5300
6350
|
</div>
|
|
5301
6351
|
</div>
|
|
5302
6352
|
<div class="mb-4">
|
|
5303
|
-
${
|
|
6353
|
+
${f}
|
|
5304
6354
|
</div>
|
|
5305
6355
|
\${tableHtml}
|
|
5306
|
-
${
|
|
6356
|
+
${w}
|
|
5307
6357
|
</div>
|
|
5308
6358
|
<div class="drawer-side z-50">
|
|
5309
|
-
<label for="create-drawer-${
|
|
6359
|
+
<label for="create-drawer-${e.exportName}" aria-label="close sidebar" class="drawer-overlay"></label>
|
|
5310
6360
|
<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">
|
|
5311
6361
|
<div class="flex justify-between items-center mb-5">
|
|
5312
|
-
<h3 class="text-base font-semibold">Create ${
|
|
5313
|
-
<label for="create-drawer-${
|
|
6362
|
+
<h3 class="text-base font-semibold">Create ${e.tableName}</h3>
|
|
6363
|
+
<label for="create-drawer-${e.exportName}" class="btn btn-sm btn-ghost btn-square">
|
|
5314
6364
|
<iconify-icon icon="mdi:close" width="18" height="18"></iconify-icon>
|
|
5315
6365
|
</label>
|
|
5316
6366
|
</div>
|
|
5317
|
-
<form hx-post="/admin/table/${
|
|
6367
|
+
<form hx-post="/admin/table/${e.exportName}/create" hx-target="#main-content" hx-swap="outerHTML" class="flex flex-col gap-4">
|
|
5318
6368
|
<input type="hidden" name="sort" value="\${sort}" />
|
|
5319
6369
|
<input type="hidden" name="order" value="\${order}" />
|
|
5320
6370
|
<input type="hidden" name="search" value="\${search}" />
|
|
5321
6371
|
<input type="hidden" name="page" value="\${page}" />
|
|
5322
|
-
${
|
|
6372
|
+
${u}
|
|
5323
6373
|
<button type="submit" class="btn btn-primary btn-sm mt-2">Create record</button>
|
|
5324
6374
|
</form>
|
|
5325
6375
|
</div>
|
|
@@ -5333,17 +6383,17 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5333
6383
|
}
|
|
5334
6384
|
|
|
5335
6385
|
return c.html(Layout({
|
|
5336
|
-
title: "${
|
|
6386
|
+
title: "${e.tableName} - Admin Dashboard",
|
|
5337
6387
|
children: content
|
|
5338
6388
|
}));
|
|
5339
|
-
});`}function
|
|
6389
|
+
});`}function yt(e,t,n,r,a,o,i,s){let l=r==="number"?`
|
|
5340
6390
|
const parsedId = Number(rawId);
|
|
5341
6391
|
if (Number.isNaN(parsedId)) return c.text('${n} must be a valid number', 400);
|
|
5342
6392
|
idValue = parsedId;
|
|
5343
|
-
`:"",
|
|
5344
|
-
adminApp.post('/table/${
|
|
6393
|
+
`:"",c=a?`
|
|
6394
|
+
adminApp.post('/table/${e}/edit', async (c) => {
|
|
5345
6395
|
const db = drizzle(c.env[options.databaseBinding], { schema });
|
|
5346
|
-
const tableSchema = (schema as any).${
|
|
6396
|
+
const tableSchema = (schema as any).${e};
|
|
5347
6397
|
if (!tableSchema) return c.text('Table missing', 404);
|
|
5348
6398
|
|
|
5349
6399
|
const body = await c.req.parseBody();
|
|
@@ -5368,16 +6418,16 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5368
6418
|
|
|
5369
6419
|
const query = new URLSearchParams({
|
|
5370
6420
|
page: getValue(body.page) || '1',
|
|
5371
|
-
sort: getValue(body.sort) || '${
|
|
6421
|
+
sort: getValue(body.sort) || '${t}',
|
|
5372
6422
|
order: getValue(body.order) || 'desc',
|
|
5373
6423
|
search: getValue(body.search) || '',
|
|
5374
6424
|
});
|
|
5375
|
-
return c.redirect('/admin/table/${
|
|
6425
|
+
return c.redirect('/admin/table/${e}?' + query.toString());
|
|
5376
6426
|
});
|
|
5377
6427
|
|
|
5378
|
-
adminApp.post('/table/${
|
|
6428
|
+
adminApp.post('/table/${e}/delete', async (c) => {
|
|
5379
6429
|
const db = drizzle(c.env[options.databaseBinding], { schema });
|
|
5380
|
-
const tableSchema = (schema as any).${
|
|
6430
|
+
const tableSchema = (schema as any).${e};
|
|
5381
6431
|
if (!tableSchema) return c.text('Table missing', 404);
|
|
5382
6432
|
|
|
5383
6433
|
const body = await c.req.parseBody();
|
|
@@ -5395,16 +6445,16 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5395
6445
|
|
|
5396
6446
|
const query = new URLSearchParams({
|
|
5397
6447
|
page: getValue(body.page) || '1',
|
|
5398
|
-
sort: getValue(body.sort) || '${
|
|
6448
|
+
sort: getValue(body.sort) || '${t}',
|
|
5399
6449
|
order: getValue(body.order) || 'desc',
|
|
5400
6450
|
search: getValue(body.search) || '',
|
|
5401
6451
|
});
|
|
5402
|
-
return c.redirect('/admin/table/${
|
|
6452
|
+
return c.redirect('/admin/table/${e}?' + query.toString());
|
|
5403
6453
|
});
|
|
5404
6454
|
|
|
5405
|
-
adminApp.post('/table/${
|
|
6455
|
+
adminApp.post('/table/${e}/delete-bulk', async (c) => {
|
|
5406
6456
|
const db = drizzle(c.env[options.databaseBinding], { schema });
|
|
5407
|
-
const tableSchema = (schema as any).${
|
|
6457
|
+
const tableSchema = (schema as any).${e};
|
|
5408
6458
|
if (!tableSchema) return c.text('Table missing', 404);
|
|
5409
6459
|
|
|
5410
6460
|
const body = await c.req.parseBody();
|
|
@@ -5441,15 +6491,15 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5441
6491
|
|
|
5442
6492
|
const query = new URLSearchParams({
|
|
5443
6493
|
page: getValue(body.page) || '1',
|
|
5444
|
-
sort: getValue(body.sort) || '${
|
|
6494
|
+
sort: getValue(body.sort) || '${t}',
|
|
5445
6495
|
order: getValue(body.order) || 'desc',
|
|
5446
6496
|
search: getValue(body.search) || '',
|
|
5447
6497
|
});
|
|
5448
|
-
return c.redirect('/admin/table/${
|
|
6498
|
+
return c.redirect('/admin/table/${e}?' + query.toString());
|
|
5449
6499
|
});`:"";return `
|
|
5450
|
-
adminApp.post('/table/${
|
|
6500
|
+
adminApp.post('/table/${e}/create', async (c) => {
|
|
5451
6501
|
const db = drizzle(c.env[options.databaseBinding], { schema });
|
|
5452
|
-
const tableSchema = (schema as any).${
|
|
6502
|
+
const tableSchema = (schema as any).${e};
|
|
5453
6503
|
if (!tableSchema) return c.text('Table missing', 404);
|
|
5454
6504
|
|
|
5455
6505
|
const body = await c.req.parseBody();
|
|
@@ -5462,22 +6512,22 @@ import type { D1Database, IncomingRequestCfProperties, KVNamespace } from "@clou
|
|
|
5462
6512
|
|
|
5463
6513
|
const query = new URLSearchParams({
|
|
5464
6514
|
page: getValue(body.page) || '1',
|
|
5465
|
-
sort: getValue(body.sort) || '${
|
|
6515
|
+
sort: getValue(body.sort) || '${t}',
|
|
5466
6516
|
order: getValue(body.order) || 'desc',
|
|
5467
6517
|
search: getValue(body.search) || '',
|
|
5468
6518
|
});
|
|
5469
|
-
return c.redirect('/admin/table/${
|
|
6519
|
+
return c.redirect('/admin/table/${e}?' + query.toString());
|
|
5470
6520
|
});
|
|
5471
|
-
${
|
|
5472
|
-
`}function
|
|
5473
|
-
`+
|
|
6521
|
+
${c}
|
|
6522
|
+
`}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),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)+`
|
|
6523
|
+
`+yt(e.exportName,y,t,w,n,i,f,d)}function wt(){return `
|
|
5474
6524
|
const buildUsersRedirect = (params: { page?: string; sort?: string; order?: string; search?: string }) => {
|
|
5475
6525
|
const page = params.page && params.page.trim() ? params.page : '1';
|
|
5476
6526
|
const sort = params.sort && params.sort.trim() ? params.sort : 'createdAt';
|
|
5477
6527
|
const order = params.order === 'asc' ? 'asc' : 'desc';
|
|
5478
6528
|
const search = params.search ? params.search : '';
|
|
5479
6529
|
return '/admin/users?page=' + encodeURIComponent(page) + '&sort=' + encodeURIComponent(sort) + '&order=' + encodeURIComponent(order) + '&search=' + encodeURIComponent(search);
|
|
5480
|
-
};`}function
|
|
6530
|
+
};`}function xt(){return `
|
|
5481
6531
|
\${(row as any).id === currentUserId ? '' : html\`
|
|
5482
6532
|
<input type="checkbox" id="ban-user-modal-\${String((row as any).id)}" class="modal-toggle" />
|
|
5483
6533
|
<div class="modal">
|
|
@@ -5498,7 +6548,7 @@ ${d}
|
|
|
5498
6548
|
</div>
|
|
5499
6549
|
<label class="modal-backdrop" for="ban-user-modal-\${String((row as any).id)}">Close</label>
|
|
5500
6550
|
</div>
|
|
5501
|
-
\`}`}function
|
|
6551
|
+
\`}`}function vt(){return `
|
|
5502
6552
|
\${(row as any).id === currentUserId ? '' : html\`
|
|
5503
6553
|
<input type="checkbox" id="delete-user-modal-\${String((row as any).id)}" class="modal-toggle" />
|
|
5504
6554
|
<div class="modal">
|
|
@@ -5519,15 +6569,15 @@ ${d}
|
|
|
5519
6569
|
</div>
|
|
5520
6570
|
<label class="modal-backdrop" for="delete-user-modal-\${String((row as any).id)}">Close</label>
|
|
5521
6571
|
</div>
|
|
5522
|
-
\`}`}var
|
|
5523
|
-
`),
|
|
6572
|
+
\`}`}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(`
|
|
6573
|
+
`),t=C("/admin/users");return `
|
|
5524
6574
|
const tableHtml = html\`
|
|
5525
6575
|
<div class="bg-base-100 rounded-xl border border-base-200 overflow-hidden">
|
|
5526
6576
|
<div class="overflow-x-auto">
|
|
5527
6577
|
<table class="table table-sm md:table-md w-full">
|
|
5528
6578
|
<thead>
|
|
5529
6579
|
<tr class="border-b border-base-200">
|
|
5530
|
-
${
|
|
6580
|
+
${e}
|
|
5531
6581
|
<th class="text-right">
|
|
5532
6582
|
<iconify-icon icon="mdi:dots-horizontal" width="16" height="16" class="opacity-30"></iconify-icon>
|
|
5533
6583
|
</th>
|
|
@@ -5588,8 +6638,8 @@ ${d}
|
|
|
5588
6638
|
</div>
|
|
5589
6639
|
</div>
|
|
5590
6640
|
</div>
|
|
5591
|
-
${
|
|
5592
|
-
${
|
|
6641
|
+
${xt()}
|
|
6642
|
+
${vt()}
|
|
5593
6643
|
</td>
|
|
5594
6644
|
</tr>
|
|
5595
6645
|
\`)}
|
|
@@ -5602,9 +6652,9 @@ ${he()}
|
|
|
5602
6652
|
</tbody>
|
|
5603
6653
|
</table>
|
|
5604
6654
|
</div>
|
|
5605
|
-
${
|
|
6655
|
+
${t}
|
|
5606
6656
|
</div>
|
|
5607
|
-
\`;`}function
|
|
6657
|
+
\`;`}function Rt(){return `
|
|
5608
6658
|
const content = html\`
|
|
5609
6659
|
<div id="main-content">
|
|
5610
6660
|
<div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-5 gap-3">
|
|
@@ -5616,11 +6666,11 @@ ${he()}
|
|
|
5616
6666
|
<iconify-icon icon="mdi:refresh" width="14" height="14"></iconify-icon>
|
|
5617
6667
|
</button>
|
|
5618
6668
|
</div>
|
|
5619
|
-
${
|
|
6669
|
+
${M("/admin/users","Search users...")}
|
|
5620
6670
|
</div>
|
|
5621
6671
|
\${tableHtml}
|
|
5622
6672
|
</div>
|
|
5623
|
-
\`;`}function
|
|
6673
|
+
\`;`}function kt(){let e=Tt(),t=Rt();return `
|
|
5624
6674
|
adminApp.get('/users', async (c) => {
|
|
5625
6675
|
const db = drizzle(c.env[options.databaseBinding]);
|
|
5626
6676
|
const auth = createAuth({ DATABASE: c.env[options.databaseBinding] } as any, c.req.raw.cf as any);
|
|
@@ -5664,10 +6714,10 @@ ${he()}
|
|
|
5664
6714
|
const total = Number(totalResult[0]?.count || 0);
|
|
5665
6715
|
const totalPages = Math.ceil(total / limit);
|
|
5666
6716
|
|
|
5667
|
-
${t}
|
|
5668
|
-
|
|
5669
6717
|
${e}
|
|
5670
6718
|
|
|
6719
|
+
${t}
|
|
6720
|
+
|
|
5671
6721
|
if (c.req.header('hx-request')) {
|
|
5672
6722
|
return c.html(content);
|
|
5673
6723
|
}
|
|
@@ -5676,7 +6726,7 @@ ${he()}
|
|
|
5676
6726
|
title: "users - Admin Dashboard",
|
|
5677
6727
|
children: content,
|
|
5678
6728
|
}));
|
|
5679
|
-
});`}function
|
|
6729
|
+
});`}function St(){return `
|
|
5680
6730
|
adminApp.post('/users/edit', async (c) => {
|
|
5681
6731
|
const session = await requireAdminSession(c);
|
|
5682
6732
|
if (!session) {
|
|
@@ -5819,8 +6869,8 @@ ${he()}
|
|
|
5819
6869
|
const resolvedPage = String(Math.min(nextPageCandidate, totalPages));
|
|
5820
6870
|
|
|
5821
6871
|
return c.redirect(buildUsersRedirect({ page: resolvedPage, search, sort, order }));
|
|
5822
|
-
});`}function
|
|
5823
|
-
${
|
|
6872
|
+
});`}function Q(){return `
|
|
6873
|
+
${wt()}
|
|
5824
6874
|
|
|
5825
6875
|
const requireAdminSession = async (c: any) => {
|
|
5826
6876
|
const auth = createAuth({ DATABASE: c.env[options.databaseBinding] } as any, c.req.raw.cf as any);
|
|
@@ -5831,29 +6881,29 @@ ${he()}
|
|
|
5831
6881
|
return session;
|
|
5832
6882
|
};
|
|
5833
6883
|
|
|
5834
|
-
${
|
|
6884
|
+
${kt()}
|
|
5835
6885
|
|
|
5836
|
-
${
|
|
5837
|
-
`}function
|
|
6886
|
+
${St()}
|
|
6887
|
+
`}function At(e){return `${e.tables.map(t=>U(t)).join(`
|
|
5838
6888
|
`)}
|
|
5839
|
-
${
|
|
6889
|
+
${Q()}`}function Nt(e){return `
|
|
5840
6890
|
<div class="flex items-center justify-between">
|
|
5841
6891
|
<div class="flex items-center gap-3">
|
|
5842
6892
|
<div class="w-10 h-10 rounded-xl bg-primary/10 flex items-center justify-center">
|
|
5843
|
-
<iconify-icon icon="${
|
|
6893
|
+
<iconify-icon icon="${e.kind==="query"?"solar:reorder-bold-duotone":"solar:bolt-bold-duotone"}" width="24" height="24" class="text-primary"></iconify-icon>
|
|
5844
6894
|
</div>
|
|
5845
6895
|
<div>
|
|
5846
|
-
<h1 class="text-xl font-bold tracking-tight">${
|
|
5847
|
-
<p class="text-xs opacity-50 font-medium uppercase tracking-wider">${
|
|
6896
|
+
<h1 class="text-xl font-bold tracking-tight">${e.exportName}</h1>
|
|
6897
|
+
<p class="text-xs opacity-50 font-medium uppercase tracking-wider">${e.kind}</p>
|
|
5848
6898
|
</div>
|
|
5849
6899
|
</div>
|
|
5850
6900
|
<div class="flex items-center gap-2">
|
|
5851
|
-
<span class="badge badge-sm badge-ghost font-mono opacity-50 px-2 py-3">/api${
|
|
6901
|
+
<span class="badge badge-sm badge-ghost font-mono opacity-50 px-2 py-3">/api${e.routePath}</span>
|
|
5852
6902
|
</div>
|
|
5853
6903
|
</div>
|
|
5854
|
-
`}function
|
|
5855
|
-
<div class="text-[11px] opacity-30 italic py-2">No arguments defined for this ${
|
|
5856
|
-
`:
|
|
6904
|
+
`}function rr(e){return e==="boolean"?"checkbox":e==="number"?"number":"text"}function ar(e){let t=e.args??[];return t.length===0?`
|
|
6905
|
+
<div class="text-[11px] opacity-30 italic py-2">No arguments defined for this ${e.kind}.</div>
|
|
6906
|
+
`: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?`
|
|
5857
6907
|
<div class="flex items-center gap-3 py-1">
|
|
5858
6908
|
<input
|
|
5859
6909
|
type="checkbox"
|
|
@@ -5882,12 +6932,12 @@ ${z()}`}function ke(t){return `
|
|
|
5882
6932
|
/>
|
|
5883
6933
|
</div>
|
|
5884
6934
|
`}).join(`
|
|
5885
|
-
`)}function
|
|
6935
|
+
`)}function or(e){return `
|
|
5886
6936
|
<div class="space-y-4">
|
|
5887
6937
|
<div class="flex items-center justify-between">
|
|
5888
6938
|
<div class="flex flex-col">
|
|
5889
6939
|
<span class="text-[11px] font-bold uppercase tracking-wider opacity-40">Arguments</span>
|
|
5890
|
-
<span class="text-[10px] font-mono opacity-30">${
|
|
6940
|
+
<span class="text-[10px] font-mono opacity-30">${e.kind}</span>
|
|
5891
6941
|
</div>
|
|
5892
6942
|
<label class="flex items-center gap-2 cursor-pointer select-none group" title="Enable realtime updates via WebSocket">
|
|
5893
6943
|
<span class="text-[10px] font-bold uppercase tracking-wider opacity-40 group-hover:opacity-70 transition-opacity">Realtime</span>
|
|
@@ -5895,11 +6945,11 @@ ${z()}`}function ke(t){return `
|
|
|
5895
6945
|
</label>
|
|
5896
6946
|
</div>
|
|
5897
6947
|
<div id="args-rows" class="flex flex-col gap-3">
|
|
5898
|
-
${
|
|
6948
|
+
${ar(e)}
|
|
5899
6949
|
</div>
|
|
5900
|
-
<p class="text-[11px] opacity-30 mt-2 italic">Values are sent as ${
|
|
6950
|
+
<p class="text-[11px] opacity-30 mt-2 italic">Values are sent as ${e.kind==="query"?"query string params":"JSON request body"}.</p>
|
|
5901
6951
|
</div>
|
|
5902
|
-
`}function
|
|
6952
|
+
`}function ir(){return `
|
|
5903
6953
|
<div class="space-y-4">
|
|
5904
6954
|
<label class="text-[11px] font-bold uppercase tracking-wider opacity-40 block">Bearer Token <span class="font-normal normal-case">(optional)</span></label>
|
|
5905
6955
|
<div class="relative group">
|
|
@@ -5916,7 +6966,7 @@ ${z()}`}function ke(t){return `
|
|
|
5916
6966
|
</div>
|
|
5917
6967
|
<p class="text-[10px] opacity-30 italic">Token will be included in the Authorization header.</p>
|
|
5918
6968
|
</div>
|
|
5919
|
-
`}function
|
|
6969
|
+
`}function sr(){return `
|
|
5920
6970
|
<div class="space-y-4">
|
|
5921
6971
|
<div class="flex items-center justify-between">
|
|
5922
6972
|
<span class="text-[11px] font-bold uppercase tracking-wider opacity-40">Custom Headers</span>
|
|
@@ -5930,7 +6980,7 @@ ${z()}`}function ke(t){return `
|
|
|
5930
6980
|
</div>
|
|
5931
6981
|
<p id="headers-error" class="text-[11px] text-error mt-1.5 hidden"></p>
|
|
5932
6982
|
</div>
|
|
5933
|
-
`}function
|
|
6983
|
+
`}function $t(e){return `
|
|
5934
6984
|
<div class="card bg-base-100 border border-base-200 shadow-sm overflow-hidden flex flex-col h-full">
|
|
5935
6985
|
<div class="px-5 py-3 border-b border-base-200 bg-base-200/20 flex items-center justify-between flex-none">
|
|
5936
6986
|
<h3 class="text-xs font-bold uppercase tracking-widest opacity-40">Request</h3>
|
|
@@ -5951,13 +7001,13 @@ ${z()}`}function ke(t){return `
|
|
|
5951
7001
|
<!-- Tab Content -->
|
|
5952
7002
|
<div class="flex-1 overflow-y-auto">
|
|
5953
7003
|
<div id="request-tab-args" class="p-5">
|
|
5954
|
-
${
|
|
7004
|
+
${or(e)}
|
|
5955
7005
|
</div>
|
|
5956
7006
|
<div id="request-tab-auth" class="p-5 hidden">
|
|
5957
|
-
${
|
|
7007
|
+
${ir()}
|
|
5958
7008
|
</div>
|
|
5959
7009
|
<div id="request-tab-headers" class="p-5 hidden">
|
|
5960
|
-
${
|
|
7010
|
+
${sr()}
|
|
5961
7011
|
</div>
|
|
5962
7012
|
</div>
|
|
5963
7013
|
|
|
@@ -5969,13 +7019,13 @@ ${z()}`}function ke(t){return `
|
|
|
5969
7019
|
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"
|
|
5970
7020
|
>
|
|
5971
7021
|
<iconify-icon icon="solar:play-bold" width="18" height="18"></iconify-icon>
|
|
5972
|
-
Run ${
|
|
7022
|
+
Run ${e.kind}
|
|
5973
7023
|
</button>
|
|
5974
7024
|
</div>
|
|
5975
7025
|
</form>
|
|
5976
7026
|
</div>
|
|
5977
7027
|
</div>
|
|
5978
|
-
`}function
|
|
7028
|
+
`}function qt(){return `
|
|
5979
7029
|
<div class="card bg-base-100 border border-base-200 shadow-sm overflow-hidden flex flex-col">
|
|
5980
7030
|
<!-- Panel Header -->
|
|
5981
7031
|
<div class="px-5 py-3 border-b border-base-200 bg-base-200/20 flex items-center justify-between">
|
|
@@ -6057,7 +7107,7 @@ ${z()}`}function ke(t){return `
|
|
|
6057
7107
|
|
|
6058
7108
|
</div>
|
|
6059
7109
|
</div>
|
|
6060
|
-
`}function
|
|
7110
|
+
`}function Ct(e){let t=e.kind==="query",n=e.routePath,r=e.handlerName??e.routePath;return `
|
|
6061
7111
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css">
|
|
6062
7112
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
|
|
6063
7113
|
|
|
@@ -6283,7 +7333,7 @@ ${z()}`}function ke(t){return `
|
|
|
6283
7333
|
if (indicator) indicator.classList.remove('opacity-0');
|
|
6284
7334
|
showBodyLoading();
|
|
6285
7335
|
|
|
6286
|
-
var isQuery = ${
|
|
7336
|
+
var isQuery = ${t};
|
|
6287
7337
|
var method = isQuery ? 'GET' : 'POST';
|
|
6288
7338
|
var pathWithQuery = '${n}';
|
|
6289
7339
|
|
|
@@ -6355,7 +7405,7 @@ ${z()}`}function ke(t){return `
|
|
|
6355
7405
|
var _rtToken = null;
|
|
6356
7406
|
var _rtEnabled = false;
|
|
6357
7407
|
var _rtEventCount = 0;
|
|
6358
|
-
var _isRealtimeSupported = ${
|
|
7408
|
+
var _isRealtimeSupported = ${t};
|
|
6359
7409
|
var _realtimeQueryName = '${r}';
|
|
6360
7410
|
var _rtPingInterval = null;
|
|
6361
7411
|
|
|
@@ -6599,21 +7649,21 @@ ${z()}`}function ke(t){return `
|
|
|
6599
7649
|
_rtEnabled = false;
|
|
6600
7650
|
});
|
|
6601
7651
|
</script>
|
|
6602
|
-
`}function
|
|
7652
|
+
`}function Mt(e){return `
|
|
6603
7653
|
const content = html\`
|
|
6604
7654
|
<div class="flex flex-col gap-6 max-w-5xl mx-auto" id="main-content">
|
|
6605
|
-
${
|
|
7655
|
+
${Nt(e)}
|
|
6606
7656
|
|
|
6607
7657
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
6608
7658
|
<!-- Request Panel -->
|
|
6609
|
-
${
|
|
7659
|
+
${$t(e)}
|
|
6610
7660
|
|
|
6611
7661
|
<!-- Result Panel -->
|
|
6612
|
-
${
|
|
7662
|
+
${qt()}
|
|
6613
7663
|
</div>
|
|
6614
7664
|
</div>
|
|
6615
7665
|
|
|
6616
|
-
${
|
|
7666
|
+
${Ct(e)}
|
|
6617
7667
|
\`;
|
|
6618
7668
|
|
|
6619
7669
|
if (c.req.header('hx-request')) {
|
|
@@ -6621,13 +7671,13 @@ ${z()}`}function ke(t){return `
|
|
|
6621
7671
|
}
|
|
6622
7672
|
|
|
6623
7673
|
return c.html(Layout({
|
|
6624
|
-
title: "${
|
|
7674
|
+
title: "${e.exportName} - Functions",
|
|
6625
7675
|
children: content
|
|
6626
|
-
}));`}function
|
|
7676
|
+
}));`}function Pt(e){return e.map(n=>n.kind!=="query"&&n.kind!=="mutation"?"":`
|
|
6627
7677
|
adminApp.get('/functions${n.routePath}', (c) => {
|
|
6628
|
-
${
|
|
7678
|
+
${Mt(n)}
|
|
6629
7679
|
});`).join(`
|
|
6630
|
-
`)}function
|
|
7680
|
+
`)}function It(){return `
|
|
6631
7681
|
const getStorageBucket = (c: any): R2Bucket | null => {
|
|
6632
7682
|
const r2Binding = (options as any).r2Binding;
|
|
6633
7683
|
if (!r2Binding || !c.env[r2Binding]) return null;
|
|
@@ -6696,7 +7746,7 @@ ${z()}`}function ke(t){return `
|
|
|
6696
7746
|
const parts = prefix.split('/').filter(Boolean);
|
|
6697
7747
|
return parts.slice(0, -1).join('/') + (parts.length > 1 ? '/' : '');
|
|
6698
7748
|
};
|
|
6699
|
-
`}function
|
|
7749
|
+
`}function Dt(){return `
|
|
6700
7750
|
const buildStorageListingContent = (listed: any, prefix: string) => {
|
|
6701
7751
|
const parts = prefix.split('/').filter(Boolean);
|
|
6702
7752
|
const breadcrumbs = [];
|
|
@@ -6823,7 +7873,7 @@ ${z()}`}function ke(t){return `
|
|
|
6823
7873
|
</div>
|
|
6824
7874
|
\`;
|
|
6825
7875
|
};
|
|
6826
|
-
`}function
|
|
7876
|
+
`}function Et(){return `
|
|
6827
7877
|
const handleStorageListRoute = async (c: any) => {
|
|
6828
7878
|
const bucket = getStorageBucket(c);
|
|
6829
7879
|
if (!bucket) {
|
|
@@ -6845,7 +7895,7 @@ ${z()}`}function ke(t){return `
|
|
|
6845
7895
|
|
|
6846
7896
|
adminApp.get('/storage', handleStorageListRoute);
|
|
6847
7897
|
adminApp.get('/storage/*', handleStorageListRoute);
|
|
6848
|
-
`}function
|
|
7898
|
+
`}function Ot(){return `
|
|
6849
7899
|
adminApp.post('/storage/upload', async (c) => {
|
|
6850
7900
|
const bucket = getStorageBucket(c);
|
|
6851
7901
|
if (!bucket) return c.text("Storage not configured", 400);
|
|
@@ -6863,7 +7913,7 @@ ${z()}`}function ke(t){return `
|
|
|
6863
7913
|
|
|
6864
7914
|
return c.redirect(prefixToStoragePath(prefix));
|
|
6865
7915
|
});
|
|
6866
|
-
`}function
|
|
7916
|
+
`}function Ft(){return `
|
|
6867
7917
|
adminApp.delete('/storage/delete', async (c) => {
|
|
6868
7918
|
const bucket = getStorageBucket(c);
|
|
6869
7919
|
if (!bucket) return c.text("Storage not configured", 400);
|
|
@@ -6878,7 +7928,7 @@ ${z()}`}function ke(t){return `
|
|
|
6878
7928
|
c.header('HX-Redirect', prefixToStoragePath(prefix));
|
|
6879
7929
|
return c.html('');
|
|
6880
7930
|
});
|
|
6881
|
-
`}function
|
|
7931
|
+
`}function jt(){return `
|
|
6882
7932
|
adminApp.post('/storage/directory', async (c) => {
|
|
6883
7933
|
const bucket = getStorageBucket(c);
|
|
6884
7934
|
if (!bucket) return c.text("Storage not configured", 400);
|
|
@@ -6904,7 +7954,7 @@ ${z()}`}function ke(t){return `
|
|
|
6904
7954
|
|
|
6905
7955
|
return c.redirect(prefixToStoragePath(prefix));
|
|
6906
7956
|
});
|
|
6907
|
-
`}function
|
|
7957
|
+
`}function Vt(){return `
|
|
6908
7958
|
adminApp.get('/storage/download', async (c) => {
|
|
6909
7959
|
const bucket = getStorageBucket(c);
|
|
6910
7960
|
if (!bucket) return c.text("Storage not configured", 400);
|
|
@@ -6924,7 +7974,7 @@ ${z()}`}function ke(t){return `
|
|
|
6924
7974
|
|
|
6925
7975
|
return new Response(object.body, { headers });
|
|
6926
7976
|
});
|
|
6927
|
-
`}function
|
|
7977
|
+
`}function Bt(){return `
|
|
6928
7978
|
adminApp.get('/storage/preview', async (c) => {
|
|
6929
7979
|
const bucket = getStorageBucket(c);
|
|
6930
7980
|
if (!bucket) return c.text("Storage not configured", 400);
|
|
@@ -6942,25 +7992,25 @@ ${z()}`}function ke(t){return `
|
|
|
6942
7992
|
|
|
6943
7993
|
return new Response(object.body, { headers });
|
|
6944
7994
|
});
|
|
6945
|
-
`}function
|
|
6946
|
-
${
|
|
7995
|
+
`}function Ht(){return `
|
|
7996
|
+
${Vt()}
|
|
6947
7997
|
|
|
6948
|
-
${
|
|
7998
|
+
${Bt()}
|
|
6949
7999
|
|
|
6950
|
-
${
|
|
8000
|
+
${Ot()}
|
|
6951
8001
|
|
|
6952
|
-
${
|
|
8002
|
+
${Ft()}
|
|
6953
8003
|
|
|
6954
|
-
${
|
|
8004
|
+
${jt()}
|
|
6955
8005
|
|
|
6956
|
-
${
|
|
6957
|
-
`}function
|
|
6958
|
-
${
|
|
8006
|
+
${Et()}
|
|
8007
|
+
`}function Wt(){return `
|
|
8008
|
+
${It()}
|
|
6959
8009
|
|
|
6960
|
-
${
|
|
8010
|
+
${Dt()}
|
|
6961
8011
|
|
|
6962
|
-
${
|
|
6963
|
-
`}function
|
|
8012
|
+
${Ht()}
|
|
8013
|
+
`}function Lt(e,t){let n=lt(t);return `
|
|
6964
8014
|
function Layout(props: { children: any; title: string; hideSidebar?: boolean }) {
|
|
6965
8015
|
return html\`<!DOCTYPE html>
|
|
6966
8016
|
<html lang="en" data-theme="light">
|
|
@@ -7150,7 +8200,7 @@ function Layout(props: { children: any; title: string; hideSidebar?: boolean })
|
|
|
7150
8200
|
</div>
|
|
7151
8201
|
<nav class="flex-1 overflow-y-auto px-2 pb-4">
|
|
7152
8202
|
<ul class="flex flex-col gap-0.5" id="table-list">
|
|
7153
|
-
${
|
|
8203
|
+
${e}
|
|
7154
8204
|
</ul>
|
|
7155
8205
|
</nav>
|
|
7156
8206
|
</div>
|
|
@@ -7335,7 +8385,7 @@ function Layout(props: { children: any; title: string; hideSidebar?: boolean })
|
|
|
7335
8385
|
</body>
|
|
7336
8386
|
</html>\`;
|
|
7337
8387
|
}
|
|
7338
|
-
`}function
|
|
8388
|
+
`}function zt(){return `
|
|
7339
8389
|
// Auth Middleware
|
|
7340
8390
|
adminApp.use('*', async (c, next) => {
|
|
7341
8391
|
const auth = createAuth({ DATABASE: c.env[options.databaseBinding] } as any, c.req.raw.cf as any);
|
|
@@ -7394,7 +8444,7 @@ function Layout(props: { children: any; title: string; hideSidebar?: boolean })
|
|
|
7394
8444
|
}
|
|
7395
8445
|
await next();
|
|
7396
8446
|
});
|
|
7397
|
-
`}function
|
|
8447
|
+
`}function Ut(e){return `
|
|
7398
8448
|
adminApp.get('/', (c) => {
|
|
7399
8449
|
return c.html(Layout({
|
|
7400
8450
|
title: "Admin Dashboard",
|
|
@@ -7405,28 +8455,28 @@ function Layout(props: { children: any; title: string; hideSidebar?: boolean })
|
|
|
7405
8455
|
<p class="text-base-content/50 text-sm">Select a collection to view and manage its data.</p>
|
|
7406
8456
|
</div>
|
|
7407
8457
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
7408
|
-
${
|
|
8458
|
+
${e}
|
|
7409
8459
|
</div>
|
|
7410
8460
|
</div>
|
|
7411
8461
|
\`
|
|
7412
8462
|
}));
|
|
7413
8463
|
});
|
|
7414
|
-
`}function
|
|
8464
|
+
`}function Qt(e,t,n){let r=it(t),a=st(r),o=ct(r),i=At(t),s=Pt(n),l=Wt(),u=Lt(a,n),c=zt(),f=Ut(o);return `import { Hono } from "hono";
|
|
7415
8465
|
import { html, raw } from "hono/html";
|
|
7416
8466
|
import { drizzle } from "drizzle-orm/d1";
|
|
7417
8467
|
import { eq, desc, asc, sql, like, or, inArray } from "drizzle-orm";
|
|
7418
8468
|
import { createAuth } from "./auth.config";
|
|
7419
|
-
import * as schema from "${
|
|
8469
|
+
import * as schema from "${e}";
|
|
7420
8470
|
import { users } from "./auth.schema";
|
|
7421
8471
|
|
|
7422
|
-
${
|
|
8472
|
+
${u}
|
|
7423
8473
|
|
|
7424
8474
|
export function registerAdminDashboard(app: Hono<any>, options: { databaseBinding: string, r2Binding?: string }) {
|
|
7425
8475
|
const adminApp = new Hono<any>();
|
|
7426
8476
|
|
|
7427
|
-
${
|
|
8477
|
+
${c}
|
|
7428
8478
|
|
|
7429
|
-
${
|
|
8479
|
+
${f}
|
|
7430
8480
|
|
|
7431
8481
|
// Generate table routes
|
|
7432
8482
|
${i}
|
|
@@ -7440,30 +8490,69 @@ ${g}
|
|
|
7440
8490
|
app.route('/admin', adminApp);
|
|
7441
8491
|
app.get('/admin/', (c) => c.redirect('/admin'));
|
|
7442
8492
|
}
|
|
7443
|
-
`}function
|
|
7444
|
-
`}function
|
|
7445
|
-
|
|
8493
|
+
`}function _(e){if(typeof e!="object"||e===null)return false;let t=e;return t.kind==="schema"&&typeof t.tables=="object"}function P(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 I(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=I(e,n.leftTable,n.leftReferenceField)??"string",a=I(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=I(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=I(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??P(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";
|
|
8494
|
+
`}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)}: {
|
|
8495
|
+
targetTable: ${h(i.targetTable)},
|
|
8496
|
+
junctionTable: ${h(i.junctionTable)},
|
|
8497
|
+
sourceField: ${h(i.sourceField??"")},
|
|
8498
|
+
targetField: ${h(i.targetField??"")},
|
|
8499
|
+
},`);a.length!==0&&t.push(`${h(n)}: {
|
|
8500
|
+
${a.map(o=>` ${o}`).join(`
|
|
8501
|
+
`)}
|
|
8502
|
+
},`);}return t.length===0?`export const __appflareManyToMany = {} as const;
|
|
8503
|
+
`:`export const __appflareManyToMany = {
|
|
8504
|
+
${t.map(n=>` ${n}`).join(`
|
|
8505
|
+
`)}
|
|
8506
|
+
} as const;
|
|
8507
|
+
`}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)}: {
|
|
8508
|
+
kind: "one",
|
|
8509
|
+
targetTable: ${h(i.targetTable)},
|
|
8510
|
+
sourceField: ${h(i.field??"")},
|
|
8511
|
+
referenceField: ${h(i.referenceField??"id")},
|
|
8512
|
+
},`);continue}if(i.relation==="many"){a.push(`${h(o)}: {
|
|
8513
|
+
kind: "many",
|
|
8514
|
+
targetTable: ${h(i.targetTable)},
|
|
8515
|
+
sourceField: ${h(i.field??"")},
|
|
8516
|
+
referenceField: ${h(i.referenceField??"id")},
|
|
8517
|
+
},`);continue}a.push(`${h(o)}: {
|
|
8518
|
+
kind: "manyToMany",
|
|
8519
|
+
targetTable: ${h(i.targetTable)},
|
|
8520
|
+
junctionTable: ${h(i.junctionTable??"")},
|
|
8521
|
+
sourceField: ${h(i.sourceField??"")},
|
|
8522
|
+
targetField: ${h(i.targetField??"")},
|
|
8523
|
+
referenceField: ${h(i.referenceField??"id")},
|
|
8524
|
+
targetReferenceField: ${h(i.targetReferenceField??"id")},
|
|
8525
|
+
},`);}a.length!==0&&t.push(`${h(n)}: {
|
|
8526
|
+
${a.map(o=>` ${o}`).join(`
|
|
8527
|
+
`)}
|
|
8528
|
+
},`);}return t.length===0?`export const __appflareRelations = {} as const;
|
|
8529
|
+
`:`export const __appflareRelations = {
|
|
8530
|
+
${t.map(n=>` ${n}`).join(`
|
|
8531
|
+
`)}
|
|
8532
|
+
} as const;
|
|
8533
|
+
`}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??P(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}_${P(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}_${P(b)}_idx`;c.push(` t.index(${h(R)}).on(table.${b})`);}u.push(` ${b}: ${x},`);}c.length>0?a.push(`export const ${i} = table(
|
|
8534
|
+
${h(l)},
|
|
7446
8535
|
{
|
|
7447
|
-
${
|
|
8536
|
+
${u.join(`
|
|
7448
8537
|
`)}
|
|
7449
8538
|
},
|
|
7450
8539
|
(table) => [
|
|
7451
|
-
${
|
|
8540
|
+
${c.join(`,
|
|
7452
8541
|
`)}
|
|
7453
8542
|
],
|
|
7454
|
-
);`):a.push(`export const ${i} = table(${
|
|
7455
|
-
${
|
|
8543
|
+
);`):a.push(`export const ${i} = table(${h(l)}, {
|
|
8544
|
+
${u.join(`
|
|
7456
8545
|
`)}
|
|
7457
|
-
});`);let
|
|
7458
|
-
fields: [${i}.${
|
|
7459
|
-
references: [${
|
|
7460
|
-
}),`);}for(let[
|
|
7461
|
-
${
|
|
8546
|
+
});`);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}, {
|
|
8547
|
+
fields: [${i}.${x.sourceField}],
|
|
8548
|
+
references: [${m.targetTable}.${x.targetField}],
|
|
8549
|
+
}),`);}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 }) => ({
|
|
8550
|
+
${w.join(`
|
|
7462
8551
|
`)}
|
|
7463
8552
|
}));`);}return `import * as t from "drizzle-orm/sqlite-core";
|
|
7464
8553
|
import { sqliteTable as table } from "drizzle-orm/sqlite-core";
|
|
7465
8554
|
import { relations } from "drizzle-orm";
|
|
7466
|
-
${
|
|
8555
|
+
${wr(r)}
|
|
7467
8556
|
${a.join(`
|
|
7468
8557
|
|
|
7469
8558
|
`)}
|
|
@@ -7471,7 +8560,11 @@ ${a.join(`
|
|
|
7471
8560
|
${o.join(`
|
|
7472
8561
|
|
|
7473
8562
|
`)}
|
|
7474
|
-
|
|
8563
|
+
|
|
8564
|
+
${Tr(e)}
|
|
8565
|
+
|
|
8566
|
+
${Rr(e)}
|
|
8567
|
+
`}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({
|
|
7475
8568
|
${o.join(`
|
|
7476
8569
|
`)}
|
|
7477
8570
|
});
|
|
@@ -7484,8 +8577,8 @@ export type ${a}Insert = z.infer<typeof ${n}InsertSchema>;
|
|
|
7484
8577
|
export type ${a}Select = z.infer<typeof ${n}SelectSchema>;
|
|
7485
8578
|
`);}return `import { z } from "zod";
|
|
7486
8579
|
|
|
7487
|
-
${
|
|
7488
|
-
`)}`}function
|
|
8580
|
+
${t.join(`
|
|
8581
|
+
`)}`}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} = {
|
|
7489
8582
|
${o.join(`
|
|
7490
8583
|
`)}
|
|
7491
8584
|
};
|
|
@@ -7493,14 +8586,14 @@ ${o.join(`
|
|
|
7493
8586
|
export type New${a} = {
|
|
7494
8587
|
${i.join(`
|
|
7495
8588
|
`)}
|
|
7496
|
-
};`);}return `${
|
|
8589
|
+
};`);}return `${t.join(`
|
|
7497
8590
|
|
|
7498
8591
|
`)}
|
|
7499
|
-
`}function xr(t,e){if(e){let n=t[e];if(!W(n))throw new Error(`schemaDsl.exportName '${e}' does not point to a schema() export.`);return n}for(let n of Object.values(t))if(W(n))return n;throw new Error("No schema() export found in schemaDsl entry module. Set schemaDsl.exportName to the correct export.")}async function Ke(t){let e=t.config.schemaDsl;if(!e)return;let n=e.namingStrategy??"camelToSnake",r=path.resolve(t.configDir,e.entry),a=path.resolve(t.configDir,e.outFile??path.resolve(t.outDirAbs,"schema.compiled.ts")),o=path.resolve(t.configDir,e.typesOutFile??path.resolve(t.outDirAbs,"schema.types.ts")),i=path.resolve(t.configDir,e.zodOutFile??path.resolve(t.outDirAbs,"schema.zod.ts")),l=await import(`${url.pathToFileURL(r).href}?t=${Date.now()}`),c=xr(l,e.exportName),d=cr(c);await Promise.all([promises.mkdir(path.dirname(a),{recursive:true}),promises.mkdir(path.dirname(o),{recursive:true}),promises.mkdir(path.dirname(i),{recursive:true})]);let g=fr(d,n),u=yr(d),y=hr(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 vr(t){return t.replaceAll("\\","/")}function S(t,e){let n=vr(path.relative(t,e)).replace(/\.tsx?$/,"");return n.startsWith(".")?n:`./${n}`}var Rr=new Set([".ts",".tsx",".mts",".cts"]);async function Ye(t){let e=await promises.readdir(t,{withFileTypes:true}),n=[];for(let r of e){if(r.name.startsWith(".")||r.name==="node_modules"||r.name==="_generated")continue;let a=path.resolve(t,r.name);if(r.isDirectory()){n.push(...await Ye(a));continue}r.isFile()&&Rr.has(path.extname(r.name))&&n.push(a);}return n}function Q(t){return t.replace(/\.[cm]?tsx?$/,"")}function Ar(t,e){let n=t,r=false,a,o="unknown";for(;m__namespace.isCallExpression(n);){let i=n.expression;if(!m__namespace.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__namespace.isStringLiteral(l)||m__namespace.isNumericLiteral(l)?a=l.text:l.kind===m__namespace.SyntaxKind.TrueKeyword?a="true":l.kind===m__namespace.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 $r(t){if(!t||!m__namespace.isObjectLiteralExpression(t))return [];let e=t.properties.find(r=>m__namespace.isPropertyAssignment(r)&&m__namespace.isIdentifier(r.name)&&r.name.text==="args");if(!e||!m__namespace.isObjectLiteralExpression(e.initializer))return [];let n=[];for(let r of e.initializer.properties)!m__namespace.isPropertyAssignment(r)||!m__namespace.isIdentifier(r.name)||n.push(Ar(r.initializer,r.name.text));return n}function Nr(t){return m__namespace.isVariableStatement(t)?t.modifiers?.some(e=>e.kind===m__namespace.SyntaxKind.ExportKeyword)??false:false}function Xe(t){return m__namespace.isIdentifier(t)?t.text:m__namespace.isParenthesizedExpression(t)?Xe(t.expression):null}function qr(t){if(!t||!m__namespace.isObjectLiteralExpression(t))return [];let e=t.properties.find(r=>!m__namespace.isPropertyAssignment(r)||!m__namespace.isIdentifier(r.name)?false:r.name.text==="cronTrigger");if(!e||!m__namespace.isPropertyAssignment(e))return [];let n=e.initializer;return m__namespace.isStringLiteral(n)||m__namespace.isNoSubstitutionTemplateLiteral(n)?[n.text.trim()].filter(r=>r.length>0):m__namespace.isArrayLiteralExpression(n)?n.elements.map(r=>m__namespace.isStringLiteral(r)||m__namespace.isNoSubstitutionTemplateLiteral(r)?r.text.trim():"").filter(r=>r.length>0):[]}function Cr(t,e){let n=m__namespace.createSourceFile(e,t,m__namespace.ScriptTarget.Latest,true,m__namespace.ScriptKind.TS),r=[];for(let a of n.statements)if(Nr(a))for(let o of a.declarationList.declarations){if(!m__namespace.isIdentifier(o.name)||!o.initializer||!m__namespace.isCallExpression(o.initializer))continue;let i=Xe(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"?qr(o.initializer.arguments[0]):[],args:i==="query"||i==="mutation"?$r(o.initializer.arguments[0]):[]});}return r}function Ge(t,e,n){let r=e.replace(/\\/g,"/"),o=Q(r).split("/").filter(Boolean);return `/${[t,...o,n].filter(Boolean).map(s=>s.trim()).filter(s=>s.length>0).join("/")}`}function Pr(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 Je(t,e){let n=t.replace(/\\/g,"/"),a=Q(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 tn(t){let e=[],n=await Ye(t.scanDirAbs).catch(()=>[]);for(let a of n){let o=Bun.file(a);if(!await o.exists())continue;let i=await o.text(),s=path.relative(t.scanDirAbs,a),l=Cr(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=Pr(s,d.kindDirectory);for(let u of d.exports){let y=d.kind==="query"||d.kind==="mutation"?Je(g,u.exportName):void 0,h=d.kind==="scheduler"||d.kind==="cron"?Je(g,u.exportName):void 0,f=d.kind==="query"||d.kind==="mutation"?[...Q(g).split("/").filter(Boolean),u.exportName]:void 0,b=d.kind==="query"?Ge("queries",g,u.exportName):d.kind==="mutation"?Ge("mutations",g,u.exportName):d.kind==="storage"?`/storage/managers/${u.exportName}`:`/${d.kindDirectory}/${h}`;e.push({kind:d.kind,exportName:u.exportName,filePath:a,importPath:S(t.outDirAbs,a),clientImportPath:S(path.resolve(t.outDirAbs,"client"),a),routePath:b,handlerName:y,clientSegments:f,taskName:h,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 Dr(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 Or(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 Ir(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=Dr(t),n=[];for(let r of e){let a=Or(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;n.push({name:o,expression:i,type:Ir(i),optional:g,primaryKey:s,autoIncrement:l});}return n}function Fr(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 nn(t){let e=await promises.readdir(t,{withFileTypes:true}),n=[];for(let r of e){if(r.name.startsWith(".")||r.name==="node_modules"||r.name==="_generated")continue;let a=path.resolve(t,r.name);if(r.isDirectory()){n.push(...await nn(a));continue}r.isFile()&&r.name==="schema.ts"&&n.push(a);}return n}async function rn(t,e=[]){let n=await nn(t.scanDirAbs).catch(()=>[]),r=path.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=Fr(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 jr(t,e){let n=path.relative(t,e).replace(/\\/g,"/");return n.startsWith(".")?n:`./${n}`}async function an(t){let{outDirAbs:e,wranglerOutDirAbs:n,config:r,configPath:a,configDir:o}=t,i=S(e,a),s=path.resolve(e,"client"),l=S(s,a);await Promise.all([promises.mkdir(e,{recursive:true}),promises.mkdir(s,{recursive:true}),promises.mkdir(n,{recursive:true})]);let c=path.resolve(e,"server.ts"),d=path.resolve(e,"client.ts"),g=path.resolve(e,"auth.config.ts"),u=path.resolve(e,"auth.schema.ts"),y=path.resolve(e,"drizzle.config.ts"),h=path.resolve(n,"wrangler.json"),f=await Ke(t),b=await rn(t,f?[f.schemaPath]:[]),R=S(e,b.schemaPath),v=await tn(t),fn=Yt(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),hn=rt(l,v),bn=F(R,v,r.r2[0]?.binding),yn=J(i),xn=f?[jr(o,f.schemaPath),...r.schema.filter(k=>!/(^|\/)schema\.ts$/.test(k))]:r.schema,wn=at(xn),vn=te(t,v),kn=Ve(R,b,v),Tn=path.resolve(e,"admin.routes.ts"),Sn=bn.map(k=>Bun.write(path.resolve(e,k.relativePath),k.source)),Rn=hn.map(k=>Bun.write(path.resolve(e,k.relativePath),k.source));await Promise.all([Bun.write(c,fn),Bun.write(d,`export * from "./client/index";
|
|
7500
|
-
`),...
|
|
7501
|
-
`),Bun.write(
|
|
7502
|
-
`);return}process.stdout.write(`\u2705 Generated server/client in ${
|
|
7503
|
-
`);}async function
|
|
7504
|
-
`);}finally{r=false,a&&(a=false,await o());}};
|
|
8592
|
+
`}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=path.resolve(e.configDir,t.entry),a=path.resolve(e.configDir,t.outFile??path.resolve(e.outDirAbs,"schema.compiled.ts")),o=path.resolve(e.configDir,t.typesOutFile??path.resolve(e.outDirAbs,"schema.types.ts")),i=path.resolve(e.configDir,t.zodOutFile??path.resolve(e.outDirAbs,"schema.zod.ts")),l=await import(`${url.pathToFileURL(r).href}?t=${Date.now()}`),u=$r(l,t.exportName),c=hr(u);await Promise.all([promises.mkdir(path.dirname(a),{recursive:true}),promises.mkdir(path.dirname(o),{recursive:true}),promises.mkdir(path.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 Cr(e){return e.replaceAll("\\","/")}function A(e,t){let n=Cr(path.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 promises.readdir(e,{withFileTypes:true}),n=[];for(let r of t){if(r.name.startsWith(".")||r.name==="node_modules"||r.name==="_generated")continue;let a=path.resolve(e,r.name);if(r.isDirectory()){n.push(...await rn(a));continue}r.isFile()&&Dr.has(path.extname(r.name))&&n.push(a);}return n}function Z(e){return e.replace(/\.[cm]?tsx?$/,"")}function Er(e,t){let n=e,r=false,a,o="unknown";for(;g__namespace.isCallExpression(n);){let i=n.expression;if(!g__namespace.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__namespace.isStringLiteral(l)||g__namespace.isNumericLiteral(l)?a=l.text:l.kind===g__namespace.SyntaxKind.TrueKeyword?a="true":l.kind===g__namespace.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 Or(e){if(!e||!g__namespace.isObjectLiteralExpression(e))return [];let t=e.properties.find(r=>g__namespace.isPropertyAssignment(r)&&g__namespace.isIdentifier(r.name)&&r.name.text==="args");if(!t||!g__namespace.isObjectLiteralExpression(t.initializer))return [];let n=[];for(let r of t.initializer.properties)!g__namespace.isPropertyAssignment(r)||!g__namespace.isIdentifier(r.name)||n.push(Er(r.initializer,r.name.text));return n}function Fr(e){return g__namespace.isVariableStatement(e)?e.modifiers?.some(t=>t.kind===g__namespace.SyntaxKind.ExportKeyword)??false:false}function an(e){return g__namespace.isIdentifier(e)?e.text:g__namespace.isParenthesizedExpression(e)?an(e.expression):null}function jr(e){if(!e||!g__namespace.isObjectLiteralExpression(e))return [];let t=e.properties.find(r=>!g__namespace.isPropertyAssignment(r)||!g__namespace.isIdentifier(r.name)?false:r.name.text==="cronTrigger");if(!t||!g__namespace.isPropertyAssignment(t))return [];let n=t.initializer;return g__namespace.isStringLiteral(n)||g__namespace.isNoSubstitutionTemplateLiteral(n)?[n.text.trim()].filter(r=>r.length>0):g__namespace.isArrayLiteralExpression(n)?n.elements.map(r=>g__namespace.isStringLiteral(r)||g__namespace.isNoSubstitutionTemplateLiteral(r)?r.text.trim():"").filter(r=>r.length>0):[]}function Vr(e,t){let n=g__namespace.createSourceFile(t,e,g__namespace.ScriptTarget.Latest,true,g__namespace.ScriptKind.TS),r=[];for(let a of n.statements)if(Fr(a))for(let o of a.declarationList.declarations){if(!g__namespace.isIdentifier(o.name)||!o.initializer||!g__namespace.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"?Or(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=path.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(path.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 promises.readdir(e,{withFileTypes:true}),n=[];for(let r of t){if(r.name.startsWith(".")||r.name==="node_modules"||r.name==="_generated")continue;let a=path.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=path.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=path.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=path.resolve(t,"client"),l=A(s,a);await Promise.all([promises.mkdir(t,{recursive:true}),promises.mkdir(s,{recursive:true}),promises.mkdir(n,{recursive:true})]);let u=path.resolve(t,"server.ts"),c=path.resolve(t,"client.ts"),f=path.resolve(t,"auth.config.ts"),d=path.resolve(t,"auth.schema.ts"),y=path.resolve(t,"drizzle.config.ts"),w=path.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=path.resolve(t,"admin.routes.ts"),$n=vn.map(k=>Bun.write(path.resolve(t,k.relativePath),k.source)),qn=xn.map(k=>Bun.write(path.resolve(t,k.relativePath),k.source));await Promise.all([Bun.write(u,R),Bun.write(c,`export * from "./client/index";
|
|
8593
|
+
`),...qn,...$n,Bun.write(f,Tn),Bun.write(d,""),Bun.write(y,kn),Bun.write(w,`${JSON.stringify(Sn,null,2)}
|
|
8594
|
+
`),Bun.write(Nn,An)]);let F=path.relative(o,f).replace(/\\/g,"/"),Cn=F.startsWith(".")?F:`./${F}`,j=path.relative(o,d).replace(/\\/g,"/"),Mn=j.startsWith(".")?j:`./${j}`,ee=await Bun.spawn(["npx","@better-auth/cli","generate","--config",Cn,"--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=zod.z.object({binding:zod.z.string().min(1),databaseName:zod.z.string().min(1),databaseId:zod.z.string().min(1),previewDatabaseId:zod.z.string().min(1).optional(),migrationsDir:zod.z.string().min(1).optional()}).strict(),pn=zod.z.object({binding:zod.z.string().min(1),id:zod.z.string().min(1),previewId:zod.z.string().min(1).optional()}).strict(),mn=zod.z.object({binding:zod.z.string().min(1),bucketName:zod.z.string().min(1),previewBucketName:zod.z.string().min(1).optional(),jurisdiction:zod.z.string().min(1).optional()}).strict(),gn=zod.z.object({enabled:zod.z.boolean().optional(),binding:zod.z.string().min(1).optional(),queue:zod.z.string().min(1).optional()}).strict(),Zr=zod.z.object({enabled:zod.z.boolean().optional(),binding:zod.z.string().min(1).optional(),className:zod.z.string().min(1).optional(),objectName:zod.z.string().min(1).optional(),subscribePath:zod.z.string().min(1).optional(),websocketPath:zod.z.string().min(1).optional(),protocol:zod.z.string().min(1).optional()}).strict(),Yr=zod.z.object({scanDir:zod.z.string().min(1),outDir:zod.z.string().min(1),wranglerOutDir:zod.z.string().min(1).optional(),wranglerOutPath:zod.z.string().min(1).optional(),schema:zod.z.array(zod.z.string()).min(1),schemaDsl:zod.z.object({entry:zod.z.string().min(1),exportName:zod.z.string().min(1).optional(),outFile:zod.z.string().min(1).optional(),typesOutFile:zod.z.string().min(1).optional(),zodOutFile:zod.z.string().min(1).optional(),namingStrategy:zod.z.literal("camelToSnake").optional()}).strict().optional(),database:zod.z.union([dn,zod.z.array(dn).min(1)]),kv:zod.z.union([pn,zod.z.array(pn)]).optional(),r2:zod.z.union([mn,zod.z.array(mn)]).optional(),auth:zod.z.object({enabled:zod.z.boolean(),basePath:zod.z.string().min(1),options:zod.z.custom(e=>typeof e=="object"&&e!==null),clientOptions:zod.z.custom(e=>typeof e=="object"&&e!==null)}).strict(),scheduler:gn.optional(),realtime:Zr.optional(),wranglerOverrides:zod.z.record(zod.z.string(),zod.z.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=path.isAbsolute(e??"")?e:path.resolve(process.cwd(),e??"appflare.config.ts"),n=path.dirname(t),o=(await import(url.pathToFileURL(t).href)).default,i=Yr.parse(o),s=ta(i);return {configPath:t,configDir:n,scanDirAbs:path.resolve(n,s.scanDir),outDirAbs:path.resolve(n,s.outDir),wranglerOutDirAbs:path.resolve(n,s.wranglerOutDir),config:s}}function oa(e){let t=e;for(;;){if(fs.existsSync(path.resolve(t,"package.json")))return t;let n=path.dirname(t);if(n===t)return e;t=n;}}async function O(e){let t=await q(e);if(await un(t),t.wranglerOutDirAbs===t.outDirAbs){process.stdout.write(`\u2705 Generated artifacts in ${t.outDirAbs}
|
|
8595
|
+
`);return}process.stdout.write(`\u2705 Generated server/client in ${t.outDirAbs} and wrangler.json in ${t.wranglerOutDirAbs}
|
|
8596
|
+
`);}async function bn(e,t=false){if(await O(e),!t)return;let n=await q(e),r=false,a=false,o=async()=>{if(r){a=true;return}r=true;try{await O(e);}catch(s){process.stderr.write(`\u274C Build failed: ${s.message}
|
|
8597
|
+
`);}finally{r=false,a&&(a=false,await o());}};na__default.default.watch(n.scanDirAbs,{ignoreInitial:true}).on("all",async(s,l)=>{process.stdout.write(`\u{1F504} Change detected: ${l}
|
|
7505
8598
|
`),await o();}),process.stdout.write(`\u{1F440} Watching ${n.scanDirAbs}
|
|
7506
|
-
`);}async function
|
|
8599
|
+
`);}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=path.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 commander.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 O(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);});
|