@holoyan/adonisjs-polymorphic 0.1.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.
Files changed (75) hide show
  1. package/README.md +549 -0
  2. package/build/configure.d.ts +10 -0
  3. package/build/configure.d.ts.map +1 -0
  4. package/build/configure.js +27 -0
  5. package/build/configure.js.map +1 -0
  6. package/build/providers/plugin_provider.d.ts +15 -0
  7. package/build/providers/plugin_provider.d.ts.map +1 -0
  8. package/build/providers/plugin_provider.js +21 -0
  9. package/build/providers/plugin_provider.js.map +1 -0
  10. package/build/src/decorators.d.ts +41 -0
  11. package/build/src/decorators.d.ts.map +1 -0
  12. package/build/src/decorators.js +64 -0
  13. package/build/src/decorators.js.map +1 -0
  14. package/build/src/define_config.d.ts +20 -0
  15. package/build/src/define_config.d.ts.map +1 -0
  16. package/build/src/define_config.js +8 -0
  17. package/build/src/define_config.js.map +1 -0
  18. package/build/src/index.d.ts +16 -0
  19. package/build/src/index.d.ts.map +1 -0
  20. package/build/src/index.js +15 -0
  21. package/build/src/index.js.map +1 -0
  22. package/build/src/relations/morph_many/index.d.ts +39 -0
  23. package/build/src/relations/morph_many/index.d.ts.map +1 -0
  24. package/build/src/relations/morph_many/index.js +110 -0
  25. package/build/src/relations/morph_many/index.js.map +1 -0
  26. package/build/src/relations/morph_many/query_builder.d.ts +22 -0
  27. package/build/src/relations/morph_many/query_builder.d.ts.map +1 -0
  28. package/build/src/relations/morph_many/query_builder.js +80 -0
  29. package/build/src/relations/morph_many/query_builder.js.map +1 -0
  30. package/build/src/relations/morph_many/query_client.d.ts +40 -0
  31. package/build/src/relations/morph_many/query_client.d.ts.map +1 -0
  32. package/build/src/relations/morph_many/query_client.js +115 -0
  33. package/build/src/relations/morph_many/query_client.js.map +1 -0
  34. package/build/src/relations/morph_one/index.d.ts +68 -0
  35. package/build/src/relations/morph_one/index.d.ts.map +1 -0
  36. package/build/src/relations/morph_one/index.js +147 -0
  37. package/build/src/relations/morph_one/index.js.map +1 -0
  38. package/build/src/relations/morph_one/query_builder.d.ts +22 -0
  39. package/build/src/relations/morph_one/query_builder.d.ts.map +1 -0
  40. package/build/src/relations/morph_one/query_builder.js +79 -0
  41. package/build/src/relations/morph_one/query_builder.js.map +1 -0
  42. package/build/src/relations/morph_one/query_client.d.ts +41 -0
  43. package/build/src/relations/morph_one/query_client.d.ts.map +1 -0
  44. package/build/src/relations/morph_one/query_client.js +94 -0
  45. package/build/src/relations/morph_one/query_client.js.map +1 -0
  46. package/build/src/relations/morph_to/eager_loader.d.ts +29 -0
  47. package/build/src/relations/morph_to/eager_loader.d.ts.map +1 -0
  48. package/build/src/relations/morph_to/eager_loader.js +78 -0
  49. package/build/src/relations/morph_to/eager_loader.js.map +1 -0
  50. package/build/src/relations/morph_to/index.d.ts +76 -0
  51. package/build/src/relations/morph_to/index.d.ts.map +1 -0
  52. package/build/src/relations/morph_to/index.js +172 -0
  53. package/build/src/relations/morph_to/index.js.map +1 -0
  54. package/build/src/relations/morph_to/query_client.d.ts +27 -0
  55. package/build/src/relations/morph_to/query_client.d.ts.map +1 -0
  56. package/build/src/relations/morph_to/query_client.js +64 -0
  57. package/build/src/relations/morph_to/query_client.js.map +1 -0
  58. package/build/src/relations/morph_to/registry.d.ts +2 -0
  59. package/build/src/relations/morph_to/registry.d.ts.map +1 -0
  60. package/build/src/relations/morph_to/registry.js +13 -0
  61. package/build/src/relations/morph_to/registry.js.map +1 -0
  62. package/build/src/relations/shared/query_builder.d.ts +55 -0
  63. package/build/src/relations/shared/query_builder.d.ts.map +1 -0
  64. package/build/src/relations/shared/query_builder.js +70 -0
  65. package/build/src/relations/shared/query_builder.js.map +1 -0
  66. package/build/src/types.d.ts +84 -0
  67. package/build/src/types.d.ts.map +1 -0
  68. package/build/src/types.js +2 -0
  69. package/build/src/types.js.map +1 -0
  70. package/build/stubs/config/polymorphic.stub +19 -0
  71. package/build/stubs/main.d.ts +6 -0
  72. package/build/stubs/main.d.ts.map +1 -0
  73. package/build/stubs/main.js +6 -0
  74. package/build/stubs/main.js.map +1 -0
  75. package/package.json +81 -0
@@ -0,0 +1,68 @@
1
+ import type { MorphOneOptions } from '../../types.js';
2
+ import { MorphOneQueryClient } from './query_client.js';
3
+ /**
4
+ * MorphOne relation - the parent model has exactly one polymorphic child.
5
+ *
6
+ * Example: Post morphOne Image (imageable)
7
+ * images table has: imageable_type = 'posts', imageable_id = post.id
8
+ */
9
+ export declare class MorphOne {
10
+ readonly relationName: string;
11
+ readonly relatedModel: () => any;
12
+ private readonly options;
13
+ readonly model: any;
14
+ readonly type = "hasOne";
15
+ booted: boolean;
16
+ serializeAs: string | null;
17
+ /** @internal used by the query hook */
18
+ onQueryHook: ((query: any) => void) | undefined;
19
+ /** Attribute name for the morph type column on the related model */
20
+ morphTypeKey: string;
21
+ /** DB column name for the morph type on the related model */
22
+ morphTypeColumnName: string;
23
+ /** Attribute name for the morph id column on the related model */
24
+ morphIdKey: string;
25
+ /** DB column name for the morph id on the related model */
26
+ morphIdColumnName: string;
27
+ /** Attribute name of the local key on the parent model */
28
+ localKey: string;
29
+ /** DB column name of the local key on the parent model */
30
+ localKeyColumnName: string;
31
+ /** Value stored in the morph type column to identify this parent model */
32
+ morphValue: string;
33
+ constructor(relationName: string, relatedModel: () => any, options: MorphOneOptions, model: any);
34
+ clone(parent: any): MorphOne;
35
+ /**
36
+ * Boot the relation - validates that all required columns exist and
37
+ * resolves attribute names / column names.
38
+ */
39
+ boot(): void;
40
+ /**
41
+ * Sets the related model instance on the parent (used by the preloader).
42
+ */
43
+ setRelated(parent: any, related: any): void;
44
+ pushRelated(parent: any, related: any): void;
45
+ /**
46
+ * Matches and sets related models on each parent during eager loading.
47
+ * For morphOne there is at most one related row per parent.
48
+ */
49
+ setRelatedForMany(parents: any[], related: any[]): void;
50
+ /**
51
+ * Returns a query client that can be used from model.related('relation').
52
+ */
53
+ client(parent: any, client: any): MorphOneQueryClient;
54
+ /**
55
+ * Returns an eager-load query (used by the Lucid preloader).
56
+ */
57
+ eagerQuery(parent: any | any[], client: any): import("./query_builder.js").MorphOneQueryBuilder;
58
+ /**
59
+ * Returns a subquery builder (for whereHas / withCount).
60
+ */
61
+ subQuery(client: any): never;
62
+ /**
63
+ * Hydrates the related model / plain object with the morph FK values
64
+ * before persisting. Called by the query client's create/save methods.
65
+ */
66
+ hydrateForPersistance(parent: any, related: any): void;
67
+ }
68
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/relations/morph_one/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAGvD;;;;;GAKG;AACH,qBAAa,QAAQ;aAwBD,YAAY,EAAE,MAAM;aACpB,YAAY,EAAE,MAAM,GAAG;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO;aACR,KAAK,EAAE,GAAG;IA1B5B,QAAQ,CAAC,IAAI,YAAW;IACxB,MAAM,UAAQ;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAE1B,uCAAuC;IACvC,WAAW,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IAE/C,oEAAoE;IACpE,YAAY,EAAG,MAAM,CAAA;IACrB,6DAA6D;IAC7D,mBAAmB,EAAG,MAAM,CAAA;IAC5B,kEAAkE;IAClE,UAAU,EAAG,MAAM,CAAA;IACnB,2DAA2D;IAC3D,iBAAiB,EAAG,MAAM,CAAA;IAC1B,0DAA0D;IAC1D,QAAQ,EAAG,MAAM,CAAA;IACjB,0DAA0D;IAC1D,kBAAkB,EAAG,MAAM,CAAA;IAC3B,0EAA0E;IAC1E,UAAU,EAAG,MAAM,CAAA;gBAGD,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,GAAG,EACtB,OAAO,EAAE,eAAe,EACzB,KAAK,EAAE,GAAG;IAO5B,KAAK,CAAC,MAAM,EAAE,GAAG,GAAG,QAAQ;IAI5B;;;OAGG;IACH,IAAI,IAAI,IAAI;IAuDZ;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,GAAG,IAAI;IAK3C,WAAW,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,GAAG,IAAI;IAK5C;;;OAGG;IACH,iBAAiB,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,IAAI;IAUvD;;OAEG;IACH,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG,mBAAmB;IAKrD;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,EAAE,EAAE,MAAM,EAAE,GAAG;IAK3C;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,GAAG,GAAG,KAAK;IAI5B;;;OAGG;IACH,qBAAqB,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,GAAG,IAAI;CAIvD"}
@@ -0,0 +1,147 @@
1
+ import { MorphOneQueryClient } from './query_client.js';
2
+ import { getRegistry } from '../morph_to/registry.js';
3
+ /**
4
+ * MorphOne relation - the parent model has exactly one polymorphic child.
5
+ *
6
+ * Example: Post morphOne Image (imageable)
7
+ * images table has: imageable_type = 'posts', imageable_id = post.id
8
+ */
9
+ export class MorphOne {
10
+ relationName;
11
+ relatedModel;
12
+ options;
13
+ model;
14
+ type = 'hasOne';
15
+ booted = false;
16
+ serializeAs;
17
+ /** @internal used by the query hook */
18
+ onQueryHook;
19
+ /** Attribute name for the morph type column on the related model */
20
+ morphTypeKey;
21
+ /** DB column name for the morph type on the related model */
22
+ morphTypeColumnName;
23
+ /** Attribute name for the morph id column on the related model */
24
+ morphIdKey;
25
+ /** DB column name for the morph id on the related model */
26
+ morphIdColumnName;
27
+ /** Attribute name of the local key on the parent model */
28
+ localKey;
29
+ /** DB column name of the local key on the parent model */
30
+ localKeyColumnName;
31
+ /** Value stored in the morph type column to identify this parent model */
32
+ morphValue;
33
+ constructor(relationName, relatedModel, options, model) {
34
+ this.relationName = relationName;
35
+ this.relatedModel = relatedModel;
36
+ this.options = options;
37
+ this.model = model;
38
+ this.onQueryHook = options.onQuery;
39
+ this.serializeAs =
40
+ options.serializeAs === undefined ? relationName : options.serializeAs;
41
+ }
42
+ clone(parent) {
43
+ return new MorphOne(this.relationName, this.relatedModel, { ...this.options }, parent);
44
+ }
45
+ /**
46
+ * Boot the relation - validates that all required columns exist and
47
+ * resolves attribute names / column names.
48
+ */
49
+ boot() {
50
+ if (this.booted)
51
+ return;
52
+ const relatedModel = this.relatedModel();
53
+ const morphName = this.options.name;
54
+ // Derive camelCase attribute names from the morph name
55
+ const typeAttr = `${morphName}Type`; // e.g., 'imageableType'
56
+ const idAttr = `${morphName}Id`; // e.g., 'imageableId'
57
+ // Resolve column names from related model's @column() definitions
58
+ const typeColDef = relatedModel.$getColumn(typeAttr);
59
+ if (!typeColDef) {
60
+ throw new Error(`[MorphOne] "${typeAttr}" column not found on "${relatedModel.name}". ` +
61
+ `Add @column() declare ${typeAttr}: string`);
62
+ }
63
+ const idColDef = relatedModel.$getColumn(idAttr);
64
+ if (!idColDef) {
65
+ throw new Error(`[MorphOne] "${idAttr}" column not found on "${relatedModel.name}". ` +
66
+ `Add @column() declare ${idAttr}: number`);
67
+ }
68
+ this.morphTypeKey = typeAttr;
69
+ this.morphTypeColumnName = typeColDef.columnName;
70
+ this.morphIdKey = idAttr;
71
+ this.morphIdColumnName = idColDef.columnName;
72
+ // Resolve local key on parent model
73
+ const localKeyAttr = this.options.localKey ?? this.model.primaryKey;
74
+ const localColDef = this.model.$getColumn(localKeyAttr);
75
+ if (!localColDef) {
76
+ throw new Error(`[MorphOne] "${localKeyAttr}" column not found on "${this.model.name}".`);
77
+ }
78
+ this.localKey = localKeyAttr;
79
+ this.localKeyColumnName = localColDef.columnName;
80
+ // The value stored in the type column.
81
+ // Priority: explicit option → @MorphMap alias → model table name
82
+ if (this.options.morphValue) {
83
+ this.morphValue = this.options.morphValue;
84
+ }
85
+ else {
86
+ const registry = getRegistry();
87
+ const alias = registry?.hasTarget(this.model) ? registry.getAlias(this.model) : null;
88
+ this.morphValue = alias ?? this.model.table;
89
+ }
90
+ this.booted = true;
91
+ }
92
+ /**
93
+ * Sets the related model instance on the parent (used by the preloader).
94
+ */
95
+ setRelated(parent, related) {
96
+ if (related === undefined)
97
+ return;
98
+ parent.$setRelated(this.relationName, related);
99
+ }
100
+ pushRelated(parent, related) {
101
+ if (related === undefined)
102
+ return;
103
+ parent.$pushRelated(this.relationName, related);
104
+ }
105
+ /**
106
+ * Matches and sets related models on each parent during eager loading.
107
+ * For morphOne there is at most one related row per parent.
108
+ */
109
+ setRelatedForMany(parents, related) {
110
+ parents.forEach((parentModel) => {
111
+ const parentId = parentModel[this.localKey];
112
+ const match = related.find((r) => parentId !== undefined && r[this.morphIdKey] === parentId);
113
+ this.setRelated(parentModel, match ?? null);
114
+ });
115
+ }
116
+ /**
117
+ * Returns a query client that can be used from model.related('relation').
118
+ */
119
+ client(parent, client) {
120
+ if (!this.booted)
121
+ this.boot();
122
+ return new MorphOneQueryClient(this, parent, client);
123
+ }
124
+ /**
125
+ * Returns an eager-load query (used by the Lucid preloader).
126
+ */
127
+ eagerQuery(parent, client) {
128
+ if (!this.booted)
129
+ this.boot();
130
+ return MorphOneQueryClient.eagerQuery(client, this, parent);
131
+ }
132
+ /**
133
+ * Returns a subquery builder (for whereHas / withCount).
134
+ */
135
+ subQuery(client) {
136
+ return MorphOneQueryClient.subQuery(client, this);
137
+ }
138
+ /**
139
+ * Hydrates the related model / plain object with the morph FK values
140
+ * before persisting. Called by the query client's create/save methods.
141
+ */
142
+ hydrateForPersistance(parent, related) {
143
+ related[this.morphTypeKey] = this.morphValue;
144
+ related[this.morphIdKey] = parent[this.localKey];
145
+ }
146
+ }
147
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/relations/morph_one/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { MorphBaseQueryBuilder } from '../shared/query_builder.js';
2
+ import type { MorphOne } from './index.js';
3
+ /**
4
+ * Query builder for morphOne relations.
5
+ * Scopes queries to WHERE morphType = value AND morphId = parentId LIMIT 1
6
+ */
7
+ export declare class MorphOneQueryBuilder extends MorphBaseQueryBuilder {
8
+ private parent;
9
+ relation: MorphOne;
10
+ constructor(builder: any, client: any, parent: any, relation: MorphOne);
11
+ profilerData(): {
12
+ type: string;
13
+ model: any;
14
+ relatedModel: any;
15
+ };
16
+ getRelationKeys(): string[];
17
+ applyConstraints(): void;
18
+ clone(): MorphOneQueryBuilder;
19
+ paginate(): never;
20
+ getGroupLimitQuery(): never;
21
+ }
22
+ //# sourceMappingURL=query_builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query_builder.d.ts","sourceRoot":"","sources":["../../../../src/relations/morph_one/query_builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAE1C;;;GAGG;AACH,qBAAa,oBAAqB,SAAQ,qBAAqB;IAI3D,OAAO,CAAC,MAAM;IACP,QAAQ,EAAE,QAAQ;gBAHzB,OAAO,EAAE,GAAG,EACZ,MAAM,EAAE,GAAG,EACH,MAAM,EAAE,GAAG,EACZ,QAAQ,EAAE,QAAQ;IAa3B,YAAY;;;;;IAQZ,eAAe,IAAI,MAAM,EAAE;IAI3B,gBAAgB,IAAI,IAAI;IAwCxB,KAAK,IAAI,oBAAoB;IAa7B,QAAQ,IAAI,KAAK;IAMjB,kBAAkB,IAAI,KAAK;CAK5B"}
@@ -0,0 +1,79 @@
1
+ import { unique } from '@adonisjs/lucid/utils';
2
+ import { MorphBaseQueryBuilder } from '../shared/query_builder.js';
3
+ /**
4
+ * Query builder for morphOne relations.
5
+ * Scopes queries to WHERE morphType = value AND morphId = parentId LIMIT 1
6
+ */
7
+ export class MorphOneQueryBuilder extends MorphBaseQueryBuilder {
8
+ parent;
9
+ relation;
10
+ constructor(builder, client, parent, relation) {
11
+ super(builder, relation.relatedModel(), client, (userFn) => {
12
+ return ($builder) => {
13
+ const subQuery = new MorphOneQueryBuilder($builder, this.client, this.parent, this.relation);
14
+ subQuery.isChildQuery = true;
15
+ subQuery.isRelatedPreloadQuery = this.isRelatedPreloadQuery;
16
+ userFn(subQuery);
17
+ subQuery.applyWhere();
18
+ };
19
+ });
20
+ this.parent = parent;
21
+ this.relation = relation;
22
+ }
23
+ profilerData() {
24
+ return {
25
+ type: this.relation.type,
26
+ model: this.relation.model.name,
27
+ relatedModel: this.relation.relatedModel().name,
28
+ };
29
+ }
30
+ getRelationKeys() {
31
+ return [this.relation.morphIdKey];
32
+ }
33
+ applyConstraints() {
34
+ if (this.appliedConstraints)
35
+ return;
36
+ this.appliedConstraints = true;
37
+ const queryAction = this.queryAction();
38
+ if (Array.isArray(this.parent)) {
39
+ // Eager loading: WHERE type = 'posts' AND id IN (1, 2, 3)
40
+ const ids = unique(this.parent.map((model) => {
41
+ const val = model[this.relation.localKey];
42
+ if (val === undefined) {
43
+ throw new Error(`Cannot preload "${this.relation.relationName}", value of "${this.relation.model.name}.${this.relation.localKey}" is undefined`);
44
+ }
45
+ return val;
46
+ }));
47
+ this.wrapExisting()
48
+ .where(this.relation.morphTypeColumnName, this.relation.morphValue)
49
+ .whereIn(this.relation.morphIdColumnName, ids);
50
+ }
51
+ else {
52
+ // Single query: WHERE type = 'posts' AND id = 5 LIMIT 1
53
+ const id = this.parent[this.relation.localKey];
54
+ if (id === undefined) {
55
+ throw new Error(`Cannot ${queryAction} "${this.relation.relationName}", value of "${this.relation.model.name}.${this.relation.localKey}" is undefined`);
56
+ }
57
+ this.wrapExisting()
58
+ .where(this.relation.morphTypeColumnName, this.relation.morphValue)
59
+ .where(this.relation.morphIdColumnName, id);
60
+ if (!['update', 'delete'].includes(queryAction)) {
61
+ this.limit(1);
62
+ }
63
+ }
64
+ }
65
+ clone() {
66
+ const clonedQuery = new MorphOneQueryBuilder(this.knexQuery.clone(), this.client, this.parent, this.relation);
67
+ clonedQuery.appliedConstraints = this.appliedConstraints;
68
+ clonedQuery.isRelatedPreloadQuery = this.isRelatedPreloadQuery;
69
+ this.applyQueryFlags(clonedQuery);
70
+ return clonedQuery;
71
+ }
72
+ paginate() {
73
+ throw new Error(`Cannot paginate a morphOne relationship "(${this.relation.relationName})"`);
74
+ }
75
+ getGroupLimitQuery() {
76
+ throw new Error(`Cannot apply groupLimit on a morphOne relationship "(${this.relation.relationName})"`);
77
+ }
78
+ }
79
+ //# sourceMappingURL=query_builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query_builder.js","sourceRoot":"","sources":["../../../../src/relations/morph_one/query_builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AAGlE;;;GAGG;AACH,MAAM,OAAO,oBAAqB,SAAQ,qBAAqB;IAInD;IACD;IAJT,YACE,OAAY,EACZ,MAAW,EACH,MAAW,EACZ,QAAkB;QAEzB,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,CAAC,MAAW,EAAE,EAAE;YAC9D,OAAO,CAAC,QAAa,EAAE,EAAE;gBACvB,MAAM,QAAQ,GAAG,IAAI,oBAAoB,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;gBAC5F,QAAQ,CAAC,YAAY,GAAG,IAAI,CAAA;gBAC5B,QAAQ,CAAC,qBAAqB,GAAG,IAAI,CAAC,qBAAqB,CAAA;gBAC3D,MAAM,CAAC,QAAQ,CAAC,CAAA;gBAChB,QAAQ,CAAC,UAAU,EAAE,CAAA;YACvB,CAAC,CAAA;QACH,CAAC,CAAC,CAAA;QAXM,WAAM,GAAN,MAAM,CAAK;QACZ,aAAQ,GAAR,QAAQ,CAAU;IAW3B,CAAC;IAED,YAAY;QACV,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI;YACxB,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI;YAC/B,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,IAAI;SAChD,CAAA;IACH,CAAC;IAED,eAAe;QACb,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;IACnC,CAAC;IAED,gBAAgB;QACd,IAAI,IAAI,CAAC,kBAAkB;YAAE,OAAM;QACnC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAA;QAE9B,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;QAEtC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/B,0DAA0D;YAC1D,MAAM,GAAG,GAAG,MAAM,CAChB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAU,EAAE,EAAE;gBAC7B,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;gBACzC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;oBACtB,MAAM,IAAI,KAAK,CACb,mBAAmB,IAAI,CAAC,QAAQ,CAAC,YAAY,gBAAgB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,gBAAgB,CAChI,CAAA;gBACH,CAAC;gBACD,OAAO,GAAG,CAAA;YACZ,CAAC,CAAC,CACH,CAAA;YACD,IAAI,CAAC,YAAY,EAAE;iBAChB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,mBAAmB,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;iBAClE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAA;QAClD,CAAC;aAAM,CAAC;YACN,wDAAwD;YACxD,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;YAC9C,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;gBACrB,MAAM,IAAI,KAAK,CACb,UAAU,WAAW,KAAK,IAAI,CAAC,QAAQ,CAAC,YAAY,gBAAgB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,gBAAgB,CACvI,CAAA;YACH,CAAC;YACD,IAAI,CAAC,YAAY,EAAE;iBAChB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,mBAAmB,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;iBAClE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAA;YAE7C,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBAChD,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;YACf,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK;QACH,MAAM,WAAW,GAAG,IAAI,oBAAoB,CAC1C,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,EACtB,IAAI,CAAC,MAAM,EACX,IAAI,CAAC,MAAM,EACX,IAAI,CAAC,QAAQ,CACd,CAAA;QACD,WAAW,CAAC,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,CAAA;QACxD,WAAW,CAAC,qBAAqB,GAAG,IAAI,CAAC,qBAAqB,CAC7D;QAAC,IAAY,CAAC,eAAe,CAAC,WAAW,CAAC,CAAA;QAC3C,OAAO,WAAW,CAAA;IACpB,CAAC;IAED,QAAQ;QACN,MAAM,IAAI,KAAK,CACb,6CAA6C,IAAI,CAAC,QAAQ,CAAC,YAAY,IAAI,CAC5E,CAAA;IACH,CAAC;IAED,kBAAkB;QAChB,MAAM,IAAI,KAAK,CACb,wDAAwD,IAAI,CAAC,QAAQ,CAAC,YAAY,IAAI,CACvF,CAAA;IACH,CAAC;CACF"}
@@ -0,0 +1,41 @@
1
+ import { MorphOneQueryBuilder } from './query_builder.js';
2
+ import type { MorphOne } from './index.js';
3
+ /**
4
+ * Query client for morphOne - provides read and write methods
5
+ * in scope of the relation.
6
+ */
7
+ export declare class MorphOneQueryClient {
8
+ private relation;
9
+ private parent;
10
+ private client;
11
+ constructor(relation: MorphOne, parent: any, client: any);
12
+ /**
13
+ * Creates an eager-load query builder (used by the Lucid preloader).
14
+ */
15
+ static eagerQuery(client: any, relation: MorphOne, rows: any | any[]): MorphOneQueryBuilder;
16
+ /**
17
+ * Creates a subquery builder (used for whereHas / withCount).
18
+ */
19
+ static subQuery(_client: any, relation: MorphOne): never;
20
+ /**
21
+ * Returns a query builder scoped to this relation for ad-hoc queries.
22
+ */
23
+ query(): MorphOneQueryBuilder;
24
+ /**
25
+ * Saves an existing related model instance, hydrating the morph FK columns.
26
+ */
27
+ save(related: any): Promise<void>;
28
+ /**
29
+ * Creates a new related model instance, automatically setting morph FK columns.
30
+ */
31
+ create(values: Record<string, any>, options?: any): Promise<any>;
32
+ /**
33
+ * Finds the first matching related model or creates a new one.
34
+ */
35
+ firstOrCreate(search: Record<string, any>, savePayload?: Record<string, any>, options?: any): Promise<any>;
36
+ /**
37
+ * Updates the existing related model or creates a new one.
38
+ */
39
+ updateOrCreate(search: Record<string, any>, updatePayload: Record<string, any>, options?: any): Promise<any>;
40
+ }
41
+ //# sourceMappingURL=query_client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query_client.d.ts","sourceRoot":"","sources":["../../../../src/relations/morph_one/query_client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAE1C;;;GAGG;AACH,qBAAa,mBAAmB;IAE5B,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;gBAFN,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,GAAG,EACX,MAAM,EAAE,GAAG;IAGrB;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,GAAG,GAAG,EAAE;IAOpE;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,GAAG,KAAK;IAMxD;;OAEG;IACH,KAAK,IAAI,oBAAoB;IAW7B;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAUvC;;OAEG;IACG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAUtE;;OAEG;IACG,aAAa,CACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACjC,OAAO,CAAC,EAAE,GAAG,GACZ,OAAO,CAAC,GAAG,CAAC;IAYf;;OAEG;IACG,cAAc,CAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAClC,OAAO,CAAC,EAAE,GAAG,GACZ,OAAO,CAAC,GAAG,CAAC;CAWhB"}
@@ -0,0 +1,94 @@
1
+ import { managedTransaction } from '@adonisjs/lucid/utils';
2
+ import { MorphOneQueryBuilder } from './query_builder.js';
3
+ /**
4
+ * Query client for morphOne - provides read and write methods
5
+ * in scope of the relation.
6
+ */
7
+ export class MorphOneQueryClient {
8
+ relation;
9
+ parent;
10
+ client;
11
+ constructor(relation, parent, client) {
12
+ this.relation = relation;
13
+ this.parent = parent;
14
+ this.client = client;
15
+ }
16
+ /**
17
+ * Creates an eager-load query builder (used by the Lucid preloader).
18
+ */
19
+ static eagerQuery(client, relation, rows) {
20
+ const query = new MorphOneQueryBuilder(client.knexQuery(), client, rows, relation);
21
+ query.isRelatedPreloadQuery = true;
22
+ if (typeof relation.onQueryHook === 'function')
23
+ relation.onQueryHook(query);
24
+ return query;
25
+ }
26
+ /**
27
+ * Creates a subquery builder (used for whereHas / withCount).
28
+ */
29
+ static subQuery(_client, relation) {
30
+ throw new Error(`morphOne: whereHas/withCount is not yet supported for polymorphic relations ("${relation.relationName}")`);
31
+ }
32
+ /**
33
+ * Returns a query builder scoped to this relation for ad-hoc queries.
34
+ */
35
+ query() {
36
+ const query = new MorphOneQueryBuilder(this.client.knexQuery(), this.client, this.parent, this.relation);
37
+ if (typeof this.relation.onQueryHook === 'function')
38
+ this.relation.onQueryHook(query);
39
+ return query;
40
+ }
41
+ /**
42
+ * Saves an existing related model instance, hydrating the morph FK columns.
43
+ */
44
+ async save(related) {
45
+ await managedTransaction(this.parent.$trx || this.client, async (trx) => {
46
+ this.parent.$trx = trx;
47
+ await this.parent.save();
48
+ this.relation.hydrateForPersistance(this.parent, related);
49
+ related.$trx = trx;
50
+ await related.save();
51
+ });
52
+ }
53
+ /**
54
+ * Creates a new related model instance, automatically setting morph FK columns.
55
+ */
56
+ async create(values, options) {
57
+ return managedTransaction(this.parent.$trx || this.client, async (trx) => {
58
+ this.parent.$trx = trx;
59
+ await this.parent.save();
60
+ const valuesToPersist = { ...values };
61
+ this.relation.hydrateForPersistance(this.parent, valuesToPersist);
62
+ return this.relation.relatedModel().create(valuesToPersist, { client: trx, ...options });
63
+ });
64
+ }
65
+ /**
66
+ * Finds the first matching related model or creates a new one.
67
+ */
68
+ async firstOrCreate(search, savePayload, options) {
69
+ return managedTransaction(this.parent.$trx || this.client, async (trx) => {
70
+ this.parent.$trx = trx;
71
+ await this.parent.save();
72
+ const valuesToPersist = { ...search };
73
+ this.relation.hydrateForPersistance(this.parent, valuesToPersist);
74
+ return this.relation
75
+ .relatedModel()
76
+ .firstOrCreate(valuesToPersist, savePayload, { client: trx, ...options });
77
+ });
78
+ }
79
+ /**
80
+ * Updates the existing related model or creates a new one.
81
+ */
82
+ async updateOrCreate(search, updatePayload, options) {
83
+ return managedTransaction(this.parent.$trx || this.client, async (trx) => {
84
+ this.parent.$trx = trx;
85
+ await this.parent.save();
86
+ const valuesToPersist = { ...search };
87
+ this.relation.hydrateForPersistance(this.parent, valuesToPersist);
88
+ return this.relation
89
+ .relatedModel()
90
+ .updateOrCreate(valuesToPersist, updatePayload, { client: trx, ...options });
91
+ });
92
+ }
93
+ }
94
+ //# sourceMappingURL=query_client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query_client.js","sourceRoot":"","sources":["../../../../src/relations/morph_one/query_client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { MorphTo } from './index.js';
2
+ /**
3
+ * Handles eager loading for morphTo relations.
4
+ *
5
+ * Since different parent rows may belong to completely different model types
6
+ * (e.g., some comments belong to Post, others to Video), a single SQL query
7
+ * cannot cover all cases. This loader:
8
+ * 1. Groups parents by their morph type value
9
+ * 2. Runs one query per unique type against the correct table
10
+ * 3. Tags each result with __morphType and __morphPk in $extras
11
+ * so setRelatedForMany() can match them back to their parents
12
+ */
13
+ export declare class MorphToEagerLoader {
14
+ private client;
15
+ private relation;
16
+ private parents;
17
+ isRelatedPreloadQuery: boolean;
18
+ constructor(client: any, relation: MorphTo, parents: any[]);
19
+ debug(_flag: boolean): this;
20
+ sideload(_values: Record<string, any>): this;
21
+ selectRelationKeys(): this;
22
+ /**
23
+ * Executes all needed queries and returns a flat list of related model instances.
24
+ * Each instance gets __morphType and __morphPk stored in $extras so that
25
+ * MorphTo.setRelatedForMany() can match it back to the right parent.
26
+ */
27
+ exec(): Promise<any[]>;
28
+ }
29
+ //# sourceMappingURL=eager_loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eager_loader.d.ts","sourceRoot":"","sources":["../../../../src/relations/morph_to/eager_loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAEzC;;;;;;;;;;GAUG;AACH,qBAAa,kBAAkB;IAI3B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,OAAO;IALjB,qBAAqB,UAAO;gBAGlB,MAAM,EAAE,GAAG,EACX,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,GAAG,EAAE;IAKxB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAI3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAI5C,kBAAkB,IAAI,IAAI;IAI1B;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;CA8C7B"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Handles eager loading for morphTo relations.
3
+ *
4
+ * Since different parent rows may belong to completely different model types
5
+ * (e.g., some comments belong to Post, others to Video), a single SQL query
6
+ * cannot cover all cases. This loader:
7
+ * 1. Groups parents by their morph type value
8
+ * 2. Runs one query per unique type against the correct table
9
+ * 3. Tags each result with __morphType and __morphPk in $extras
10
+ * so setRelatedForMany() can match them back to their parents
11
+ */
12
+ export class MorphToEagerLoader {
13
+ client;
14
+ relation;
15
+ parents;
16
+ isRelatedPreloadQuery = true;
17
+ constructor(client, relation, parents) {
18
+ this.client = client;
19
+ this.relation = relation;
20
+ this.parents = parents;
21
+ }
22
+ // The preloader calls these on the object returned by eagerQuery().
23
+ // For MorphTo the underlying query is dynamic, so these are no-ops.
24
+ debug(_flag) {
25
+ return this;
26
+ }
27
+ sideload(_values) {
28
+ return this;
29
+ }
30
+ selectRelationKeys() {
31
+ return this;
32
+ }
33
+ /**
34
+ * Executes all needed queries and returns a flat list of related model instances.
35
+ * Each instance gets __morphType and __morphPk stored in $extras so that
36
+ * MorphTo.setRelatedForMany() can match it back to the right parent.
37
+ */
38
+ async exec() {
39
+ // Group parent rows by their morph type value
40
+ const groups = new Map();
41
+ for (const parent of this.parents) {
42
+ const morphType = parent[this.relation.morphTypeKey];
43
+ if (!morphType)
44
+ continue;
45
+ if (!groups.has(morphType))
46
+ groups.set(morphType, []);
47
+ groups.get(morphType).push(parent);
48
+ }
49
+ const allResults = [];
50
+ for (const [morphType, parentGroup] of groups) {
51
+ const modelFactory = this.relation.resolveModelFactory(morphType);
52
+ if (!modelFactory) {
53
+ // Unknown type - skip silently (will result in null on the parent)
54
+ continue;
55
+ }
56
+ const RelatedModel = modelFactory();
57
+ // Collect unique IDs for this type
58
+ const ids = [
59
+ ...new Set(parentGroup
60
+ .map((p) => p[this.relation.morphIdKey])
61
+ .filter((v) => v != null)),
62
+ ];
63
+ if (ids.length === 0)
64
+ continue;
65
+ const results = await RelatedModel.query({ client: this.client })
66
+ .whereIn(RelatedModel.primaryKey, ids)
67
+ .exec();
68
+ // Tag each result so we can match it back during setRelatedForMany
69
+ for (const result of results) {
70
+ result.$extras.__morphType = morphType;
71
+ result.$extras.__morphPk = result[RelatedModel.primaryKey];
72
+ allResults.push(result);
73
+ }
74
+ }
75
+ return allResults;
76
+ }
77
+ }
78
+ //# sourceMappingURL=eager_loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eager_loader.js","sourceRoot":"","sources":["../../../../src/relations/morph_to/eager_loader.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,MAAM,OAAO,kBAAkB;IAInB;IACA;IACA;IALV,qBAAqB,GAAG,IAAI,CAAA;IAE5B,YACU,MAAW,EACX,QAAiB,EACjB,OAAc;QAFd,WAAM,GAAN,MAAM,CAAK;QACX,aAAQ,GAAR,QAAQ,CAAS;QACjB,YAAO,GAAP,OAAO,CAAO;IACrB,CAAC;IAEJ,oEAAoE;IACpE,oEAAoE;IACpE,KAAK,CAAC,KAAc;QAClB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,QAAQ,CAAC,OAA4B;QACnC,OAAO,IAAI,CAAA;IACb,CAAC;IAED,kBAAkB;QAChB,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,IAAI;QACR,8CAA8C;QAC9C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAiB,CAAA;QACvC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAA;YACpD,IAAI,CAAC,SAAS;gBAAE,SAAQ;YACxB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC;gBAAE,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;YACrD,MAAM,CAAC,GAAG,CAAC,SAAS,CAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACrC,CAAC;QAED,MAAM,UAAU,GAAU,EAAE,CAAA;QAE5B,KAAK,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,MAAM,EAAE,CAAC;YAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAA;YACjE,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,mEAAmE;gBACnE,SAAQ;YACV,CAAC;YAED,MAAM,YAAY,GAAG,YAAY,EAAE,CAAA;YAEnC,mCAAmC;YACnC,MAAM,GAAG,GAAG;gBACV,GAAG,IAAI,GAAG,CACR,WAAW;qBACR,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;qBAC5C,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CACjC;aACF,CAAA;YAED,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAQ;YAE9B,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;iBAC9D,OAAO,CAAC,YAAY,CAAC,UAAU,EAAE,GAAG,CAAC;iBACrC,IAAI,EAAE,CAAA;YAET,mEAAmE;YACnE,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,MAAM,CAAC,OAAO,CAAC,WAAW,GAAG,SAAS,CAAA;gBACtC,MAAM,CAAC,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAA;gBAC1D,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACzB,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAA;IACnB,CAAC;CACF"}