infrahub-server 1.6.2__py3-none-any.whl → 1.7.0__py3-none-any.whl

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 (253) hide show
  1. infrahub/actions/tasks.py +4 -2
  2. infrahub/api/exceptions.py +2 -2
  3. infrahub/api/schema.py +3 -1
  4. infrahub/artifacts/tasks.py +1 -0
  5. infrahub/auth.py +2 -2
  6. infrahub/cli/db.py +54 -28
  7. infrahub/computed_attribute/gather.py +3 -4
  8. infrahub/computed_attribute/tasks.py +23 -6
  9. infrahub/config.py +8 -0
  10. infrahub/constants/enums.py +12 -0
  11. infrahub/core/account.py +12 -9
  12. infrahub/core/attribute.py +106 -108
  13. infrahub/core/branch/models.py +44 -71
  14. infrahub/core/branch/tasks.py +5 -3
  15. infrahub/core/changelog/diff.py +1 -20
  16. infrahub/core/changelog/models.py +0 -7
  17. infrahub/core/constants/__init__.py +17 -0
  18. infrahub/core/constants/database.py +0 -1
  19. infrahub/core/constants/schema.py +0 -1
  20. infrahub/core/convert_object_type/repository_conversion.py +3 -4
  21. infrahub/core/diff/branch_differ.py +1 -1
  22. infrahub/core/diff/conflict_transferer.py +1 -1
  23. infrahub/core/diff/data_check_synchronizer.py +4 -3
  24. infrahub/core/diff/enricher/cardinality_one.py +2 -2
  25. infrahub/core/diff/enricher/hierarchy.py +1 -1
  26. infrahub/core/diff/enricher/labels.py +1 -1
  27. infrahub/core/diff/merger/merger.py +28 -2
  28. infrahub/core/diff/merger/serializer.py +3 -10
  29. infrahub/core/diff/model/diff.py +1 -1
  30. infrahub/core/diff/query/merge.py +376 -135
  31. infrahub/core/diff/repository/repository.py +3 -1
  32. infrahub/core/graph/__init__.py +1 -1
  33. infrahub/core/graph/constraints.py +3 -3
  34. infrahub/core/graph/schema.py +2 -12
  35. infrahub/core/ipam/reconciler.py +8 -6
  36. infrahub/core/ipam/utilization.py +8 -15
  37. infrahub/core/manager.py +133 -152
  38. infrahub/core/merge.py +1 -1
  39. infrahub/core/metadata/__init__.py +0 -0
  40. infrahub/core/metadata/interface.py +37 -0
  41. infrahub/core/metadata/model.py +31 -0
  42. infrahub/core/metadata/query/__init__.py +0 -0
  43. infrahub/core/metadata/query/node_metadata.py +301 -0
  44. infrahub/core/migrations/graph/__init__.py +4 -0
  45. infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -12
  46. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +7 -12
  47. infrahub/core/migrations/graph/m017_add_core_profile.py +5 -2
  48. infrahub/core/migrations/graph/m018_uniqueness_nulls.py +2 -1
  49. infrahub/core/migrations/graph/m019_restore_rels_to_time.py +0 -10
  50. infrahub/core/migrations/graph/m020_duplicate_edges.py +0 -8
  51. infrahub/core/migrations/graph/m025_uniqueness_nulls.py +2 -1
  52. infrahub/core/migrations/graph/m026_0000_prefix_fix.py +2 -1
  53. infrahub/core/migrations/graph/m029_duplicates_cleanup.py +0 -1
  54. infrahub/core/migrations/graph/m031_check_number_attributes.py +2 -2
  55. infrahub/core/migrations/graph/m038_redo_0000_prefix_fix.py +2 -1
  56. infrahub/core/migrations/graph/m041_deleted_dup_edges.py +1 -1
  57. infrahub/core/migrations/graph/m049_remove_is_visible_relationship.py +53 -0
  58. infrahub/core/migrations/graph/m050_backfill_vertex_metadata.py +168 -0
  59. infrahub/core/migrations/query/__init__.py +2 -2
  60. infrahub/core/migrations/query/attribute_add.py +17 -6
  61. infrahub/core/migrations/query/attribute_remove.py +19 -5
  62. infrahub/core/migrations/query/attribute_rename.py +21 -5
  63. infrahub/core/migrations/query/node_duplicate.py +19 -4
  64. infrahub/core/migrations/query/schema_attribute_update.py +1 -1
  65. infrahub/core/migrations/schema/attribute_kind_update.py +26 -6
  66. infrahub/core/migrations/schema/attribute_name_update.py +1 -1
  67. infrahub/core/migrations/schema/attribute_supports_profile.py +5 -3
  68. infrahub/core/migrations/schema/models.py +3 -0
  69. infrahub/core/migrations/schema/node_attribute_add.py +5 -2
  70. infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
  71. infrahub/core/migrations/schema/node_kind_update.py +1 -1
  72. infrahub/core/migrations/schema/node_remove.py +24 -2
  73. infrahub/core/migrations/schema/tasks.py +4 -1
  74. infrahub/core/migrations/shared.py +13 -6
  75. infrahub/core/models.py +6 -6
  76. infrahub/core/node/__init__.py +157 -58
  77. infrahub/core/node/base.py +9 -5
  78. infrahub/core/node/create.py +7 -3
  79. infrahub/core/node/delete_validator.py +1 -1
  80. infrahub/core/node/standard.py +100 -14
  81. infrahub/core/order.py +30 -0
  82. infrahub/core/property.py +0 -1
  83. infrahub/core/protocols.py +1 -0
  84. infrahub/core/protocols_base.py +10 -2
  85. infrahub/core/query/__init__.py +11 -6
  86. infrahub/core/query/attribute.py +164 -49
  87. infrahub/core/query/branch.py +58 -70
  88. infrahub/core/query/delete.py +1 -1
  89. infrahub/core/query/diff.py +7 -7
  90. infrahub/core/query/ipam.py +104 -43
  91. infrahub/core/query/node.py +1072 -281
  92. infrahub/core/query/relationship.py +531 -325
  93. infrahub/core/query/resource_manager.py +107 -18
  94. infrahub/core/query/standard_node.py +25 -5
  95. infrahub/core/query/utils.py +2 -4
  96. infrahub/core/relationship/constraints/count.py +1 -1
  97. infrahub/core/relationship/constraints/peer_kind.py +1 -1
  98. infrahub/core/relationship/constraints/peer_parent.py +1 -1
  99. infrahub/core/relationship/constraints/peer_relatives.py +1 -1
  100. infrahub/core/relationship/constraints/profiles_kind.py +1 -1
  101. infrahub/core/relationship/constraints/profiles_removal.py +168 -0
  102. infrahub/core/relationship/model.py +293 -139
  103. infrahub/core/schema/attribute_parameters.py +28 -1
  104. infrahub/core/schema/attribute_schema.py +11 -17
  105. infrahub/core/schema/basenode_schema.py +3 -0
  106. infrahub/core/schema/definitions/core/__init__.py +8 -2
  107. infrahub/core/schema/definitions/core/account.py +10 -10
  108. infrahub/core/schema/definitions/core/artifact.py +14 -8
  109. infrahub/core/schema/definitions/core/check.py +10 -4
  110. infrahub/core/schema/definitions/core/generator.py +26 -6
  111. infrahub/core/schema/definitions/core/graphql_query.py +1 -1
  112. infrahub/core/schema/definitions/core/group.py +9 -2
  113. infrahub/core/schema/definitions/core/ipam.py +80 -10
  114. infrahub/core/schema/definitions/core/menu.py +41 -7
  115. infrahub/core/schema/definitions/core/permission.py +16 -2
  116. infrahub/core/schema/definitions/core/profile.py +16 -2
  117. infrahub/core/schema/definitions/core/propose_change.py +24 -4
  118. infrahub/core/schema/definitions/core/propose_change_comment.py +23 -11
  119. infrahub/core/schema/definitions/core/propose_change_validator.py +50 -21
  120. infrahub/core/schema/definitions/core/repository.py +10 -0
  121. infrahub/core/schema/definitions/core/resource_pool.py +8 -1
  122. infrahub/core/schema/definitions/core/template.py +19 -2
  123. infrahub/core/schema/definitions/core/transform.py +11 -5
  124. infrahub/core/schema/definitions/core/webhook.py +27 -9
  125. infrahub/core/schema/manager.py +63 -43
  126. infrahub/core/schema/relationship_schema.py +6 -2
  127. infrahub/core/schema/schema_branch.py +115 -11
  128. infrahub/core/task/task.py +4 -2
  129. infrahub/core/utils.py +3 -25
  130. infrahub/core/validators/aggregated_checker.py +1 -1
  131. infrahub/core/validators/attribute/choices.py +1 -1
  132. infrahub/core/validators/attribute/enum.py +1 -1
  133. infrahub/core/validators/attribute/kind.py +6 -3
  134. infrahub/core/validators/attribute/length.py +1 -1
  135. infrahub/core/validators/attribute/min_max.py +1 -1
  136. infrahub/core/validators/attribute/number_pool.py +1 -1
  137. infrahub/core/validators/attribute/optional.py +1 -1
  138. infrahub/core/validators/attribute/regex.py +1 -1
  139. infrahub/core/validators/determiner.py +3 -3
  140. infrahub/core/validators/node/attribute.py +1 -1
  141. infrahub/core/validators/node/relationship.py +1 -1
  142. infrahub/core/validators/relationship/peer.py +1 -1
  143. infrahub/database/__init__.py +4 -4
  144. infrahub/dependencies/builder/constraint/grouped/node_runner.py +2 -0
  145. infrahub/dependencies/builder/constraint/relationship_manager/profiles_removal.py +8 -0
  146. infrahub/dependencies/registry.py +2 -0
  147. infrahub/display_labels/tasks.py +12 -3
  148. infrahub/git/integrator.py +18 -18
  149. infrahub/git/tasks.py +1 -1
  150. infrahub/git/utils.py +1 -1
  151. infrahub/graphql/app.py +2 -2
  152. infrahub/graphql/constants.py +3 -0
  153. infrahub/graphql/context.py +1 -1
  154. infrahub/graphql/field_extractor.py +1 -1
  155. infrahub/graphql/initialization.py +11 -0
  156. infrahub/graphql/loaders/account.py +134 -0
  157. infrahub/graphql/loaders/node.py +5 -12
  158. infrahub/graphql/loaders/peers.py +5 -7
  159. infrahub/graphql/manager.py +175 -21
  160. infrahub/graphql/metadata.py +91 -0
  161. infrahub/graphql/mutations/account.py +6 -6
  162. infrahub/graphql/mutations/attribute.py +0 -2
  163. infrahub/graphql/mutations/branch.py +9 -5
  164. infrahub/graphql/mutations/computed_attribute.py +1 -1
  165. infrahub/graphql/mutations/display_label.py +1 -1
  166. infrahub/graphql/mutations/hfid.py +1 -1
  167. infrahub/graphql/mutations/ipam.py +4 -6
  168. infrahub/graphql/mutations/main.py +9 -4
  169. infrahub/graphql/mutations/profile.py +16 -22
  170. infrahub/graphql/mutations/proposed_change.py +4 -4
  171. infrahub/graphql/mutations/relationship.py +40 -10
  172. infrahub/graphql/mutations/repository.py +14 -12
  173. infrahub/graphql/mutations/schema.py +2 -2
  174. infrahub/graphql/order.py +14 -0
  175. infrahub/graphql/queries/branch.py +62 -6
  176. infrahub/graphql/queries/diff/tree.py +5 -5
  177. infrahub/graphql/queries/resource_manager.py +25 -24
  178. infrahub/graphql/resolvers/account_metadata.py +84 -0
  179. infrahub/graphql/resolvers/ipam.py +6 -8
  180. infrahub/graphql/resolvers/many_relationship.py +77 -35
  181. infrahub/graphql/resolvers/resolver.py +59 -14
  182. infrahub/graphql/resolvers/single_relationship.py +87 -23
  183. infrahub/graphql/subscription/graphql_query.py +2 -0
  184. infrahub/graphql/types/__init__.py +0 -1
  185. infrahub/graphql/types/attribute.py +10 -5
  186. infrahub/graphql/types/branch.py +40 -53
  187. infrahub/graphql/types/enums.py +3 -0
  188. infrahub/graphql/types/metadata.py +28 -0
  189. infrahub/graphql/types/node.py +22 -2
  190. infrahub/graphql/types/relationship.py +10 -2
  191. infrahub/graphql/types/standard_node.py +12 -7
  192. infrahub/hfid/tasks.py +12 -3
  193. infrahub/lock.py +7 -0
  194. infrahub/menu/repository.py +1 -1
  195. infrahub/patch/queries/base.py +1 -1
  196. infrahub/pools/number.py +1 -8
  197. infrahub/profiles/gather.py +56 -0
  198. infrahub/profiles/mandatory_fields_checker.py +116 -0
  199. infrahub/profiles/models.py +66 -0
  200. infrahub/profiles/node_applier.py +154 -13
  201. infrahub/profiles/queries/get_profile_data.py +143 -31
  202. infrahub/profiles/tasks.py +79 -27
  203. infrahub/profiles/triggers.py +22 -0
  204. infrahub/proposed_change/action_checker.py +1 -1
  205. infrahub/proposed_change/tasks.py +4 -1
  206. infrahub/services/__init__.py +1 -1
  207. infrahub/services/adapters/cache/nats.py +1 -1
  208. infrahub/services/adapters/cache/redis.py +7 -0
  209. infrahub/tasks/artifact.py +1 -0
  210. infrahub/transformations/tasks.py +2 -2
  211. infrahub/trigger/catalogue.py +2 -0
  212. infrahub/trigger/models.py +1 -0
  213. infrahub/trigger/setup.py +3 -3
  214. infrahub/trigger/tasks.py +3 -0
  215. infrahub/validators/tasks.py +1 -0
  216. infrahub/webhook/gather.py +1 -1
  217. infrahub/webhook/models.py +1 -1
  218. infrahub/webhook/tasks.py +23 -7
  219. infrahub/workers/dependencies.py +9 -3
  220. infrahub/workers/infrahub_async.py +13 -4
  221. infrahub/workflows/catalogue.py +19 -0
  222. infrahub_sdk/analyzer.py +2 -2
  223. infrahub_sdk/branch.py +12 -39
  224. infrahub_sdk/checks.py +4 -4
  225. infrahub_sdk/client.py +36 -0
  226. infrahub_sdk/ctl/cli_commands.py +2 -1
  227. infrahub_sdk/ctl/graphql.py +15 -4
  228. infrahub_sdk/ctl/utils.py +2 -2
  229. infrahub_sdk/enums.py +6 -0
  230. infrahub_sdk/graphql/renderers.py +21 -0
  231. infrahub_sdk/graphql/utils.py +85 -0
  232. infrahub_sdk/node/attribute.py +12 -2
  233. infrahub_sdk/node/constants.py +12 -0
  234. infrahub_sdk/node/metadata.py +69 -0
  235. infrahub_sdk/node/node.py +65 -14
  236. infrahub_sdk/node/property.py +3 -0
  237. infrahub_sdk/node/related_node.py +37 -5
  238. infrahub_sdk/node/relationship.py +18 -1
  239. infrahub_sdk/operation.py +2 -2
  240. infrahub_sdk/schema/repository.py +1 -2
  241. infrahub_sdk/transforms.py +2 -2
  242. infrahub_sdk/types.py +18 -2
  243. {infrahub_server-1.6.2.dist-info → infrahub_server-1.7.0.dist-info}/METADATA +17 -16
  244. {infrahub_server-1.6.2.dist-info → infrahub_server-1.7.0.dist-info}/RECORD +252 -231
  245. infrahub_testcontainers/container.py +3 -3
  246. infrahub_testcontainers/docker-compose-cluster.test.yml +7 -7
  247. infrahub_testcontainers/docker-compose.test.yml +13 -5
  248. infrahub_testcontainers/models.py +3 -3
  249. infrahub_testcontainers/performance_test.py +1 -1
  250. infrahub/graphql/models.py +0 -6
  251. {infrahub_server-1.6.2.dist-info → infrahub_server-1.7.0.dist-info}/WHEEL +0 -0
  252. {infrahub_server-1.6.2.dist-info → infrahub_server-1.7.0.dist-info}/entry_points.txt +0 -0
  253. {infrahub_server-1.6.2.dist-info → infrahub_server-1.7.0.dist-info}/licenses/LICENSE.txt +0 -0
infrahub/core/manager.py CHANGED
@@ -5,9 +5,17 @@ from typing import TYPE_CHECKING, Any, Iterable, Literal, TypeVar, overload
5
5
 
6
6
  from infrahub_sdk.utils import deep_merge_dict, is_valid_uuid
7
7
 
8
- from infrahub.core.constants import InfrahubKind, RelationshipCardinality, RelationshipDirection
8
+ from infrahub.core.constants import (
9
+ SYSTEM_USER_ID,
10
+ InfrahubKind,
11
+ MetadataOptions,
12
+ RelationshipCardinality,
13
+ RelationshipDirection,
14
+ )
15
+ from infrahub.core.metadata.model import MetadataQueryOptions
9
16
  from infrahub.core.node import Node
10
17
  from infrahub.core.node.delete_validator import NodeDeleteValidator
18
+ from infrahub.core.order import OrderModel
11
19
  from infrahub.core.query.node import (
12
20
  AttributeFromDB,
13
21
  GroupedPeerNodes,
@@ -21,6 +29,7 @@ from infrahub.core.query.node import (
21
29
  from infrahub.core.query.relationship import RelationshipGetPeerQuery
22
30
  from infrahub.core.registry import registry
23
31
  from infrahub.core.relationship import Relationship, RelationshipManager
32
+ from infrahub.core.relationship.model import PeerWithRelationshipMetadata
24
33
  from infrahub.core.schema import (
25
34
  GenericSchema,
26
35
  MainSchemaTypes,
@@ -31,7 +40,6 @@ from infrahub.core.schema import (
31
40
  )
32
41
  from infrahub.core.timestamp import Timestamp
33
42
  from infrahub.exceptions import NodeNotFoundError, ProcessingError, SchemaNotFoundError
34
- from infrahub.graphql.models import OrderModel
35
43
 
36
44
  if TYPE_CHECKING:
37
45
  from infrahub.core.branch import Branch
@@ -88,10 +96,8 @@ class NodeManager:
88
96
  limit: int | None = ...,
89
97
  at: Timestamp | str | None = ...,
90
98
  branch: Branch | str | None = ...,
91
- include_source: bool = ...,
92
- include_owner: bool = ...,
99
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
93
100
  prefetch_relationships: bool = ...,
94
- account=...,
95
101
  partial_match: bool = ...,
96
102
  branch_agnostic: bool = ...,
97
103
  order: OrderModel | None = ...,
@@ -109,10 +115,8 @@ class NodeManager:
109
115
  limit: int | None = ...,
110
116
  at: Timestamp | str | None = ...,
111
117
  branch: Branch | str | None = ...,
112
- include_source: bool = ...,
113
- include_owner: bool = ...,
118
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
114
119
  prefetch_relationships: bool = ...,
115
- account=...,
116
120
  partial_match: bool = ...,
117
121
  branch_agnostic: bool = ...,
118
122
  order: OrderModel | None = ...,
@@ -129,10 +133,8 @@ class NodeManager:
129
133
  limit: int | None = None,
130
134
  at: Timestamp | str | None = None,
131
135
  branch: Branch | str | None = None,
132
- include_source: bool = False,
133
- include_owner: bool = False,
136
+ include_metadata: MetadataQueryOptions | MetadataOptions = MetadataOptions.NONE,
134
137
  prefetch_relationships: bool = False,
135
- account=None,
136
138
  partial_match: bool = False,
137
139
  branch_agnostic: bool = False,
138
140
  order: OrderModel | None = None,
@@ -164,10 +166,8 @@ class NodeManager:
164
166
  fields=fields,
165
167
  at=at,
166
168
  branch=branch,
167
- include_source=include_source,
168
- include_owner=include_owner,
169
+ include_metadata=include_metadata,
169
170
  prefetch_relationships=prefetch_relationships,
170
- account=account,
171
171
  branch_agnostic=branch_agnostic,
172
172
  )
173
173
  return [node] if node else []
@@ -209,10 +209,8 @@ class NodeManager:
209
209
  ids=node_ids,
210
210
  fields=fields,
211
211
  branch=branch,
212
- account=account,
213
212
  at=at,
214
- include_source=include_source,
215
- include_owner=include_owner,
213
+ include_metadata=include_metadata,
216
214
  db=db,
217
215
  prefetch_relationships=prefetch_relationships,
218
216
  branch_agnostic=branch_agnostic,
@@ -228,7 +226,6 @@ class NodeManager:
228
226
  filters: dict | None = None,
229
227
  at: Timestamp | str | None = None,
230
228
  branch: Branch | str | None = None,
231
- account=None, # noqa: ARG003
232
229
  partial_match: bool = False,
233
230
  branch_agnostic: bool = False,
234
231
  ) -> int:
@@ -276,15 +273,14 @@ class NodeManager:
276
273
  branch = await registry.get_branch(branch=branch, db=db)
277
274
  at = Timestamp(at)
278
275
 
279
- rel = Relationship(schema=schema, branch=branch, node_id="PLACEHOLDER")
280
-
281
276
  query = await RelationshipGetPeerQuery.init(
282
277
  db=db,
278
+ branch=branch,
283
279
  source_ids=ids,
284
280
  source_kind=source_kind,
285
281
  schema=schema,
286
282
  filters=filters,
287
- rel=rel,
283
+ rel=Relationship,
288
284
  at=at,
289
285
  branch_agnostic=branch_agnostic,
290
286
  )
@@ -305,25 +301,29 @@ class NodeManager:
305
301
  branch: Branch | str | None = None,
306
302
  branch_agnostic: bool = False,
307
303
  fetch_peers: bool = False,
308
- include_source: bool = False,
309
- include_owner: bool = False,
304
+ include_metadata: MetadataQueryOptions | MetadataOptions = MetadataOptions.NONE,
310
305
  ) -> list[Relationship]:
311
306
  branch = await registry.get_branch(branch=branch, db=db)
312
307
  at = Timestamp(at)
313
308
 
314
- rel = Relationship(schema=schema, branch=branch, node_id="PLACEHOLDER")
315
-
309
+ relationship_metadata_options = (
310
+ include_metadata.relationship_level
311
+ if isinstance(include_metadata, MetadataQueryOptions)
312
+ else include_metadata
313
+ )
316
314
  query = await RelationshipGetPeerQuery.init(
317
315
  db=db,
316
+ branch=branch,
318
317
  source_ids=ids,
319
318
  source_kind=source_kind,
320
319
  schema=schema,
321
320
  filters=filters,
322
- rel=rel,
321
+ rel=Relationship,
323
322
  offset=offset,
324
323
  limit=limit,
325
324
  at=at,
326
325
  branch_agnostic=branch_agnostic,
326
+ include_metadata=relationship_metadata_options,
327
327
  )
328
328
  await query.execute(db=db)
329
329
 
@@ -354,17 +354,21 @@ class NodeManager:
354
354
  at=at,
355
355
  branch=branch,
356
356
  branch_agnostic=branch_agnostic,
357
- include_source=include_source,
358
- include_owner=include_owner,
357
+ include_metadata=include_metadata,
359
358
  )
360
359
 
361
360
  results = []
362
361
  for peer in peers_info:
363
- result = Relationship(schema=schema, branch=branch, at=at, node_id=peer.source_id).load(
362
+ result = Relationship(
363
+ schema=schema,
364
+ branch=branch,
365
+ source_kind=peer.source_kind,
366
+ at=at,
367
+ node_id=peer.source_id,
368
+ ).load(
364
369
  db=db,
365
370
  id=peer.rel_node_id,
366
371
  db_id=peer.rel_node_db_id,
367
- updated_at=peer.updated_at,
368
372
  data=peer,
369
373
  )
370
374
  if fetch_peers:
@@ -435,7 +439,12 @@ class NodeManager:
435
439
  return {}
436
440
 
437
441
  return await cls.get_many(
438
- db=db, ids=peers_ids, fields=fields, at=at, branch=branch, include_owner=True, include_source=True
442
+ db=db,
443
+ ids=peers_ids,
444
+ fields=fields,
445
+ at=at,
446
+ branch=branch,
447
+ include_metadata=MetadataOptions.LINKED_NODES,
439
448
  )
440
449
 
441
450
  @overload
@@ -479,8 +488,7 @@ class NodeManager:
479
488
  id=id,
480
489
  branch=branch,
481
490
  at=at,
482
- include_owner=True,
483
- include_source=True,
491
+ include_metadata=MetadataOptions.LINKED_NODES,
484
492
  raise_on_error=True,
485
493
  )
486
494
 
@@ -491,8 +499,7 @@ class NodeManager:
491
499
  hfid=hfid,
492
500
  branch=branch,
493
501
  at=at,
494
- include_owner=True,
495
- include_source=True,
502
+ include_metadata=MetadataOptions.LINKED_NODES,
496
503
  raise_on_error=True,
497
504
  )
498
505
 
@@ -503,8 +510,7 @@ class NodeManager:
503
510
  id=id,
504
511
  branch=branch,
505
512
  at=at,
506
- include_owner=True,
507
- include_source=True,
513
+ include_metadata=MetadataOptions.LINKED_NODES,
508
514
  raise_on_error=True,
509
515
  )
510
516
 
@@ -521,10 +527,8 @@ class NodeManager:
521
527
  fields: dict | None = ...,
522
528
  at: Timestamp | str | None = ...,
523
529
  branch: Branch | str | None = ...,
524
- include_source: bool = ...,
525
- include_owner: bool = ...,
530
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
526
531
  prefetch_relationships: bool = ...,
527
- account=...,
528
532
  branch_agnostic: bool = ...,
529
533
  ) -> SchemaProtocol | None: ...
530
534
 
@@ -539,10 +543,8 @@ class NodeManager:
539
543
  fields: dict | None = ...,
540
544
  at: Timestamp | str | None = ...,
541
545
  branch: Branch | str | None = ...,
542
- include_source: bool = ...,
543
- include_owner: bool = ...,
546
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
544
547
  prefetch_relationships: bool = ...,
545
- account=...,
546
548
  branch_agnostic: bool = ...,
547
549
  ) -> SchemaProtocol: ...
548
550
 
@@ -557,10 +559,8 @@ class NodeManager:
557
559
  fields: dict | None = ...,
558
560
  at: Timestamp | str | None = ...,
559
561
  branch: Branch | str | None = ...,
560
- include_source: bool = ...,
561
- include_owner: bool = ...,
562
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
562
563
  prefetch_relationships: bool = ...,
563
- account=...,
564
564
  branch_agnostic: bool = ...,
565
565
  ) -> SchemaProtocol | None: ...
566
566
 
@@ -575,10 +575,8 @@ class NodeManager:
575
575
  fields: dict | None = ...,
576
576
  at: Timestamp | str | None = ...,
577
577
  branch: Branch | str | None = ...,
578
- include_source: bool = ...,
579
- include_owner: bool = ...,
578
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
580
579
  prefetch_relationships: bool = ...,
581
- account=...,
582
580
  branch_agnostic: bool = ...,
583
581
  ) -> Node | None: ...
584
582
 
@@ -593,10 +591,8 @@ class NodeManager:
593
591
  fields: dict | None = ...,
594
592
  at: Timestamp | str | None = ...,
595
593
  branch: Branch | str | None = ...,
596
- include_source: bool = ...,
597
- include_owner: bool = ...,
594
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
598
595
  prefetch_relationships: bool = ...,
599
- account=...,
600
596
  branch_agnostic: bool = ...,
601
597
  ) -> Node: ...
602
598
 
@@ -611,10 +607,8 @@ class NodeManager:
611
607
  fields: dict | None = ...,
612
608
  at: Timestamp | str | None = ...,
613
609
  branch: Branch | str | None = ...,
614
- include_source: bool = ...,
615
- include_owner: bool = ...,
610
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
616
611
  prefetch_relationships: bool = ...,
617
- account=...,
618
612
  branch_agnostic: bool = ...,
619
613
  ) -> Node | None: ...
620
614
 
@@ -628,10 +622,8 @@ class NodeManager:
628
622
  fields: dict | None = None,
629
623
  at: Timestamp | str | None = None,
630
624
  branch: Branch | str | None = None,
631
- include_source: bool = False,
632
- include_owner: bool = False,
625
+ include_metadata: MetadataQueryOptions | MetadataOptions = MetadataOptions.NONE,
633
626
  prefetch_relationships: bool = False,
634
- account=None,
635
627
  branch_agnostic: bool = False,
636
628
  ) -> Node | SchemaProtocol | None:
637
629
  branch = await registry.get_branch(branch=branch, db=db)
@@ -651,10 +643,8 @@ class NodeManager:
651
643
  filters={node_schema.default_filter: id},
652
644
  branch=branch,
653
645
  at=at,
654
- include_owner=include_owner,
655
- include_source=include_source,
646
+ include_metadata=include_metadata,
656
647
  prefetch_relationships=prefetch_relationships,
657
- account=account,
658
648
  branch_agnostic=branch_agnostic,
659
649
  order=OrderModel(disable=True),
660
650
  )
@@ -689,10 +679,8 @@ class NodeManager:
689
679
  fields: dict | None = ...,
690
680
  at: Timestamp | str | None = ...,
691
681
  branch: Branch | str | None = ...,
692
- include_source: bool = ...,
693
- include_owner: bool = ...,
682
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
694
683
  prefetch_relationships: bool = ...,
695
- account=...,
696
684
  ) -> SchemaProtocol | None: ...
697
685
 
698
686
  @overload
@@ -706,10 +694,8 @@ class NodeManager:
706
694
  fields: dict | None = ...,
707
695
  at: Timestamp | str | None = ...,
708
696
  branch: Branch | str | None = ...,
709
- include_source: bool = ...,
710
- include_owner: bool = ...,
697
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
711
698
  prefetch_relationships: bool = ...,
712
- account=...,
713
699
  branch_agnostic: bool = ...,
714
700
  ) -> SchemaProtocol: ...
715
701
 
@@ -724,10 +710,8 @@ class NodeManager:
724
710
  fields: dict | None = ...,
725
711
  at: Timestamp | str | None = ...,
726
712
  branch: Branch | str | None = ...,
727
- include_source: bool = ...,
728
- include_owner: bool = ...,
713
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
729
714
  prefetch_relationships: bool = ...,
730
- account=...,
731
715
  branch_agnostic: bool = ...,
732
716
  ) -> SchemaProtocol | None: ...
733
717
 
@@ -742,10 +726,8 @@ class NodeManager:
742
726
  fields: dict | None = ...,
743
727
  at: Timestamp | str | None = ...,
744
728
  branch: Branch | str | None = ...,
745
- include_source: bool = ...,
746
- include_owner: bool = ...,
729
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
747
730
  prefetch_relationships: bool = ...,
748
- account=...,
749
731
  branch_agnostic: bool = ...,
750
732
  ) -> Node: ...
751
733
 
@@ -760,10 +742,8 @@ class NodeManager:
760
742
  fields: dict | None = ...,
761
743
  at: Timestamp | str | None = ...,
762
744
  branch: Branch | str | None = ...,
763
- include_source: bool = ...,
764
- include_owner: bool = ...,
745
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
765
746
  prefetch_relationships: bool = ...,
766
- account=...,
767
747
  branch_agnostic: bool = ...,
768
748
  ) -> Node | None: ...
769
749
 
@@ -778,10 +758,8 @@ class NodeManager:
778
758
  fields: dict | None = ...,
779
759
  at: Timestamp | str | None = ...,
780
760
  branch: Branch | str | None = ...,
781
- include_source: bool = ...,
782
- include_owner: bool = ...,
761
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
783
762
  prefetch_relationships: bool = ...,
784
- account=...,
785
763
  branch_agnostic: bool = ...,
786
764
  ) -> Node | None: ...
787
765
 
@@ -795,15 +773,12 @@ class NodeManager:
795
773
  fields: dict | None = None,
796
774
  at: Timestamp | str | None = None,
797
775
  branch: Branch | str | None = None,
798
- include_source: bool = False,
799
- include_owner: bool = False,
776
+ include_metadata: MetadataQueryOptions | MetadataOptions = MetadataOptions.NONE,
800
777
  prefetch_relationships: bool = False,
801
- account=None,
802
778
  branch_agnostic: bool = False,
803
779
  ) -> Node | SchemaProtocol | None:
804
780
  branch = await registry.get_branch(branch=branch, db=db)
805
781
  at = Timestamp(at)
806
-
807
782
  node_schema = get_schema(db=db, branch=branch, node_schema=kind)
808
783
  kind_str = node_schema.kind
809
784
 
@@ -833,7 +808,8 @@ class NodeManager:
833
808
  rel_schema = path.related_schema
834
809
  # Keep the relationship attribute path and parse it
835
810
  path = rel_schema.parse_schema_path(
836
- path=key.split("__", maxsplit=1)[1], schema=registry.schema.get_schema_branch(name=branch.name)
811
+ path=key.split("__", maxsplit=1)[1],
812
+ schema=registry.schema.get_schema_branch(name=branch.name),
837
813
  )
838
814
 
839
815
  filters[key] = path.active_attribute_schema.get_class().deserialize_from_string(item)
@@ -846,10 +822,8 @@ class NodeManager:
846
822
  filters=filters,
847
823
  branch=branch,
848
824
  at=at,
849
- include_owner=include_owner,
850
- include_source=include_source,
825
+ include_metadata=include_metadata,
851
826
  prefetch_relationships=prefetch_relationships,
852
- account=account,
853
827
  branch_agnostic=branch_agnostic,
854
828
  order=OrderModel(disable=True),
855
829
  )
@@ -879,10 +853,8 @@ class NodeManager:
879
853
  fields: dict | None = ...,
880
854
  at: Timestamp | str | None = ...,
881
855
  branch: Branch | str | None = ...,
882
- include_source: bool = ...,
883
- include_owner: bool = ...,
856
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
884
857
  prefetch_relationships: bool = ...,
885
- account=...,
886
858
  branch_agnostic: bool = ...,
887
859
  ) -> SchemaProtocol: ...
888
860
 
@@ -896,10 +868,8 @@ class NodeManager:
896
868
  fields: dict | None = ...,
897
869
  at: Timestamp | str | None = ...,
898
870
  branch: Branch | str | None = ...,
899
- include_source: bool = ...,
900
- include_owner: bool = ...,
871
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
901
872
  prefetch_relationships: bool = ...,
902
- account=...,
903
873
  branch_agnostic: bool = ...,
904
874
  ) -> Any: ...
905
875
 
@@ -912,10 +882,8 @@ class NodeManager:
912
882
  fields: dict | None = None,
913
883
  at: Timestamp | str | None = None,
914
884
  branch: Branch | str | None = None,
915
- include_source: bool = False,
916
- include_owner: bool = False,
885
+ include_metadata: MetadataQueryOptions | MetadataOptions = MetadataOptions.NONE,
917
886
  prefetch_relationships: bool = False,
918
- account=None,
919
887
  branch_agnostic: bool = False,
920
888
  ) -> Any:
921
889
  branch = await registry.get_branch(branch=branch, db=db)
@@ -926,11 +894,9 @@ class NodeManager:
926
894
  fields=fields,
927
895
  at=at,
928
896
  branch=branch,
929
- include_owner=include_owner,
930
- include_source=include_source,
897
+ include_metadata=include_metadata,
931
898
  db=db,
932
899
  prefetch_relationships=prefetch_relationships,
933
- account=account,
934
900
  branch_agnostic=branch_agnostic,
935
901
  )
936
902
  if node:
@@ -943,10 +909,8 @@ class NodeManager:
943
909
  fields=fields,
944
910
  at=at,
945
911
  branch=branch,
946
- include_source=include_source,
947
- include_owner=include_owner,
912
+ include_metadata=include_metadata,
948
913
  prefetch_relationships=prefetch_relationships,
949
- account=account,
950
914
  branch_agnostic=branch_agnostic,
951
915
  )
952
916
  if not node:
@@ -964,10 +928,8 @@ class NodeManager:
964
928
  fields: dict | None = ...,
965
929
  at: Timestamp | str | None = ...,
966
930
  branch: Branch | str | None = ...,
967
- include_source: bool = ...,
968
- include_owner: bool = ...,
931
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
969
932
  prefetch_relationships: bool = ...,
970
- account=...,
971
933
  branch_agnostic: bool = ...,
972
934
  ) -> SchemaProtocol | None: ...
973
935
 
@@ -982,10 +944,8 @@ class NodeManager:
982
944
  fields: dict | None = ...,
983
945
  at: Timestamp | str | None = ...,
984
946
  branch: Branch | str | None = ...,
985
- include_source: bool = ...,
986
- include_owner: bool = ...,
947
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
987
948
  prefetch_relationships: bool = ...,
988
- account=...,
989
949
  branch_agnostic: bool = ...,
990
950
  ) -> SchemaProtocol: ...
991
951
 
@@ -1000,10 +960,8 @@ class NodeManager:
1000
960
  fields: dict | None = ...,
1001
961
  at: Timestamp | str | None = ...,
1002
962
  branch: Branch | str | None = ...,
1003
- include_source: bool = ...,
1004
- include_owner: bool = ...,
963
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
1005
964
  prefetch_relationships: bool = ...,
1006
- account=...,
1007
965
  branch_agnostic: bool = ...,
1008
966
  ) -> SchemaProtocol: ...
1009
967
 
@@ -1018,10 +976,8 @@ class NodeManager:
1018
976
  fields: dict | None = ...,
1019
977
  at: Timestamp | str | None = ...,
1020
978
  branch: Branch | str | None = ...,
1021
- include_source: bool = ...,
1022
- include_owner: bool = ...,
979
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
1023
980
  prefetch_relationships: bool = ...,
1024
- account=...,
1025
981
  branch_agnostic: bool = ...,
1026
982
  ) -> Node: ...
1027
983
 
@@ -1036,10 +992,8 @@ class NodeManager:
1036
992
  fields: dict | None = ...,
1037
993
  at: Timestamp | str | None = ...,
1038
994
  branch: Branch | str | None = ...,
1039
- include_source: bool = ...,
1040
- include_owner: bool = ...,
995
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
1041
996
  prefetch_relationships: bool = ...,
1042
- account=...,
1043
997
  branch_agnostic: bool = ...,
1044
998
  ) -> Node | None: ...
1045
999
 
@@ -1054,10 +1008,8 @@ class NodeManager:
1054
1008
  fields: dict | None = ...,
1055
1009
  at: Timestamp | str | None = ...,
1056
1010
  branch: Branch | str | None = ...,
1057
- include_source: bool = ...,
1058
- include_owner: bool = ...,
1011
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
1059
1012
  prefetch_relationships: bool = ...,
1060
- account=...,
1061
1013
  branch_agnostic: bool = ...,
1062
1014
  ) -> Node | None: ...
1063
1015
 
@@ -1072,10 +1024,8 @@ class NodeManager:
1072
1024
  fields: dict | None = ...,
1073
1025
  at: Timestamp | str | None = ...,
1074
1026
  branch: Branch | str | None = ...,
1075
- include_source: bool = ...,
1076
- include_owner: bool = ...,
1027
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
1077
1028
  prefetch_relationships: bool = ...,
1078
- account=...,
1079
1029
  branch_agnostic: bool = ...,
1080
1030
  ) -> Node: ...
1081
1031
 
@@ -1090,10 +1040,8 @@ class NodeManager:
1090
1040
  fields: dict | None = ...,
1091
1041
  at: Timestamp | str | None = ...,
1092
1042
  branch: Branch | str | None = ...,
1093
- include_source: bool = ...,
1094
- include_owner: bool = ...,
1043
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
1095
1044
  prefetch_relationships: bool = ...,
1096
- account=...,
1097
1045
  branch_agnostic: bool = ...,
1098
1046
  ) -> Node | None: ...
1099
1047
 
@@ -1108,10 +1056,8 @@ class NodeManager:
1108
1056
  fields: dict | None = ...,
1109
1057
  at: Timestamp | str | None = ...,
1110
1058
  branch: Branch | str | None = ...,
1111
- include_source: bool = ...,
1112
- include_owner: bool = ...,
1059
+ include_metadata: MetadataQueryOptions | MetadataOptions = ...,
1113
1060
  prefetch_relationships: bool = ...,
1114
- account=...,
1115
1061
  branch_agnostic: bool = ...,
1116
1062
  ) -> Node | None: ...
1117
1063
 
@@ -1125,10 +1071,8 @@ class NodeManager:
1125
1071
  fields: dict | None = None,
1126
1072
  at: Timestamp | str | None = None,
1127
1073
  branch: Branch | str | None = None,
1128
- include_source: bool = False,
1129
- include_owner: bool = False,
1074
+ include_metadata: MetadataQueryOptions | MetadataOptions = MetadataOptions.NONE,
1130
1075
  prefetch_relationships: bool = False,
1131
- account=None,
1132
1076
  branch_agnostic: bool = False,
1133
1077
  ) -> Node | SchemaProtocol | None:
1134
1078
  """Return one node based on its ID."""
@@ -1139,9 +1083,7 @@ class NodeManager:
1139
1083
  fields=fields,
1140
1084
  at=at,
1141
1085
  branch=branch,
1142
- include_source=include_source,
1143
- include_owner=include_owner,
1144
- account=account,
1086
+ include_metadata=include_metadata,
1145
1087
  prefetch_relationships=prefetch_relationships,
1146
1088
  db=db,
1147
1089
  branch_agnostic=branch_agnostic,
@@ -1189,10 +1131,8 @@ class NodeManager:
1189
1131
  fields: dict | None = None,
1190
1132
  at: Timestamp | str | None = None,
1191
1133
  branch: Branch | str | None = None,
1192
- include_source: bool = False,
1193
- include_owner: bool = False,
1134
+ include_metadata: MetadataQueryOptions | MetadataOptions = MetadataOptions.NONE,
1194
1135
  prefetch_relationships: bool = False,
1195
- account=None,
1196
1136
  branch_agnostic: bool = False,
1197
1137
  ) -> dict[str, Node]:
1198
1138
  """Return a list of nodes based on their IDs."""
@@ -1200,22 +1140,34 @@ class NodeManager:
1200
1140
  branch = await registry.get_branch(branch=branch, db=db)
1201
1141
  at = Timestamp(at)
1202
1142
 
1143
+ if not ids:
1144
+ return {}
1145
+
1203
1146
  # Query all nodes
1147
+ node_metadata_options = (
1148
+ include_metadata.node_level if isinstance(include_metadata, MetadataQueryOptions) else include_metadata
1149
+ )
1204
1150
  query = await NodeListGetInfoQuery.init(
1205
- db=db, ids=ids, branch=branch, account=account, at=at, branch_agnostic=branch_agnostic
1151
+ db=db,
1152
+ ids=ids,
1153
+ branch=branch,
1154
+ at=at,
1155
+ branch_agnostic=branch_agnostic,
1156
+ include_metadata=node_metadata_options,
1206
1157
  )
1207
1158
  await query.execute(db=db)
1208
1159
  nodes_info_by_id: dict[str, NodeToProcess] = {node.node_uuid: node async for node in query.get_nodes(db=db)}
1209
1160
 
1210
1161
  # Query list of all Attributes
1162
+ attribute_metadata_options = (
1163
+ include_metadata.attribute_level if isinstance(include_metadata, MetadataQueryOptions) else include_metadata
1164
+ )
1211
1165
  query = await NodeListGetAttributeQuery.init(
1212
1166
  db=db,
1213
1167
  ids=list(nodes_info_by_id.keys()),
1214
1168
  fields=fields,
1215
1169
  branch=branch,
1216
- include_source=include_source,
1217
- include_owner=include_owner,
1218
- account=account,
1170
+ include_metadata=attribute_metadata_options,
1219
1171
  at=at,
1220
1172
  branch_agnostic=branch_agnostic,
1221
1173
  )
@@ -1232,7 +1184,6 @@ class NodeManager:
1232
1184
  new_node_data: dict[str, str | AttributeFromDB] = {
1233
1185
  "db_id": node.node_id,
1234
1186
  "id": node_id,
1235
- "updated_at": node.updated_at,
1236
1187
  }
1237
1188
 
1238
1189
  if not node.schema:
@@ -1253,17 +1204,26 @@ class NodeManager:
1253
1204
  node_branch = await registry.get_branch(db=db, branch=node.branch)
1254
1205
  item = await node_class.init(schema=node.schema, branch=node_branch, at=at, db=db)
1255
1206
  await item.load(**new_node_data, db=db)
1207
+ item._set_created_at(node.created_at)
1208
+ item._set_created_by(node.created_by)
1209
+ item._set_updated_at(node.updated_at)
1210
+ item._set_updated_by(node.updated_by)
1256
1211
 
1257
1212
  nodes[node_id] = item
1258
1213
 
1214
+ relationships_metadata_options = (
1215
+ include_metadata.relationship_level
1216
+ if isinstance(include_metadata, MetadataQueryOptions)
1217
+ else include_metadata
1218
+ )
1219
+
1259
1220
  await cls._enrich_node_dicts_with_relationships(
1260
1221
  db=db,
1261
1222
  branch=branch,
1262
1223
  at=at,
1263
1224
  nodes_by_id=nodes,
1264
1225
  branch_agnostic=branch_agnostic,
1265
- include_owner=include_owner,
1266
- include_source=include_source,
1226
+ include_metadata=relationships_metadata_options,
1267
1227
  prefetch_relationships=prefetch_relationships,
1268
1228
  fields=fields,
1269
1229
  )
@@ -1278,8 +1238,7 @@ class NodeManager:
1278
1238
  at: Timestamp,
1279
1239
  nodes_by_id: dict[str, Node],
1280
1240
  branch_agnostic: bool,
1281
- include_owner: bool,
1282
- include_source: bool,
1241
+ include_metadata: MetadataOptions,
1283
1242
  prefetch_relationships: bool,
1284
1243
  fields: dict[str, Any] | None,
1285
1244
  ) -> None:
@@ -1314,6 +1273,7 @@ class NodeManager:
1314
1273
  branch=branch,
1315
1274
  at=at,
1316
1275
  branch_agnostic=branch_agnostic,
1276
+ include_metadata=include_metadata,
1317
1277
  )
1318
1278
  await query.execute(db=db)
1319
1279
  grouped_peer_nodes = query.get_peers_group_by_node()
@@ -1331,8 +1291,7 @@ class NodeManager:
1331
1291
  branch=branch,
1332
1292
  at=at,
1333
1293
  db=db,
1334
- include_owner=include_owner,
1335
- include_source=include_source,
1294
+ include_metadata=include_metadata,
1336
1295
  )
1337
1296
 
1338
1297
  for node in nodes_by_id.values():
@@ -1361,7 +1320,9 @@ class NodeManager:
1361
1320
  node_schema = node.get_schema()
1362
1321
  for rel_schema in node_schema.relationships:
1363
1322
  peer_ids = grouped_peer_nodes.get_peer_ids(
1364
- node_id=node.get_id(), rel_name=rel_schema.get_identifier(), direction=rel_schema.direction
1323
+ node_id=node.get_id(),
1324
+ rel_name=rel_schema.get_identifier(),
1325
+ direction=rel_schema.direction,
1365
1326
  )
1366
1327
  if not peer_ids:
1367
1328
  continue
@@ -1386,8 +1347,27 @@ class NodeManager:
1386
1347
  if rel_schema.cardinality is RelationshipCardinality.ONE and len(rel_peers) > 1:
1387
1348
  raise ValueError("At most, one relationship expected")
1388
1349
 
1350
+ rel_peers_with_metadata: list[PeerWithRelationshipMetadata] = []
1351
+ for peer in rel_peers:
1352
+ peer_id = peer.get_id() if isinstance(peer, Node) else peer
1353
+ metadata_map = grouped_peer_nodes.get_metadata_map(
1354
+ node_id=node.get_id(),
1355
+ rel_name=rel_schema.get_identifier(),
1356
+ direction=rel_schema.direction,
1357
+ peer_id=peer_id,
1358
+ )
1359
+ peer_with_metadata = PeerWithRelationshipMetadata(peer=peer)
1360
+ if not metadata_map:
1361
+ rel_peers_with_metadata.append(peer_with_metadata)
1362
+ continue
1363
+ peer_with_metadata.created_at = metadata_map.get(MetadataOptions.CREATED_AT)
1364
+ peer_with_metadata.created_by = metadata_map.get(MetadataOptions.CREATED_BY)
1365
+ peer_with_metadata.updated_at = metadata_map.get(MetadataOptions.UPDATED_AT)
1366
+ peer_with_metadata.updated_by = metadata_map.get(MetadataOptions.UPDATED_BY)
1367
+ rel_peers_with_metadata.append(peer_with_metadata)
1368
+
1389
1369
  rel_manager.has_fetched_relationships = True
1390
- await rel_manager.update(db=db, data=rel_peers)
1370
+ await rel_manager.update(db=db, data=rel_peers_with_metadata)
1391
1371
 
1392
1372
  @classmethod
1393
1373
  async def delete(
@@ -1397,6 +1377,7 @@ class NodeManager:
1397
1377
  branch: Branch | str | None = None,
1398
1378
  at: Timestamp | None = None,
1399
1379
  cascade_delete: bool = True,
1380
+ user_id: str = SYSTEM_USER_ID,
1400
1381
  ) -> list[Node]:
1401
1382
  """Returns list of deleted nodes because of cascading deletes"""
1402
1383
  branch = await registry.get_branch(branch=branch, db=db)
@@ -1411,7 +1392,7 @@ class NodeManager:
1411
1392
  nodes_to_delete += list(node_map.values())
1412
1393
 
1413
1394
  for node in nodes_to_delete:
1414
- await node.delete(db=db, at=at)
1395
+ await node.delete(db=db, at=at, user_id=user_id)
1415
1396
 
1416
1397
  return nodes_to_delete
1417
1398