arkormx 2.5.1 → 2.5.3

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.
@@ -2933,6 +2933,8 @@ const userConfig = {
2933
2933
  };
2934
2934
  let runtimeConfigLoaded = false;
2935
2935
  let runtimeConfigLoadingPromise;
2936
+ let runtimeModelRegistrationPromise;
2937
+ let runtimeModelRegistrationGeneration = 0;
2936
2938
  let runtimeClientResolver;
2937
2939
  let runtimeAdapter;
2938
2940
  let runtimePaginationURLDriverFactory;
@@ -2998,6 +3000,51 @@ const mergeFeatureConfig = (features) => {
2998
3000
  ...features ?? {}
2999
3001
  };
3000
3002
  };
3003
+ const resolveRuntimeModelsDirectory = (directory) => {
3004
+ if ((0, fs.existsSync)(directory)) return directory;
3005
+ const buildOutput = userConfig.paths?.buildOutput;
3006
+ if (typeof buildOutput !== "string" || buildOutput.trim().length === 0) return directory;
3007
+ const relativeSource = path.default.relative(process.cwd(), directory);
3008
+ if (!relativeSource || relativeSource.startsWith("..")) return directory;
3009
+ const mappedDirectory = path.default.join(buildOutput, relativeSource);
3010
+ return (0, fs.existsSync)(mappedDirectory) ? mappedDirectory : directory;
3011
+ };
3012
+ const collectRuntimeModelFiles = (directory) => {
3013
+ if (!(0, fs.existsSync)(directory)) return [];
3014
+ return (0, fs.readdirSync)(directory, { withFileTypes: true }).flatMap((entry) => {
3015
+ const entryPath = path.default.join(directory, entry.name);
3016
+ if (entry.isDirectory()) return collectRuntimeModelFiles(entryPath);
3017
+ if (!entry.isFile() || !/\.(ts|tsx|mts|cts|js|mjs|cjs)$/i.test(entry.name)) return [];
3018
+ if (/\.d\.(ts|mts|cts)$/i.test(entry.name)) return [];
3019
+ return [entryPath];
3020
+ });
3021
+ };
3022
+ const isModelConstructor = (value) => {
3023
+ if (typeof value !== "function") return false;
3024
+ const candidate = value;
3025
+ return typeof candidate.query === "function" && typeof candidate.hydrate === "function" && typeof candidate.getTable === "function" && typeof candidate.getPrimaryKey === "function";
3026
+ };
3027
+ const registerConfiguredModels = async (generation) => {
3028
+ const configured = userConfig.paths?.models;
3029
+ const additional = getRegisteredPaths("models");
3030
+ const files = [...typeof configured === "string" ? [configured] : [], ...additional].map((directory) => resolveRuntimeModelsDirectory(path.default.isAbsolute(directory) ? directory : path.default.resolve(process.cwd(), directory))).filter((directory, index, all) => all.indexOf(directory) === index).flatMap(collectRuntimeModelFiles);
3031
+ const models = (await Promise.all(files.map(async (file) => {
3032
+ try {
3033
+ return await RuntimeModuleLoader.load(file);
3034
+ } catch {
3035
+ return null;
3036
+ }
3037
+ }))).flatMap((module) => module ? Object.values(module).filter(isModelConstructor) : []);
3038
+ if (generation === runtimeModelRegistrationGeneration) registerModels(models);
3039
+ };
3040
+ const scheduleConfiguredModelRegistration = () => {
3041
+ const generation = runtimeModelRegistrationGeneration;
3042
+ runtimeModelRegistrationPromise = (runtimeModelRegistrationPromise ?? Promise.resolve()).then(async () => await registerConfiguredModels(generation));
3043
+ return runtimeModelRegistrationPromise;
3044
+ };
3045
+ const awaitConfiguredModelsRegistration = async () => {
3046
+ if (runtimeModelRegistrationPromise) await runtimeModelRegistrationPromise;
3047
+ };
3001
3048
  /**
3002
3049
  * Define the ArkORM runtime configuration. This function can be used to provide.
3003
3050
  *
@@ -3058,6 +3105,7 @@ const configureArkormRuntime = (client, options = {}) => {
3058
3105
  runtimePaginationURLDriverFactory = nextConfig.pagination?.urlDriver;
3059
3106
  runtimePaginationCurrentPageResolver = nextConfig.pagination?.resolveCurrentPage;
3060
3107
  runtimeDebugHandler = resolveDebugHandler(nextConfig.debug);
3108
+ scheduleConfiguredModelRegistration();
3061
3109
  const bootClient = resolveClient(resolvedClient);
3062
3110
  options.boot?.({
3063
3111
  client: bootClient,
@@ -3078,6 +3126,8 @@ const resetArkormRuntimeForTests = () => {
3078
3126
  });
3079
3127
  runtimeConfigLoaded = false;
3080
3128
  runtimeConfigLoadingPromise = void 0;
3129
+ runtimeModelRegistrationPromise = void 0;
3130
+ runtimeModelRegistrationGeneration++;
3081
3131
  runtimeClientResolver = void 0;
3082
3132
  runtimeAdapter = void 0;
3083
3133
  runtimePaginationURLDriverFactory = void 0;
@@ -3154,21 +3204,30 @@ const loadRuntimeConfigSync = () => {
3154
3204
  * @returns
3155
3205
  */
3156
3206
  const loadArkormConfig = async () => {
3157
- if (runtimeConfigLoaded) return;
3207
+ if (runtimeConfigLoaded) {
3208
+ await awaitConfiguredModelsRegistration();
3209
+ return;
3210
+ }
3158
3211
  if (runtimeConfigLoadingPromise) return await runtimeConfigLoadingPromise;
3159
- if (loadRuntimeConfigSync()) return;
3212
+ if (loadRuntimeConfigSync()) {
3213
+ await awaitConfiguredModelsRegistration();
3214
+ return;
3215
+ }
3160
3216
  runtimeConfigLoadingPromise = (async () => {
3161
3217
  const configPaths = [path.default.join(process.cwd(), "arkormx.config.js"), path.default.join(process.cwd(), "arkormx.config.ts")];
3162
3218
  for (const configPath of configPaths) {
3163
3219
  if (!(0, fs.existsSync)(configPath)) continue;
3164
3220
  try {
3165
3221
  resolveAndApplyConfig(await importConfigFile(configPath));
3222
+ await awaitConfiguredModelsRegistration();
3166
3223
  return;
3167
3224
  } catch {
3168
3225
  continue;
3169
3226
  }
3170
3227
  }
3171
3228
  runtimeConfigLoaded = true;
3229
+ await scheduleConfiguredModelRegistration();
3230
+ await awaitConfiguredModelsRegistration();
3172
3231
  })();
3173
3232
  await runtimeConfigLoadingPromise;
3174
3233
  };
@@ -5034,6 +5093,78 @@ var MorphToManyRelation = class extends Relation {
5034
5093
  }
5035
5094
  };
5036
5095
 
5096
+ //#endregion
5097
+ //#region src/relationship/MorphToRelation.ts
5098
+ /**
5099
+ * Defines the inverse side of a polymorphic one-to-one or one-to-many relationship.
5100
+ *
5101
+ * Related models are resolved from ArkORM's runtime model registry using the value
5102
+ * stored in the morph type column.
5103
+ *
5104
+ * @author Legacy (3m1n3nc3)
5105
+ * @since 2.6.0
5106
+ */
5107
+ var MorphToRelation = class extends Relation {
5108
+ constructor(parent, morphName, morphTypeColumn, morphIdColumn, ownerKey, relatedModel) {
5109
+ super();
5110
+ this.parent = parent;
5111
+ this.morphName = morphName;
5112
+ this.morphTypeColumn = morphTypeColumn;
5113
+ this.morphIdColumn = morphIdColumn;
5114
+ this.ownerKey = ownerKey;
5115
+ this.relatedModel = relatedModel;
5116
+ }
5117
+ get related() {
5118
+ return this.resolveRelatedModel();
5119
+ }
5120
+ /**
5121
+ * Build the relationship query.
5122
+ *
5123
+ * @returns
5124
+ */
5125
+ async getQuery() {
5126
+ await awaitConfiguredModelsRegistration();
5127
+ const related = this.resolveRelatedModel();
5128
+ const resolvedOwnerKey = this.ownerKey ?? related.getPrimaryKey();
5129
+ const morphId = this.parent.getAttribute(this.morphIdColumn);
5130
+ return this.applyConstraint(related.query().where({ [resolvedOwnerKey]: morphId }));
5131
+ }
5132
+ getMetadata() {
5133
+ return {
5134
+ type: "morphTo",
5135
+ morphName: this.morphName,
5136
+ morphIdColumn: this.morphIdColumn,
5137
+ morphTypeColumn: this.morphTypeColumn,
5138
+ ownerKey: this.ownerKey
5139
+ };
5140
+ }
5141
+ /**
5142
+ * Fetch the polymorphic parent model.
5143
+ *
5144
+ * @returns
5145
+ */
5146
+ async getResults() {
5147
+ const morphType = this.parent.getAttribute(this.morphTypeColumn);
5148
+ const morphId = this.parent.getAttribute(this.morphIdColumn);
5149
+ if (morphType == null || morphId == null) return null;
5150
+ return await (await this.getQuery()).first();
5151
+ }
5152
+ resolveRelatedModel() {
5153
+ const morphType = this.parent.getAttribute(this.morphTypeColumn);
5154
+ if (typeof morphType !== "string" || morphType.trim().length === 0) throw new RelationResolutionException(`Morph type column [${this.morphTypeColumn}] does not contain a model name.`, {
5155
+ operation: "morphTo",
5156
+ relation: this.morphName
5157
+ });
5158
+ const related = this.relatedModel?.name === morphType ? this.relatedModel : getRegisteredModels().find((model) => model.name === morphType);
5159
+ if (!related) throw new RelationResolutionException(`Morph model [${morphType}] is not registered. Register it with Arkorm.registerModels().`, {
5160
+ operation: "morphTo",
5161
+ model: morphType,
5162
+ relation: this.morphName
5163
+ });
5164
+ return related;
5165
+ }
5166
+ };
5167
+
5037
5168
  //#endregion
5038
5169
  Object.defineProperty(exports, 'ArkormCollection', {
5039
5170
  enumerable: true,
@@ -5119,6 +5250,12 @@ Object.defineProperty(exports, 'MorphToManyRelation', {
5119
5250
  return MorphToManyRelation;
5120
5251
  }
5121
5252
  });
5253
+ Object.defineProperty(exports, 'MorphToRelation', {
5254
+ enumerable: true,
5255
+ get: function () {
5256
+ return MorphToRelation;
5257
+ }
5258
+ });
5122
5259
  Object.defineProperty(exports, 'PRISMA_ENUM_MEMBER_REGEX', {
5123
5260
  enumerable: true,
5124
5261
  get: function () {
@@ -5269,6 +5406,12 @@ Object.defineProperty(exports, 'applyOperationsToPrismaSchema', {
5269
5406
  return applyOperationsToPrismaSchema;
5270
5407
  }
5271
5408
  });
5409
+ Object.defineProperty(exports, 'awaitConfiguredModelsRegistration', {
5410
+ enumerable: true,
5411
+ get: function () {
5412
+ return awaitConfiguredModelsRegistration;
5413
+ }
5414
+ });
5272
5415
  Object.defineProperty(exports, 'bindAdapterToModels', {
5273
5416
  enumerable: true,
5274
5417
  get: function () {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arkormx",
3
- "version": "2.5.1",
3
+ "version": "2.5.3",
4
4
  "description": "Modern TypeScript-first ORM for Node.js.",
5
5
  "keywords": [
6
6
  "orm",