arkormx 2.11.12 → 2.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,11 +1,13 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_relationship = require('./relationship-BIie-GXN.cjs');
2
+ const require_relationship = require('./relationship-BoQDV6gx.cjs');
3
3
  let pg = require("pg");
4
4
  let node_path = require("node:path");
5
+ let node_fs = require("node:fs");
6
+ let jiti = require("jiti");
7
+ let node_url = require("node:url");
5
8
  let module$1 = require("module");
6
9
  let fs = require("fs");
7
10
  let path = require("path");
8
- let node_fs = require("node:fs");
9
11
  let _h3ravel_support = require("@h3ravel/support");
10
12
  let node_async_hooks = require("node:async_hooks");
11
13
  let kysely = require("kysely");
@@ -635,6 +637,15 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
635
637
  mapColumn(target, column) {
636
638
  return target.columns?.[column] ?? column;
637
639
  }
640
+ buildIdentifierReference(target, reference) {
641
+ const segments = reference.split(".");
642
+ if (segments.length === 1) return kysely.sql.ref(this.mapColumn(target, reference));
643
+ const column = segments.pop();
644
+ const table = segments.join(".");
645
+ const mappedTable = this.mapping[table] ?? table;
646
+ const mappedColumn = mappedTable === (target.table ? this.mapping[target.table] ?? target.table : void 0) ? this.mapColumn(target, column) : column;
647
+ return this.buildColumnReference(mappedTable, mappedColumn);
648
+ }
638
649
  reverseColumnMap(target) {
639
650
  return Object.entries(target.columns ?? {}).reduce((all, [attribute, column]) => {
640
651
  all[column] = attribute;
@@ -658,29 +669,31 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
658
669
  return mapped;
659
670
  }, {});
660
671
  }
661
- buildSelectList(target, columns) {
662
- if (!columns || columns.length === 0) return kysely.sql.raw("*");
672
+ buildSelectList(target, columns, qualifyColumns = false) {
673
+ const table = this.resolveTable(target);
674
+ if (!columns || columns.length === 0) return qualifyColumns ? kysely.sql`${kysely.sql.table(table)}.*` : kysely.sql.raw("*");
663
675
  return kysely.sql.join(columns.map(({ column, alias, raw, wildcard, expression }) => {
664
- if (wildcard) return kysely.sql.raw("*");
676
+ if (wildcard) return qualifyColumns ? kysely.sql`${kysely.sql.table(table)}.*` : kysely.sql.raw("*");
665
677
  if (expression) {
666
678
  const compiled = this.buildExpression(target, expression);
667
679
  const resultAlias = alias ?? column;
668
680
  return resultAlias ? kysely.sql`${compiled} as ${kysely.sql.id(resultAlias)}` : compiled;
669
681
  }
670
682
  if (raw) {
671
- const rawExpression = kysely.sql.raw(column);
683
+ const rawExpression = /^[A-Za-z_][\w]*(?:\.[A-Za-z_][\w]*)+$/.test(column) ? this.buildIdentifierReference(target, column) : kysely.sql.raw(column);
672
684
  return alias ? kysely.sql`${rawExpression} as ${kysely.sql.id(alias)}` : rawExpression;
673
685
  }
674
686
  const mappedColumn = this.mapColumn(target, column);
675
687
  const resultAlias = alias ?? column;
676
- if (mappedColumn === resultAlias) return kysely.sql.ref(mappedColumn);
677
- return kysely.sql`${kysely.sql.ref(mappedColumn)} as ${kysely.sql.id(resultAlias)}`;
688
+ const reference = qualifyColumns ? this.buildColumnReference(table, mappedColumn) : kysely.sql.ref(mappedColumn);
689
+ if (mappedColumn === resultAlias) return reference;
690
+ return kysely.sql`${reference} as ${kysely.sql.id(resultAlias)}`;
678
691
  }));
679
692
  }
680
- buildOrderBy(target, orderBy) {
693
+ buildOrderBy(target, orderBy, qualifyColumns = false) {
681
694
  if (!orderBy || orderBy.length === 0) return kysely.sql``;
682
695
  return kysely.sql` order by ${kysely.sql.join(orderBy.map(({ column, direction, expression }) => {
683
- return kysely.sql`${expression ? this.buildExpression(target, expression) : kysely.sql.ref(this.mapColumn(target, column))} ${kysely.sql.raw(direction === "desc" ? "desc" : "asc")}`;
696
+ return kysely.sql`${expression ? this.buildExpression(target, expression) : qualifyColumns ? this.buildColumnReference(this.resolveTable(target), this.mapColumn(target, column)) : kysely.sql.ref(this.mapColumn(target, column))} ${kysely.sql.raw(direction === "desc" ? "desc" : "asc")}`;
684
697
  }), kysely.sql`, `)}`;
685
698
  }
686
699
  buildGroupBy(target, groupBy) {
@@ -735,7 +748,7 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
735
748
  return kysely.sql`${kysely.sql.join(parts, kysely.sql``)}`;
736
749
  }
737
750
  buildJoinConstraint(target, constraint) {
738
- if (constraint.type === "column") return kysely.sql`${kysely.sql.ref(constraint.first)} ${kysely.sql.raw(constraint.operator)} ${kysely.sql.ref(constraint.second)}`;
751
+ if (constraint.type === "column") return kysely.sql`${this.buildIdentifierReference(target, constraint.first)} ${kysely.sql.raw(constraint.operator)} ${this.buildIdentifierReference(target, constraint.second)}`;
739
752
  if (constraint.type === "null") return constraint.not ? kysely.sql`${kysely.sql.ref(constraint.column)} is not null` : kysely.sql`${kysely.sql.ref(constraint.column)} is null`;
740
753
  if (constraint.type === "raw") return this.buildRawWhereCondition({
741
754
  type: "raw",
@@ -743,7 +756,7 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
743
756
  bindings: constraint.bindings
744
757
  });
745
758
  if (constraint.type === "nested") return kysely.sql`(${this.buildJoinConstraints(target, constraint.constraints)})`;
746
- const column = kysely.sql.ref(constraint.column);
759
+ const column = this.buildIdentifierReference(target, constraint.column);
747
760
  const operator = constraint.operator;
748
761
  if (operator === "is-null") return kysely.sql`${column} is null`;
749
762
  if (operator === "is-not-null") return kysely.sql`${column} is not null`;
@@ -765,7 +778,7 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
765
778
  return typeof value === "undefined" ? [] : [value];
766
779
  }
767
780
  buildComparisonCondition(target, condition) {
768
- const column = kysely.sql.ref(this.mapColumn(target, condition.column));
781
+ const column = this.buildIdentifierReference(target, condition.column);
769
782
  if (condition.operator === "is-null") return kysely.sql`${column} is null`;
770
783
  if (condition.operator === "is-not-null") return kysely.sql`${column} is not null`;
771
784
  if (condition.operator === "in") {
@@ -1198,6 +1211,30 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
1198
1211
  ${this.buildOrderBy(spec.target, spec.orderBy)}
1199
1212
  ${this.buildPaginationClause(spec)}
1200
1213
  `;
1214
+ }
1215
+ buildPartitionedSelectStatement(spec) {
1216
+ const table = this.resolveTable(spec.target);
1217
+ const rankedAlias = "__arkorm_partitioned";
1218
+ const rowAlias = "__arkorm_partition_row";
1219
+ const offset = Math.max(0, spec.perPartitionOffset ?? 0);
1220
+ const upperBound = offset + Math.max(0, spec.perPartitionLimit);
1221
+ const partitionColumns = spec.partitionBy.map((column) => this.buildIdentifierReference(spec.target, column));
1222
+ const orderBy = spec.orderBy && spec.orderBy.length > 0 ? this.buildOrderBy(spec.target, spec.orderBy, true) : kysely.sql` order by ${this.buildColumnReference(table, this.resolvePrimaryKey(spec.target))} asc`;
1223
+ return kysely.sql`
1224
+ select *
1225
+ from (
1226
+ select ${spec.distinct ? kysely.sql`distinct ` : kysely.sql``}${this.buildSelectList(spec.target, spec.columns, true)}
1227
+ ${this.buildRelationAggregateSelectList(spec.target, spec.relationAggregates)},
1228
+ row_number() over (
1229
+ partition by ${kysely.sql.join(partitionColumns, kysely.sql`, `)}${orderBy}
1230
+ ) as ${kysely.sql.id(rowAlias)}
1231
+ from ${kysely.sql.table(table)}
1232
+ ${this.buildJoinClause(spec.target, spec.joins)}
1233
+ ${this.buildCombinedWhereClause(spec.target, spec.where, spec.relationFilters)}
1234
+ ) as ${kysely.sql.table(rankedAlias)}
1235
+ where ${kysely.sql.ref(rowAlias)} > ${offset} and ${kysely.sql.ref(rowAlias)} <= ${upperBound}
1236
+ order by ${kysely.sql.ref(rowAlias)} asc
1237
+ `;
1201
1238
  }
1202
1239
  buildCountStatement(spec) {
1203
1240
  return kysely.sql`
@@ -1299,6 +1336,20 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
1299
1336
  offset: spec.offset
1300
1337
  });
1301
1338
  }
1339
+ async selectPerPartition(spec) {
1340
+ if (spec.partitionBy.length === 0) return await this.select(spec);
1341
+ return await this.executeWithDebug("select", spec.target, this.buildPartitionedSelectStatement(spec), (rows) => this.mapRows(spec.target, rows.map((row) => {
1342
+ const { __arkorm_partition_row: _partitionRow, ...attributes } = row;
1343
+ return attributes;
1344
+ })), {
1345
+ where: spec.where,
1346
+ relationFilters: spec.relationFilters,
1347
+ orderBy: spec.orderBy,
1348
+ partitionBy: spec.partitionBy,
1349
+ perPartitionLimit: spec.perPartitionLimit,
1350
+ perPartitionOffset: spec.perPartitionOffset
1351
+ });
1352
+ }
1302
1353
  /**
1303
1354
  * Selects a single record from the database matching the specified criteria and returns it as
1304
1355
  * a database row. If multiple records match the criteria, only the first one is returned.
@@ -2331,6 +2382,92 @@ const createPrismaDatabaseAdapter = (prisma, mapping = {}) => {
2331
2382
  */
2332
2383
  const createPrismaCompatibilityAdapter = createPrismaDatabaseAdapter;
2333
2384
 
2385
+ //#endregion
2386
+ //#region src/helpers/model-resolver.ts
2387
+ const modelExtensions = [
2388
+ ".ts",
2389
+ ".tsx",
2390
+ ".mts",
2391
+ ".cts",
2392
+ ".js",
2393
+ ".mjs",
2394
+ ".cjs"
2395
+ ];
2396
+ const isModelModule = (value) => typeof value === "object" && value !== null;
2397
+ const isModelConstructor = (value) => {
2398
+ if (typeof value !== "function") return false;
2399
+ const candidate = value;
2400
+ return typeof candidate.query === "function" && typeof candidate.hydrate === "function" && typeof candidate.getTable === "function" && typeof candidate.getPrimaryKey === "function";
2401
+ };
2402
+ const resolveModelExport = (module, modelName) => {
2403
+ if (!isModelModule(module)) return module;
2404
+ return module.default ?? module[modelName] ?? module;
2405
+ };
2406
+ const resolveRuntimeDirectory = (directory) => {
2407
+ if ((0, node_fs.existsSync)(directory)) return directory;
2408
+ const buildOutput = require_relationship.getUserConfig("paths")?.buildOutput;
2409
+ if (typeof buildOutput !== "string" || buildOutput.trim().length === 0) return directory;
2410
+ const relativeSource = (0, node_path.relative)(process.cwd(), directory);
2411
+ if (!relativeSource || relativeSource.startsWith("..")) return directory;
2412
+ const mappedDirectory = (0, node_path.join)(buildOutput, relativeSource);
2413
+ return (0, node_fs.existsSync)(mappedDirectory) ? mappedDirectory : directory;
2414
+ };
2415
+ const resolveRuntimeModelPath = (sourcePath) => {
2416
+ const extension = (0, node_path.extname)(sourcePath).toLowerCase();
2417
+ const candidates = [];
2418
+ if (modelExtensions.includes(extension)) candidates.push(sourcePath);
2419
+ else candidates.push(...modelExtensions.map((modelExtension) => `${sourcePath}${modelExtension}`));
2420
+ const buildOutput = require_relationship.getUserConfig("paths")?.buildOutput;
2421
+ if (typeof buildOutput === "string" && buildOutput.trim().length > 0) candidates.slice().forEach((candidate) => {
2422
+ const relativeSource = (0, node_path.relative)(process.cwd(), candidate);
2423
+ if (!relativeSource || relativeSource.startsWith("..")) return;
2424
+ const mappedFile = (0, node_path.join)(buildOutput, relativeSource);
2425
+ const mappedExtension = (0, node_path.extname)(mappedFile).toLowerCase();
2426
+ if ([
2427
+ ".ts",
2428
+ ".tsx",
2429
+ ".mts",
2430
+ ".cts"
2431
+ ].includes(mappedExtension)) {
2432
+ const base = mappedFile.slice(0, -mappedExtension.length);
2433
+ candidates.push(`${base}.js`, `${base}.mjs`, `${base}.cjs`);
2434
+ return;
2435
+ }
2436
+ candidates.push(mappedFile);
2437
+ });
2438
+ return candidates.find((candidate) => (0, node_fs.existsSync)(candidate)) ?? sourcePath;
2439
+ };
2440
+ const getModelDirectories = () => {
2441
+ const configured = require_relationship.getUserConfig("paths")?.models;
2442
+ const registered = require_relationship.getRegisteredPaths("models");
2443
+ return [...typeof configured === "string" ? [configured] : [], ...registered].map((directory) => resolveRuntimeDirectory((0, node_path.isAbsolute)(directory) ? directory : (0, node_path.resolve)(directory))).filter((directory, index, all) => all.indexOf(directory) === index);
2444
+ };
2445
+ const loadModel = (modelName, exportName) => {
2446
+ const jiti$1 = (0, jiti.createJiti)(`${(0, node_url.pathToFileURL)((0, node_path.resolve)(".")).href}/`, {
2447
+ interopDefault: false,
2448
+ tsconfigPaths: true,
2449
+ sourceMaps: true
2450
+ });
2451
+ for (const directory of getModelDirectories()) {
2452
+ const modulePath = resolveRuntimeModelPath((0, node_path.join)(directory, modelName));
2453
+ if (!(0, node_fs.existsSync)(modulePath)) continue;
2454
+ const model = resolveModelExport(jiti$1(modulePath), exportName);
2455
+ if (!isModelConstructor(model)) continue;
2456
+ require_relationship.registerModels(model);
2457
+ return model;
2458
+ }
2459
+ };
2460
+ function getModel(modelName) {
2461
+ const normalized = modelName.trim();
2462
+ const exportName = normalized.replace(/\\/g, "/").split("/").pop()?.replace(/\.[^.]+$/, "");
2463
+ if (!normalized || !exportName) throw new Error("Model name is required.");
2464
+ const registeredModel = require_relationship.getRegisteredModels().find((model) => model.name === exportName);
2465
+ if (registeredModel) return registeredModel;
2466
+ const model = loadModel(normalized, exportName);
2467
+ if (model) return model;
2468
+ throw new Error(`Model "${modelName}" not found.`);
2469
+ }
2470
+
2334
2471
  //#endregion
2335
2472
  //#region src/Arkorm.ts
2336
2473
  var Arkorm = class Arkorm {
@@ -2350,6 +2487,7 @@ var Arkorm = class Arkorm {
2350
2487
  this.getRegisteredMigrations = Arkorm.getRegisteredMigrations;
2351
2488
  this.getRegisteredSeeders = Arkorm.getRegisteredSeeders;
2352
2489
  this.getRegisteredModels = Arkorm.getRegisteredModels;
2490
+ this.getModel = Arkorm.getModel;
2353
2491
  this.getRegisteredFactories = Arkorm.getRegisteredFactories;
2354
2492
  }
2355
2493
  /**
@@ -2477,6 +2615,9 @@ var Arkorm = class Arkorm {
2477
2615
  static getRegisteredModels() {
2478
2616
  return require_relationship.getRegisteredModels();
2479
2617
  }
2618
+ static {
2619
+ this.getModel = getModel;
2620
+ }
2480
2621
  /**
2481
2622
  * Get registered factory constructors or instances.
2482
2623
  *
@@ -3107,6 +3248,58 @@ var CliApp = class {
3107
3248
  skipped
3108
3249
  };
3109
3250
  }
3251
+ resolveModelFiles(modelsDir) {
3252
+ if (!(0, fs.existsSync)(modelsDir)) throw new Error(`Models directory not found: ${modelsDir}`);
3253
+ return (0, fs.readdirSync)(modelsDir).filter((file) => file.endsWith(".ts")).map((file) => (0, path.join)(modelsDir, file));
3254
+ }
3255
+ syncModelRegistryTypes(modelFiles) {
3256
+ const registryDir = (0, path.join)((0, fs.realpathSync)(process.cwd()), ".arkormx");
3257
+ const registryPath = (0, path.join)(registryDir, "models.d.ts");
3258
+ const models = modelFiles.map((filePath) => {
3259
+ const parsed = this.parseModelSyncSource((0, fs.readFileSync)(filePath, "utf-8"));
3260
+ if (!parsed) return null;
3261
+ return {
3262
+ className: parsed.className,
3263
+ importPath: this.resolveModelRegistryImportPath(registryPath, filePath)
3264
+ };
3265
+ }).filter((model) => model !== null).sort((left, right) => left.className.localeCompare(right.className));
3266
+ const importLines = models.map((model) => {
3267
+ return `import type { ${model.className} } from '${model.importPath}'`;
3268
+ });
3269
+ const registryLines = models.map((model) => {
3270
+ return ` ${model.className}: typeof ${model.className}`;
3271
+ });
3272
+ const content = [
3273
+ "/* eslint-disable */",
3274
+ "// This file is generated by `arkorm models:sync`.",
3275
+ ...importLines,
3276
+ "",
3277
+ "declare module 'arkormx' {",
3278
+ " interface ArkormModelRegistry {",
3279
+ ...registryLines,
3280
+ " }",
3281
+ "}",
3282
+ "",
3283
+ "export {}",
3284
+ ""
3285
+ ].join("\n");
3286
+ if (((0, fs.existsSync)(registryPath) ? (0, fs.readFileSync)(registryPath, "utf-8") : null) === content) return {
3287
+ path: registryPath,
3288
+ updated: false
3289
+ };
3290
+ (0, fs.mkdirSync)(registryDir, { recursive: true });
3291
+ (0, fs.writeFileSync)(registryPath, content);
3292
+ return {
3293
+ path: registryPath,
3294
+ updated: true
3295
+ };
3296
+ }
3297
+ resolveModelRegistryImportPath(registryPath, modelPath) {
3298
+ const realModelPath = (0, fs.realpathSync)(modelPath);
3299
+ const withoutExtension = realModelPath.slice(0, -(0, path.extname)(realModelPath).length);
3300
+ const relativePath = (0, path.relative)((0, path.dirname)(registryPath), withoutExtension).replace(/\\/g, "/");
3301
+ return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
3302
+ }
3110
3303
  applyPersistedFieldMetadata(structure) {
3111
3304
  const persistedMetadata = require_relationship.getPersistedTableMetadata(structure.table, {
3112
3305
  features: require_relationship.resolvePersistedMetadataFeatures(this.getConfig("features")),
@@ -3284,8 +3477,7 @@ var CliApp = class {
3284
3477
  }
3285
3478
  async syncModels(options = {}) {
3286
3479
  const modelsDir = options.modelsDir ?? this.resolveConfigPath("models", (0, path.join)(process.cwd(), "src", "models"));
3287
- if (!(0, fs.existsSync)(modelsDir)) throw new Error(`Models directory not found: ${modelsDir}`);
3288
- const modelFiles = (0, fs.readdirSync)(modelsDir).filter((file) => file.endsWith(".ts")).map((file) => (0, path.join)(modelsDir, file));
3480
+ const modelFiles = this.resolveModelFiles(modelsDir);
3289
3481
  const adapter = this.getConfig("adapter");
3290
3482
  if (adapter && typeof adapter.introspectModels === "function") {
3291
3483
  const sources = modelFiles.reduce((all, filePath) => {
@@ -3302,11 +3494,13 @@ var CliApp = class {
3302
3494
  const parsed = sources.get(filePath);
3303
3495
  return parsed ? structuresByTable.get(parsed.table) : void 0;
3304
3496
  }, /* @__PURE__ */ new Map());
3497
+ const modelTypes = this.syncModelRegistryTypes(modelFiles);
3305
3498
  return {
3306
3499
  source: "adapter",
3307
3500
  modelsDir,
3501
+ modelTypesPath: modelTypes.path,
3308
3502
  total: modelFiles.length,
3309
- updated: result.updated,
3503
+ updated: modelTypes.updated ? [...result.updated, modelTypes.path] : result.updated,
3310
3504
  skipped: result.skipped
3311
3505
  };
3312
3506
  }
@@ -3315,6 +3509,19 @@ var CliApp = class {
3315
3509
  ...this.syncModelsFromPrisma(options)
3316
3510
  };
3317
3511
  }
3512
+ syncModelRegistry(options = {}) {
3513
+ const modelsDir = options.modelsDir ?? this.resolveConfigPath("models", (0, path.join)(process.cwd(), "src", "models"));
3514
+ const modelFiles = this.resolveModelFiles(modelsDir);
3515
+ const modelTypes = this.syncModelRegistryTypes(modelFiles);
3516
+ return {
3517
+ source: "registry",
3518
+ modelsDir,
3519
+ modelTypesPath: modelTypes.path,
3520
+ total: modelFiles.length,
3521
+ updated: modelTypes.updated ? [modelTypes.path] : [],
3522
+ skipped: []
3523
+ };
3524
+ }
3318
3525
  /**
3319
3526
  * Sync model attribute declarations in model files based on the Prisma schema.
3320
3527
  * This method reads the Prisma schema to extract model definitions and their
@@ -3330,21 +3537,22 @@ var CliApp = class {
3330
3537
  const schemaPath = options.schemaPath ?? (0, path.join)(process.cwd(), "prisma", "schema.prisma");
3331
3538
  const modelsDir = options.modelsDir ?? this.resolveConfigPath("models", (0, path.join)(process.cwd(), "src", "models"));
3332
3539
  if (!(0, fs.existsSync)(schemaPath)) throw new Error(`Prisma schema file not found: ${schemaPath}`);
3333
- if (!(0, fs.existsSync)(modelsDir)) throw new Error(`Models directory not found: ${modelsDir}`);
3334
3540
  const schema = (0, fs.readFileSync)(schemaPath, "utf-8");
3335
3541
  const prismaEnums = this.parsePrismaEnums(schema);
3336
3542
  const prismaModels = this.parsePrismaModels(schema);
3337
- const modelFiles = (0, fs.readdirSync)(modelsDir).filter((file) => file.endsWith(".ts")).map((file) => (0, path.join)(modelsDir, file));
3543
+ const modelFiles = this.resolveModelFiles(modelsDir);
3338
3544
  const result = this.syncModelFiles(modelFiles, (filePath, source) => {
3339
3545
  const parsed = this.parseModelSyncSource(source);
3340
3546
  if (!parsed) return void 0;
3341
3547
  return prismaModels.find((model) => model.table === parsed.table) ?? prismaModels.find((model) => model.name === parsed.className);
3342
3548
  }, prismaEnums);
3549
+ const modelTypes = this.syncModelRegistryTypes(modelFiles);
3343
3550
  return {
3344
3551
  schemaPath,
3345
3552
  modelsDir,
3553
+ modelTypesPath: modelTypes.path,
3346
3554
  total: modelFiles.length,
3347
- updated: result.updated,
3555
+ updated: modelTypes.updated ? [...result.updated, modelTypes.path] : result.updated,
3348
3556
  skipped: result.skipped
3349
3557
  };
3350
3558
  }
@@ -3737,6 +3945,7 @@ var MigrateCommand = class extends _h3ravel_musket.Command {
3737
3945
  {--deploy : Use prisma migrate deploy instead of migrate dev (Prisma compatibility driver only)}
3738
3946
  {--skip-generate : Skip prisma generate (Prisma compatibility driver only)}
3739
3947
  {--skip-migrate : Skip prisma migrate command}
3948
+ {--r|registry : Sync the generated model registry type augmentation after a successful migration}
3740
3949
  {--state-file= : Path to applied migration state file}
3741
3950
  {--schema= : Explicit prisma schema path (Prisma compatibility driver only)}
3742
3951
  {--migration-name= : Name for prisma migrate dev (Prisma compatibility driver only)}
@@ -3793,6 +4002,7 @@ var MigrateCommand = class extends _h3ravel_musket.Command {
3793
4002
  this.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
3794
4003
  return;
3795
4004
  }
4005
+ if (!this.syncModelRegistryIfRequested()) return;
3796
4006
  this.success("No pending migration classes to apply.");
3797
4007
  return;
3798
4008
  }
@@ -3851,6 +4061,18 @@ var MigrateCommand = class extends _h3ravel_musket.Command {
3851
4061
  ], process.cwd());
3852
4062
  this.success(`Applied ${pending.length} migration(s).`);
3853
4063
  pending.forEach(([_, file]) => this.success(this.app.splitLogger("Migrated", file)));
4064
+ this.syncModelRegistryIfRequested();
4065
+ }
4066
+ syncModelRegistryIfRequested() {
4067
+ if (!this.option("registry") && !this.option("r")) return true;
4068
+ try {
4069
+ const result = this.app.syncModelRegistry();
4070
+ this.success(this.app.splitLogger("Model Types", result.modelTypesPath ?? "none"));
4071
+ return true;
4072
+ } catch (error) {
4073
+ this.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
4074
+ return false;
4075
+ }
3854
4076
  }
3855
4077
  /**
3856
4078
  * Load all migration classes from the specified directory.
@@ -4280,6 +4502,7 @@ var ModelsSyncCommand = class extends _h3ravel_musket.Command {
4280
4502
  this.signature = `models:sync
4281
4503
  {--schema= : Path to prisma schema file used when adapter introspection is unavailable}
4282
4504
  {--models= : Path to models directory}
4505
+ {--r|registry-only : Only sync the generated model registry type augmentation}
4283
4506
  `;
4284
4507
  this.description = "Sync model declare attributes from the active adapter when supported";
4285
4508
  }
@@ -4288,10 +4511,11 @@ var ModelsSyncCommand = class extends _h3ravel_musket.Command {
4288
4511
  await require_relationship.loadArkormConfig();
4289
4512
  let result;
4290
4513
  try {
4291
- result = await this.app.syncModels({
4514
+ const options = {
4292
4515
  schemaPath: this.option("schema") ? (0, node_path.resolve)(String(this.option("schema"))) : void 0,
4293
4516
  modelsDir: this.option("models") ? (0, node_path.resolve)(String(this.option("models"))) : void 0
4294
- });
4517
+ };
4518
+ result = this.option("registryOnly") || this.option("registry-only") || this.option("r") ? this.app.syncModelRegistry({ modelsDir: options.modelsDir }) : await this.app.syncModels(options);
4295
4519
  } catch (error) {
4296
4520
  this.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
4297
4521
  return;
@@ -4299,9 +4523,10 @@ var ModelsSyncCommand = class extends _h3ravel_musket.Command {
4299
4523
  const updatedLines = result.updated.length === 0 ? [this.app.splitLogger("Updated", "none")] : result.updated.map((path) => this.app.splitLogger("Updated", path));
4300
4524
  this.success("SUCCESS: Model sync completed with the following results:");
4301
4525
  [
4302
- this.app.splitLogger("Source", result.source === "adapter" ? "adapter introspection" : "prisma schema"),
4526
+ this.app.splitLogger("Source", result.source === "adapter" ? "adapter introspection" : result.source === "registry" ? "model registry" : "prisma schema"),
4303
4527
  ...result.schemaPath ? [this.app.splitLogger("Schema", result.schemaPath)] : [],
4304
4528
  this.app.splitLogger("Models", result.modelsDir),
4529
+ ...result.modelTypesPath ? [this.app.splitLogger("Model Types", result.modelTypesPath)] : [],
4305
4530
  this.app.splitLogger("Processed", String(result.total)),
4306
4531
  ...updatedLines,
4307
4532
  this.app.splitLogger("Skipped", String(result.skipped.length))
@@ -6466,6 +6691,26 @@ var QueryBuilder = class QueryBuilder {
6466
6691
  });
6467
6692
  }
6468
6693
  /**
6694
+ * Compiles the current query into SQL without executing it. Values remain represented by the
6695
+ * adapter's parameter placeholders; use {@link inspect} when the corresponding bindings are
6696
+ * also required.
6697
+ *
6698
+ * @param operation
6699
+ * @returns
6700
+ */
6701
+ toSql(operation = "select") {
6702
+ const inspection = this.inspect(operation);
6703
+ if (inspection?.sql) return inspection.sql;
6704
+ throw new require_relationship.UnsupportedAdapterFeatureException("The active database adapter cannot compile this query to SQL.", {
6705
+ operation: "query.toSql",
6706
+ model: this.model.name,
6707
+ meta: {
6708
+ feature: "inspectQuery",
6709
+ requestedOperation: operation
6710
+ }
6711
+ });
6712
+ }
6713
+ /**
6469
6714
  * Sets offset/limit for a 1-based page.
6470
6715
  *
6471
6716
  * @param page
@@ -6501,6 +6746,50 @@ var QueryBuilder = class QueryBuilder {
6501
6746
  return new require_relationship.ArkormCollection(filteredModels);
6502
6747
  }
6503
6748
  /**
6749
+ * Executes a bounded eager-load query independently for each partition while retaining a
6750
+ * single set-based database query. Returns null when the active adapter cannot represent the
6751
+ * query so the relationship loader can use its correctness fallback.
6752
+ *
6753
+ * @internal
6754
+ *
6755
+ * @param partitionBy
6756
+ * @returns
6757
+ */
6758
+ async getForEagerLoad(partitionBy) {
6759
+ if (this.limitValue === void 0 && this.offsetValue === void 0) return await this.get();
6760
+ const rows = await this.getRowsForEagerLoad(partitionBy);
6761
+ if (!rows) return null;
6762
+ const models = await this.model.hydrateManyRetrieved(rows);
6763
+ await this.eagerLoadModels(models);
6764
+ return new require_relationship.ArkormCollection(models);
6765
+ }
6766
+ /** @internal */
6767
+ async getRowsForEagerLoad(partitionBy) {
6768
+ if (this.limitValue === void 0 && this.offsetValue === void 0) return await this.executeReadRows();
6769
+ const adapter = this.requireAdapter();
6770
+ if (partitionBy.length === 0 || typeof adapter.selectPerPartition !== "function" || this.randomOrderEnabled || this.queryDistinct || this.queryGroupBy !== void 0 || this.queryHaving !== void 0 || !this.canExecuteRelationFeaturesInAdapter()) return null;
6771
+ const spec = this.tryBuildSelectSpec(this.buildWhere());
6772
+ if (!spec) return null;
6773
+ return await adapter.selectPerPartition({
6774
+ ...spec,
6775
+ limit: void 0,
6776
+ offset: void 0,
6777
+ partitionBy,
6778
+ perPartitionLimit: this.limitValue ?? Number.MAX_SAFE_INTEGER,
6779
+ perPartitionOffset: this.offsetValue
6780
+ });
6781
+ }
6782
+ /** Removes limit and offset clauses from a cloned relationship query. @internal */
6783
+ withoutPagination() {
6784
+ this.limitValue = void 0;
6785
+ this.offsetValue = void 0;
6786
+ return this;
6787
+ }
6788
+ /** @internal */
6789
+ hasEagerLoadPagination() {
6790
+ return this.limitValue !== void 0 || this.offsetValue !== void 0;
6791
+ }
6792
+ /**
6504
6793
  * Processes the query results in chunks, invoking the callback with each chunk
6505
6794
  * as a collection. Return `false` from the callback to stop early. Resolves to
6506
6795
  * `false` when stopped early, otherwise `true`.
@@ -7595,6 +7884,7 @@ var QueryBuilder = class QueryBuilder {
7595
7884
  const normalizedQuery = constrained instanceof QueryBuilder ? constrained : relatedQuery;
7596
7885
  if (constrained && !(constrained instanceof QueryBuilder) && constrained !== relatedQuery) return null;
7597
7886
  if (normalizedQuery.randomOrderEnabled) return null;
7887
+ if (normalizedQuery.hasRelationAggregates()) return null;
7598
7888
  const callbackRelationLoads = normalizedQuery.tryBuildAdapterRelationLoadPlans();
7599
7889
  const childRelationLoads = node.children.size > 0 ? toPlans(relatedModel, node.children) : [];
7600
7890
  if (callbackRelationLoads === null || childRelationLoads === null) return null;
@@ -9551,115 +9841,50 @@ var Model = class Model {
9551
9841
  isNotSame(model) {
9552
9842
  return !this.isSame(model);
9553
9843
  }
9554
- /**
9555
- * Define a has one relationship.
9556
- *
9557
- * @param related
9558
- * @param foreignKey
9559
- * @param localKey
9560
- * @returns
9561
- */
9562
9844
  hasOne(related, foreignKey, localKey) {
9563
9845
  const constructor = this.constructor;
9564
- return new require_relationship.HasOneRelation(this, related, foreignKey, localKey ?? constructor.getPrimaryKey());
9846
+ const relatedModel = this.resolveRelationshipModel(related, "hasOne");
9847
+ const resolvedLocalKey = localKey ?? constructor.getPrimaryKey();
9848
+ return new require_relationship.HasOneRelation(this, relatedModel, foreignKey ?? this.resolveDefaultHasForeignKey(constructor, resolvedLocalKey), resolvedLocalKey);
9565
9849
  }
9566
- /**
9567
- * Define a has many relationship.
9568
- *
9569
- * @param related
9570
- * @param foreignKey
9571
- * @param localKey
9572
- * @returns
9573
- */
9574
9850
  hasMany(related, foreignKey, localKey) {
9575
9851
  const constructor = this.constructor;
9576
- return new require_relationship.HasManyRelation(this, related, foreignKey, localKey ?? constructor.getPrimaryKey());
9852
+ const relatedModel = this.resolveRelationshipModel(related, "hasMany");
9853
+ const resolvedLocalKey = localKey ?? constructor.getPrimaryKey();
9854
+ return new require_relationship.HasManyRelation(this, relatedModel, foreignKey ?? this.resolveDefaultHasForeignKey(constructor, resolvedLocalKey), resolvedLocalKey);
9577
9855
  }
9578
- /**
9579
- * Define a belongs to relationship.
9580
- *
9581
- * @param related
9582
- * @param foreignKey
9583
- * @param ownerKey
9584
- * @returns
9585
- */
9586
9856
  belongsTo(related, foreignKey, ownerKey) {
9587
- return new require_relationship.BelongsToRelation(this, related, foreignKey, ownerKey ?? related.getPrimaryKey());
9857
+ const relatedModel = this.resolveRelationshipModel(related, "belongsTo");
9858
+ const resolvedOwnerKey = ownerKey ?? relatedModel.getPrimaryKey();
9859
+ return new require_relationship.BelongsToRelation(this, relatedModel, foreignKey ?? this.resolveDefaultBelongsToForeignKey(relatedModel, resolvedOwnerKey), resolvedOwnerKey);
9588
9860
  }
9589
- /**
9590
- * Define a belongs to many relationship.
9591
- *
9592
- * @param related
9593
- * @param throughTable
9594
- * @param foreignPivotKey
9595
- * @param relatedPivotKey
9596
- * @param parentKey
9597
- * @param relatedKey
9598
- * @returns
9599
- */
9600
9861
  belongsToMany(related, throughTable, foreignPivotKey, relatedPivotKey, parentKey, relatedKey) {
9601
9862
  const constructor = this.constructor;
9602
- return new require_relationship.BelongsToManyRelation(this, related, throughTable, foreignPivotKey, relatedPivotKey, parentKey ?? constructor.getPrimaryKey(), relatedKey ?? related.getPrimaryKey());
9863
+ const relatedModel = this.resolveRelationshipModel(related, "belongsToMany");
9864
+ const resolvedRelatedKey = relatedKey ?? relatedModel.getPrimaryKey();
9865
+ return new require_relationship.BelongsToManyRelation(this, relatedModel, throughTable, foreignPivotKey, relatedPivotKey, parentKey ?? constructor.getPrimaryKey(), resolvedRelatedKey);
9603
9866
  }
9604
- /**
9605
- * Define a has one through relationship.
9606
- *
9607
- * @param related
9608
- * @param throughTable
9609
- * @param firstKey
9610
- * @param secondKey
9611
- * @param localKey
9612
- * @param secondLocalKey
9613
- * @returns
9614
- */
9615
- hasOneThrough(related, throughTable, firstKey, secondKey, localKey, secondLocalKey = "id") {
9867
+ hasOneThrough(related, throughTable, firstKey, secondKey, localKey, secondLocalKey) {
9616
9868
  const constructor = this.constructor;
9617
- return new require_relationship.HasOneThroughRelation(this, related, throughTable, firstKey, secondKey, localKey ?? constructor.getPrimaryKey(), secondLocalKey);
9869
+ const relatedModel = this.resolveRelationshipModel(related, "hasOneThrough");
9870
+ return new require_relationship.HasOneThroughRelation(this, relatedModel, throughTable, firstKey, secondKey, localKey ?? constructor.getPrimaryKey(), secondLocalKey ?? "id");
9618
9871
  }
9619
- /**
9620
- * Define a has many through relationship.
9621
- *
9622
- * @param related
9623
- * @param throughTable
9624
- * @param firstKey
9625
- * @param secondKey
9626
- * @param localKey
9627
- * @param secondLocalKey
9628
- * @returns
9629
- */
9630
9872
  hasManyThrough(related, throughTable, firstKey, secondKey, localKey, secondLocalKey = "id") {
9631
9873
  const constructor = this.constructor;
9632
- return new require_relationship.HasManyThroughRelation(this, related, throughTable, firstKey, secondKey, localKey ?? constructor.getPrimaryKey(), secondLocalKey);
9874
+ const relatedModel = this.resolveRelationshipModel(related, "hasManyThrough");
9875
+ return new require_relationship.HasManyThroughRelation(this, relatedModel, throughTable, firstKey, secondKey, localKey ?? constructor.getPrimaryKey(), secondLocalKey);
9633
9876
  }
9634
- /**
9635
- * Define a polymorphic one to one relationship.
9636
- *
9637
- * @param related
9638
- * @param morphName
9639
- * @param idColumn
9640
- * @param typeColumn
9641
- * @param localKey
9642
- * @returns
9643
- */
9644
9877
  morphOne(related, morphName, idColumn, typeColumn, localKey) {
9645
9878
  const constructor = this.constructor;
9879
+ const relatedModel = this.resolveRelationshipModel(related, "morphOne");
9646
9880
  const columns = this.resolveMorphColumns(morphName, idColumn, typeColumn);
9647
- return new require_relationship.MorphOneRelation(this, related, morphName, columns.idColumn, columns.typeColumn, localKey ?? constructor.getPrimaryKey());
9881
+ return new require_relationship.MorphOneRelation(this, relatedModel, morphName, columns.idColumn, columns.typeColumn, localKey ?? constructor.getPrimaryKey());
9648
9882
  }
9649
- /**
9650
- * Define a polymorphic one to many relationship.
9651
- *
9652
- * @param related
9653
- * @param morphName
9654
- * @param idColumn
9655
- * @param typeColumn
9656
- * @param localKey
9657
- * @returns
9658
- */
9659
9883
  morphMany(related, morphName, idColumn, typeColumn, localKey) {
9660
9884
  const constructor = this.constructor;
9885
+ const relatedModel = this.resolveRelationshipModel(related, "morphMany");
9661
9886
  const columns = this.resolveMorphColumns(morphName, idColumn, typeColumn);
9662
- return new require_relationship.MorphManyRelation(this, related, morphName, columns.idColumn, columns.typeColumn, localKey ?? constructor.getPrimaryKey());
9887
+ return new require_relationship.MorphManyRelation(this, relatedModel, morphName, columns.idColumn, columns.typeColumn, localKey ?? constructor.getPrimaryKey());
9663
9888
  }
9664
9889
  morphTo(morphName, typeColumnOrRelated, idColumn, ownerKey) {
9665
9890
  const related = typeof typeColumnOrRelated === "function" ? typeColumnOrRelated : void 0;
@@ -9667,51 +9892,37 @@ var Model = class Model {
9667
9892
  const columns = this.resolveMorphColumns(morphName, idColumn, typeColumn);
9668
9893
  return new require_relationship.MorphToRelation(this, morphName, columns.typeColumn, columns.idColumn, ownerKey, related);
9669
9894
  }
9670
- /**
9671
- * Define a polymorphic many to many relationship.
9672
- *
9673
- * @param related
9674
- * @param morphName
9675
- * @param throughTable
9676
- * @param foreignPivotKey
9677
- * @param morphTypeColumn
9678
- * @param relatedPivotKey
9679
- * @param parentKey
9680
- * @param relatedKey
9681
- * @returns
9682
- */
9683
9895
  morphToMany(related, morphName, throughTable, foreignPivotKey, morphTypeColumn, relatedPivotKey, parentKey, relatedKey) {
9684
9896
  const constructor = this.constructor;
9685
9897
  const namingCase = Model.getNamingCase();
9686
- const resolvedRelatedKey = relatedKey ?? related.getPrimaryKey();
9898
+ const relatedModel = this.resolveRelationshipModel(related, "morphToMany");
9899
+ const resolvedRelatedKey = relatedKey ?? relatedModel.getPrimaryKey();
9687
9900
  const resolvedTable = throughTable ?? this.formatConventionName(`${(0, _h3ravel_support.str)(morphName).plural()}`, namingCase);
9688
- const resolvedRelatedPivotKey = relatedPivotKey ?? this.formatConventionName(`${(0, _h3ravel_support.str)(related.getTable()).singular()}_${resolvedRelatedKey}`, namingCase);
9901
+ const resolvedRelatedPivotKey = relatedPivotKey ?? this.formatConventionName(`${(0, _h3ravel_support.str)(relatedModel.getTable()).singular()}_${resolvedRelatedKey}`, namingCase);
9689
9902
  const morphIdColumn = foreignPivotKey ?? this.formatConventionName(`${morphName}_id`, namingCase);
9690
9903
  const resolvedMorphTypeColumn = morphTypeColumn ?? this.formatConventionName(`${morphName}_type`, namingCase);
9691
- return new require_relationship.MorphToManyRelation(this, related, resolvedTable, morphName, morphIdColumn, resolvedMorphTypeColumn, resolvedRelatedPivotKey, parentKey ?? constructor.getPrimaryKey(), resolvedRelatedKey);
9904
+ return new require_relationship.MorphToManyRelation(this, relatedModel, resolvedTable, morphName, morphIdColumn, resolvedMorphTypeColumn, resolvedRelatedPivotKey, parentKey ?? constructor.getPrimaryKey(), resolvedRelatedKey);
9692
9905
  }
9693
- /**
9694
- * Define the inverse side of a polymorphic many-to-many relationship.
9695
- *
9696
- * @param related
9697
- * @param morphName
9698
- * @param throughTable
9699
- * @param foreignPivotKey
9700
- * @param morphTypeColumn
9701
- * @param relatedPivotKey
9702
- * @param parentKey
9703
- * @param relatedKey
9704
- * @returns
9705
- */
9706
9906
  morphedByMany(related, morphName, throughTable, foreignPivotKey, morphTypeColumn, relatedPivotKey, parentKey, relatedKey) {
9707
9907
  const constructor = this.constructor;
9708
9908
  const namingCase = Model.getNamingCase();
9709
- const resolvedRelatedKey = relatedKey ?? related.getPrimaryKey();
9909
+ const relatedModel = this.resolveRelationshipModel(related, "morphedByMany");
9910
+ const resolvedRelatedKey = relatedKey ?? relatedModel.getPrimaryKey();
9710
9911
  const resolvedTable = throughTable ?? this.formatConventionName(`${(0, _h3ravel_support.str)(morphName).plural()}`, namingCase);
9711
9912
  const resolvedForeignPivotKey = foreignPivotKey ?? this.formatConventionName(`${(0, _h3ravel_support.str)(constructor.getTable()).singular()}_${parentKey ?? constructor.getPrimaryKey()}`, namingCase);
9712
9913
  const resolvedMorphTypeColumn = morphTypeColumn ?? this.formatConventionName(`${morphName}_type`, namingCase);
9713
9914
  const resolvedRelatedPivotKey = relatedPivotKey ?? this.formatConventionName(`${morphName}_id`, namingCase);
9714
- return new require_relationship.MorphedByManyRelation(this, related, resolvedTable, morphName, resolvedForeignPivotKey, resolvedMorphTypeColumn, resolvedRelatedPivotKey, parentKey ?? constructor.getPrimaryKey(), resolvedRelatedKey);
9915
+ return new require_relationship.MorphedByManyRelation(this, relatedModel, resolvedTable, morphName, resolvedForeignPivotKey, resolvedMorphTypeColumn, resolvedRelatedPivotKey, parentKey ?? constructor.getPrimaryKey(), resolvedRelatedKey);
9916
+ }
9917
+ resolveRelationshipModel(related, operation) {
9918
+ if (typeof related === "function") return related;
9919
+ return require_relationship.resolveRegisteredModel(related, { operation });
9920
+ }
9921
+ resolveDefaultHasForeignKey(parent, localKey) {
9922
+ return this.formatConventionName(`${(0, _h3ravel_support.str)(parent.getTable()).singular()}_${localKey}`, Model.getNamingCase());
9923
+ }
9924
+ resolveDefaultBelongsToForeignKey(related, ownerKey) {
9925
+ return this.formatConventionName(`${(0, _h3ravel_support.str)(related.getTable()).singular()}_${ownerKey}`, Model.getNamingCase());
9715
9926
  }
9716
9927
  resolveMorphColumns(morphName, idColumn, typeColumn) {
9717
9928
  const namingCase = Model.getNamingCase();
@@ -10783,6 +10994,7 @@ exports.getLastBatchMigrations = require_relationship.getLastBatchMigrations;
10783
10994
  exports.getLastMigrationRun = require_relationship.getLastMigrationRun;
10784
10995
  exports.getLatestAppliedMigrations = require_relationship.getLatestAppliedMigrations;
10785
10996
  exports.getMigrationPlan = require_relationship.getMigrationPlan;
10997
+ exports.getModel = getModel;
10786
10998
  exports.getPersistedColumnMap = require_relationship.getPersistedColumnMap;
10787
10999
  exports.getPersistedEnumMap = require_relationship.getPersistedEnumMap;
10788
11000
  exports.getPersistedEnumTsType = require_relationship.getPersistedEnumTsType;
@@ -10841,6 +11053,7 @@ exports.resolveMigrationClassName = require_relationship.resolveMigrationClassNa
10841
11053
  exports.resolveMigrationStateFilePath = require_relationship.resolveMigrationStateFilePath;
10842
11054
  exports.resolvePersistedMetadataFeatures = require_relationship.resolvePersistedMetadataFeatures;
10843
11055
  exports.resolvePrismaType = require_relationship.resolvePrismaType;
11056
+ exports.resolveRegisteredModel = require_relationship.resolveRegisteredModel;
10844
11057
  exports.resolveRuntimeCompatibilityQuerySchema = resolveRuntimeCompatibilityQuerySchema;
10845
11058
  exports.resolveRuntimeCompatibilityQuerySchemaOrThrow = resolveRuntimeCompatibilityQuerySchemaOrThrow;
10846
11059
  exports.runArkormTransaction = require_relationship.runArkormTransaction;