@burdenoff/be-sdk 2026.510.79

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 (220) hide show
  1. package/README.md +173 -0
  2. package/configs/eslint/index.js +492 -0
  3. package/configs/tsconfig/tsconfig.json +53 -0
  4. package/dist/EventQueueFactory-6NMSGECR.js +8 -0
  5. package/dist/EventQueueFactory-6NMSGECR.js.map +1 -0
  6. package/dist/auth/index.d.ts +66 -0
  7. package/dist/auth/index.js +8 -0
  8. package/dist/auth/index.js.map +1 -0
  9. package/dist/cache/index.d.ts +2 -0
  10. package/dist/cache/index.js +6 -0
  11. package/dist/cache/index.js.map +1 -0
  12. package/dist/captcha/index.d.ts +1 -0
  13. package/dist/captcha/index.js +4 -0
  14. package/dist/captcha/index.js.map +1 -0
  15. package/dist/chunk-2HANKZZM.js +245 -0
  16. package/dist/chunk-2HANKZZM.js.map +1 -0
  17. package/dist/chunk-2SD5L2F2.js +816 -0
  18. package/dist/chunk-2SD5L2F2.js.map +1 -0
  19. package/dist/chunk-3O2RQOPV.js +1068 -0
  20. package/dist/chunk-3O2RQOPV.js.map +1 -0
  21. package/dist/chunk-4B43DZIS.js +560 -0
  22. package/dist/chunk-4B43DZIS.js.map +1 -0
  23. package/dist/chunk-4XAEES25.js +2444 -0
  24. package/dist/chunk-4XAEES25.js.map +1 -0
  25. package/dist/chunk-4XGGWW36.js +1405 -0
  26. package/dist/chunk-4XGGWW36.js.map +1 -0
  27. package/dist/chunk-5LXDPGDH.js +245 -0
  28. package/dist/chunk-5LXDPGDH.js.map +1 -0
  29. package/dist/chunk-AI7L22ZJ.js +472 -0
  30. package/dist/chunk-AI7L22ZJ.js.map +1 -0
  31. package/dist/chunk-CBZNP6RF.js +286 -0
  32. package/dist/chunk-CBZNP6RF.js.map +1 -0
  33. package/dist/chunk-ELLX3K54.js +613 -0
  34. package/dist/chunk-ELLX3K54.js.map +1 -0
  35. package/dist/chunk-F5XEAGHQ.js +1875 -0
  36. package/dist/chunk-F5XEAGHQ.js.map +1 -0
  37. package/dist/chunk-FNZEQOJY.js +628 -0
  38. package/dist/chunk-FNZEQOJY.js.map +1 -0
  39. package/dist/chunk-GTEMQXCA.js +516 -0
  40. package/dist/chunk-GTEMQXCA.js.map +1 -0
  41. package/dist/chunk-HIWTWIGQ.js +226 -0
  42. package/dist/chunk-HIWTWIGQ.js.map +1 -0
  43. package/dist/chunk-IYE2NTRX.js +764 -0
  44. package/dist/chunk-IYE2NTRX.js.map +1 -0
  45. package/dist/chunk-J26YGR2U.js +1484 -0
  46. package/dist/chunk-J26YGR2U.js.map +1 -0
  47. package/dist/chunk-JG2FTZPI.js +509 -0
  48. package/dist/chunk-JG2FTZPI.js.map +1 -0
  49. package/dist/chunk-JVBTNSPG.js +1551 -0
  50. package/dist/chunk-JVBTNSPG.js.map +1 -0
  51. package/dist/chunk-L7ZMN2FJ.js +12 -0
  52. package/dist/chunk-L7ZMN2FJ.js.map +1 -0
  53. package/dist/chunk-M5IMU3US.js +473 -0
  54. package/dist/chunk-M5IMU3US.js.map +1 -0
  55. package/dist/chunk-MLW2HPS5.js +1267 -0
  56. package/dist/chunk-MLW2HPS5.js.map +1 -0
  57. package/dist/chunk-MNCGUYLJ.js +269 -0
  58. package/dist/chunk-MNCGUYLJ.js.map +1 -0
  59. package/dist/chunk-MOCUBSTW.js +373 -0
  60. package/dist/chunk-MOCUBSTW.js.map +1 -0
  61. package/dist/chunk-NGMEI42S.js +103 -0
  62. package/dist/chunk-NGMEI42S.js.map +1 -0
  63. package/dist/chunk-NUB5GQTU.js +270 -0
  64. package/dist/chunk-NUB5GQTU.js.map +1 -0
  65. package/dist/chunk-OVSYMNCI.js +145 -0
  66. package/dist/chunk-OVSYMNCI.js.map +1 -0
  67. package/dist/chunk-QLVKMWFA.js +94 -0
  68. package/dist/chunk-QLVKMWFA.js.map +1 -0
  69. package/dist/chunk-SAG6ZYWQ.js +89 -0
  70. package/dist/chunk-SAG6ZYWQ.js.map +1 -0
  71. package/dist/chunk-SAK2JCA7.js +198 -0
  72. package/dist/chunk-SAK2JCA7.js.map +1 -0
  73. package/dist/chunk-SBS4S2PJ.js +100 -0
  74. package/dist/chunk-SBS4S2PJ.js.map +1 -0
  75. package/dist/chunk-SNEOLWXT.js +148 -0
  76. package/dist/chunk-SNEOLWXT.js.map +1 -0
  77. package/dist/chunk-TKBD2ONF.js +564 -0
  78. package/dist/chunk-TKBD2ONF.js.map +1 -0
  79. package/dist/chunk-UBXFIIAW.js +127 -0
  80. package/dist/chunk-UBXFIIAW.js.map +1 -0
  81. package/dist/chunk-VI4VSNTI.js +57 -0
  82. package/dist/chunk-VI4VSNTI.js.map +1 -0
  83. package/dist/chunk-VWCN5PMD.js +268 -0
  84. package/dist/chunk-VWCN5PMD.js.map +1 -0
  85. package/dist/chunk-XC2YD6CF.js +913 -0
  86. package/dist/chunk-XC2YD6CF.js.map +1 -0
  87. package/dist/chunk-XE4OXN2W.js +10 -0
  88. package/dist/chunk-XE4OXN2W.js.map +1 -0
  89. package/dist/chunk-YMZEUTD2.js +110 -0
  90. package/dist/chunk-YMZEUTD2.js.map +1 -0
  91. package/dist/chunk-Z4IRLBWO.js +758 -0
  92. package/dist/chunk-Z4IRLBWO.js.map +1 -0
  93. package/dist/client/internal-client.d.ts +7 -0
  94. package/dist/client/internal-client.js +5 -0
  95. package/dist/client/internal-client.js.map +1 -0
  96. package/dist/client-CSjIrYKS.d.ts +77 -0
  97. package/dist/config-UKE2E3BW.js +4 -0
  98. package/dist/config-UKE2E3BW.js.map +1 -0
  99. package/dist/crypto/index.d.ts +1 -0
  100. package/dist/crypto/index.js +4 -0
  101. package/dist/crypto/index.js.map +1 -0
  102. package/dist/database/index.d.ts +117 -0
  103. package/dist/database/index.js +7 -0
  104. package/dist/database/index.js.map +1 -0
  105. package/dist/dataloader/index.d.ts +1 -0
  106. package/dist/dataloader/index.js +4 -0
  107. package/dist/dataloader/index.js.map +1 -0
  108. package/dist/esm-K6H7EIWK.js +1450 -0
  109. package/dist/esm-K6H7EIWK.js.map +1 -0
  110. package/dist/event-queue/index.d.ts +6 -0
  111. package/dist/event-queue/index.js +10 -0
  112. package/dist/event-queue/index.js.map +1 -0
  113. package/dist/export/index.d.ts +2 -0
  114. package/dist/export/index.js +9 -0
  115. package/dist/export/index.js.map +1 -0
  116. package/dist/feature-flags/index.d.ts +1 -0
  117. package/dist/feature-flags/index.js +4 -0
  118. package/dist/feature-flags/index.js.map +1 -0
  119. package/dist/gateway/index.d.ts +4 -0
  120. package/dist/gateway/index.js +8 -0
  121. package/dist/gateway/index.js.map +1 -0
  122. package/dist/gateway/security/index.d.ts +2 -0
  123. package/dist/gateway/security/index.js +5 -0
  124. package/dist/gateway/security/index.js.map +1 -0
  125. package/dist/graph/index.d.ts +9 -0
  126. package/dist/graph/index.js +13 -0
  127. package/dist/graph/index.js.map +1 -0
  128. package/dist/graph-emitter-Bk0FqD53.d.ts +47 -0
  129. package/dist/graphql/index.d.ts +2 -0
  130. package/dist/graphql/index.js +7 -0
  131. package/dist/graphql/index.js.map +1 -0
  132. package/dist/graphql/services/index.d.ts +24 -0
  133. package/dist/graphql/services/index.js +5 -0
  134. package/dist/graphql/services/index.js.map +1 -0
  135. package/dist/graphql-BAVrUgBF.d.ts +22 -0
  136. package/dist/i18n/index.d.ts +2 -0
  137. package/dist/i18n/index.js +5 -0
  138. package/dist/i18n/index.js.map +1 -0
  139. package/dist/i18n-DA6IPnYy.d.ts +101 -0
  140. package/dist/index-4gKQKZ2B.d.ts +71 -0
  141. package/dist/index-B18rrFru.d.ts +42 -0
  142. package/dist/index-B70b5mYS.d.ts +33 -0
  143. package/dist/index-BMq3lFjj.d.ts +247 -0
  144. package/dist/index-BODgvRtL.d.ts +316 -0
  145. package/dist/index-BS2idbnr.d.ts +874 -0
  146. package/dist/index-BV3G48cH.d.ts +124 -0
  147. package/dist/index-CHbVw5M7.d.ts +73 -0
  148. package/dist/index-Cq_xNjcv.d.ts +602 -0
  149. package/dist/index-CrQgidpx.d.ts +77 -0
  150. package/dist/index-CyVEg86m.d.ts +309 -0
  151. package/dist/index-DOcBnmMe.d.ts +166 -0
  152. package/dist/index-DSOpj8DI.d.ts +17 -0
  153. package/dist/index-DW9q22GH.d.ts +75 -0
  154. package/dist/index-DlFDFyWD.d.ts +55 -0
  155. package/dist/index-DoK0bjhH.d.ts +607 -0
  156. package/dist/index-Dtf6FBaD.d.ts +199 -0
  157. package/dist/index-KVWGHMbS.d.ts +415 -0
  158. package/dist/index-PaojfSdd.d.ts +71 -0
  159. package/dist/index-RU_M5c74.d.ts +163 -0
  160. package/dist/index-UhkH2eaB.d.ts +192 -0
  161. package/dist/index-e_18DzAg.d.ts +18 -0
  162. package/dist/index-jOuh_TKn.d.ts +59 -0
  163. package/dist/index.d.ts +584 -0
  164. package/dist/index.js +2626 -0
  165. package/dist/index.js.map +1 -0
  166. package/dist/init/index.d.ts +2 -0
  167. package/dist/init/index.js +12 -0
  168. package/dist/init/index.js.map +1 -0
  169. package/dist/instrumentation/index.d.ts +3 -0
  170. package/dist/instrumentation/index.js +5 -0
  171. package/dist/instrumentation/index.js.map +1 -0
  172. package/dist/layer/index.d.ts +2 -0
  173. package/dist/layer/index.js +6 -0
  174. package/dist/layer/index.js.map +1 -0
  175. package/dist/layer-DDip18KY.d.ts +67 -0
  176. package/dist/logger/index.d.ts +2 -0
  177. package/dist/logger/index.js +4 -0
  178. package/dist/logger/index.js.map +1 -0
  179. package/dist/middleware/index.d.ts +3 -0
  180. package/dist/middleware/index.js +5 -0
  181. package/dist/middleware/index.js.map +1 -0
  182. package/dist/notifications/index.d.ts +4 -0
  183. package/dist/notifications/index.js +7 -0
  184. package/dist/notifications/index.js.map +1 -0
  185. package/dist/observability/index.d.ts +3 -0
  186. package/dist/observability/index.js +5 -0
  187. package/dist/observability/index.js.map +1 -0
  188. package/dist/pino-logger-RYLGXPHZ.js +5 -0
  189. package/dist/pino-logger-RYLGXPHZ.js.map +1 -0
  190. package/dist/prisma/generator/index.d.ts +1 -0
  191. package/dist/prisma/generator/index.js +228 -0
  192. package/dist/prisma/generator/index.js.map +1 -0
  193. package/dist/prisma/index.d.ts +5 -0
  194. package/dist/prisma/index.js +12 -0
  195. package/dist/prisma/index.js.map +1 -0
  196. package/dist/prisma-extension-krXnYnrN.d.ts +30 -0
  197. package/dist/rbac/index.d.ts +116 -0
  198. package/dist/rbac/index.js +7 -0
  199. package/dist/rbac/index.js.map +1 -0
  200. package/dist/sdk-THO3IWEE.js +136 -0
  201. package/dist/sdk-THO3IWEE.js.map +1 -0
  202. package/dist/server/index.d.ts +359 -0
  203. package/dist/server/index.js +884 -0
  204. package/dist/server/index.js.map +1 -0
  205. package/dist/telemetry/index.d.ts +83 -0
  206. package/dist/telemetry/index.js +209 -0
  207. package/dist/telemetry/index.js.map +1 -0
  208. package/dist/temporal/index.d.ts +148 -0
  209. package/dist/temporal/index.js +6 -0
  210. package/dist/temporal/index.js.map +1 -0
  211. package/dist/tracker/index.d.ts +5 -0
  212. package/dist/tracker/index.js +9 -0
  213. package/dist/tracker/index.js.map +1 -0
  214. package/dist/types-Bo2wkjSP.d.ts +35 -0
  215. package/dist/utils/index.d.ts +1 -0
  216. package/dist/utils/index.js +4 -0
  217. package/dist/utils/index.js.map +1 -0
  218. package/dist/workspace-guard-LHBNK4TG.js +5 -0
  219. package/dist/workspace-guard-LHBNK4TG.js.map +1 -0
  220. package/package.json +241 -0
@@ -0,0 +1,1875 @@
1
+ import { shouldSyncRelationship, shouldSyncEntity, parseRelationship, getCollectionForEntity, extractMinimalFields, extractEntityTitle, createRelationshipEvent, createEntityEvent, addGraphExtension, GraphRegistry } from './chunk-TKBD2ONF.js';
2
+ import { getGraphEventEmitter, NatsGraphEventEmitter } from './chunk-ELLX3K54.js';
3
+ import { ValidationError } from './chunk-SAG6ZYWQ.js';
4
+ import { logger } from './chunk-CBZNP6RF.js';
5
+ import { __export, __name } from './chunk-XE4OXN2W.js';
6
+
7
+ // src/graph/index.ts
8
+ var graph_exports = {};
9
+ __export(graph_exports, {
10
+ AUDIT_FIELDS: () => AUDIT_FIELDS,
11
+ GraphEventsPublisher: () => GraphEventsPublisher,
12
+ GraphExportService: () => GraphExportService,
13
+ GraphModule: () => GraphModule,
14
+ GraphRegistry: () => GraphRegistry,
15
+ SOFT_DELETE_FIELDS: () => SOFT_DELETE_FIELDS,
16
+ STANDARD_FIELDS: () => STANDARD_FIELDS,
17
+ TENANT_FIELDS: () => TENANT_FIELDS,
18
+ addGraphExtension: () => addGraphExtension,
19
+ createEntityEvent: () => createEntityEvent,
20
+ createGraphEventsHelper: () => createGraphEventsHelper,
21
+ createGraphExportService: () => createGraphExportService,
22
+ createPrismaGraphIntegration: () => createPrismaGraphIntegration,
23
+ createRelationshipEvent: () => createRelationshipEvent,
24
+ createRelationshipFromEntity: () => createRelationshipFromEntity,
25
+ defineEntity: () => defineEntity,
26
+ defineGraphConfig: () => defineGraphConfig,
27
+ defineModuleGraph: () => defineModuleGraph,
28
+ defineRelationship: () => defineRelationship,
29
+ extractEntityTitle: () => extractEntityTitle,
30
+ extractMinimalFields: () => extractMinimalFields,
31
+ getCollectionForEntity: () => getCollectionForEntity,
32
+ getGraphEventsPublisher: () => getGraphEventsPublisher,
33
+ getGraphStats: () => getGraphStats,
34
+ initializeGraph: () => initializeGraph,
35
+ isGraphInitialized: () => isGraphInitialized,
36
+ parseRelationship: () => parseRelationship,
37
+ shouldSyncEntity: () => shouldSyncEntity,
38
+ shouldSyncRelationship: () => shouldSyncRelationship
39
+ });
40
+
41
+ // src/graph/utils/prisma-helpers.ts
42
+ function createPrismaGraphIntegration(options) {
43
+ const { serviceName, graphConfig, productName = "workspaces", validateRuntime = process.env.NODE_ENV !== "production", autoInit = true, createPrismaClient } = options;
44
+ const state = {
45
+ graphEmitter: null,
46
+ extendedPrismaClient: null,
47
+ emitterInitialized: false,
48
+ initializationPromise: null
49
+ };
50
+ async function initializeGraphEmitter() {
51
+ if (state.initializationPromise) {
52
+ return state.initializationPromise;
53
+ }
54
+ if (state.emitterInitialized) {
55
+ return;
56
+ }
57
+ state.initializationPromise = (async () => {
58
+ if (!process.env["GRAPH_EVENTS_ENABLED"] || process.env["GRAPH_EVENTS_ENABLED"] !== "true") {
59
+ logger.info(`[${serviceName}] Graph events disabled`);
60
+ state.emitterInitialized = true;
61
+ return;
62
+ }
63
+ try {
64
+ if (!process.env["NATS_SERVERS"] && process.env["NATS_URL"]) {
65
+ process.env["NATS_SERVERS"] = process.env["NATS_URL"];
66
+ }
67
+ state.graphEmitter = new NatsGraphEventEmitter();
68
+ logger.info(`[${serviceName}] Graph event emitter initialized`);
69
+ state.emitterInitialized = true;
70
+ const basePrisma = createPrismaClient();
71
+ state.extendedPrismaClient = initializeGraph(basePrisma, graphConfig, {
72
+ productName,
73
+ eventEmitter: state.graphEmitter,
74
+ enabled: true,
75
+ validateRuntime
76
+ });
77
+ logger.info(`[${serviceName}] Graph integration initialized successfully`);
78
+ } catch (error) {
79
+ logger.error(`[${serviceName}] Failed to initialize graph integration:`, error);
80
+ state.graphEmitter = null;
81
+ state.extendedPrismaClient = null;
82
+ state.emitterInitialized = true;
83
+ }
84
+ })();
85
+ return state.initializationPromise;
86
+ }
87
+ __name(initializeGraphEmitter, "initializeGraphEmitter");
88
+ function db() {
89
+ if (autoInit && !state.emitterInitialized && !state.initializationPromise) {
90
+ logger.warn(`[${serviceName}] Graph emitter not initialized before first database access. Auto-initializing now. Consider calling 'await initializeGraphEmitter()' explicitly during server startup for better control.`);
91
+ void initializeGraphEmitter();
92
+ }
93
+ if (!process.env["GRAPH_EVENTS_ENABLED"] || process.env["GRAPH_EVENTS_ENABLED"] !== "true" || !state.extendedPrismaClient) {
94
+ const baseClient = createPrismaClient();
95
+ return {
96
+ client: baseClient
97
+ };
98
+ }
99
+ return {
100
+ client: state.extendedPrismaClient
101
+ };
102
+ }
103
+ __name(db, "db");
104
+ const prisma = new Proxy({}, {
105
+ get(_, prop) {
106
+ const { client } = db();
107
+ const value = client[prop];
108
+ if (typeof value === "function") {
109
+ return value.bind(client);
110
+ }
111
+ return value;
112
+ }
113
+ });
114
+ async function cleanup() {
115
+ if (state.graphEmitter) {
116
+ await state.graphEmitter.disconnect();
117
+ logger.info(`[${serviceName}] Graph event emitter disconnected`);
118
+ }
119
+ if (state.extendedPrismaClient) {
120
+ await state.extendedPrismaClient.$disconnect();
121
+ state.extendedPrismaClient = null;
122
+ logger.info(`[${serviceName}] Prisma client disconnected`);
123
+ }
124
+ state.emitterInitialized = false;
125
+ }
126
+ __name(cleanup, "cleanup");
127
+ return {
128
+ /**
129
+ * Initialize graph event emitter
130
+ *
131
+ * With autoInit=true (default), this is called automatically on first database access.
132
+ * You can still call it manually for explicit initialization timing.
133
+ *
134
+ * With autoInit=false, you must call this during application startup.
135
+ */
136
+ initializeGraphEmitter,
137
+ /**
138
+ * Get Prisma client with graph integration
139
+ * Returns { client: PrismaClient }
140
+ *
141
+ * If autoInit is enabled, triggers initialization on first call.
142
+ */
143
+ db,
144
+ /**
145
+ * Direct Prisma client accessor (Proxy-based)
146
+ * Use this for most database operations
147
+ *
148
+ * If autoInit is enabled, initialization happens automatically.
149
+ */
150
+ prisma,
151
+ /**
152
+ * Cleanup function for graceful shutdown
153
+ */
154
+ cleanup,
155
+ /**
156
+ * Get the raw graph emitter instance (for advanced use cases)
157
+ */
158
+ getGraphEmitter: /* @__PURE__ */ __name(() => state.graphEmitter, "getGraphEmitter"),
159
+ /**
160
+ * Check if emitter is initialized
161
+ */
162
+ isInitialized: /* @__PURE__ */ __name(() => state.emitterInitialized, "isInitialized")
163
+ };
164
+ }
165
+ __name(createPrismaGraphIntegration, "createPrismaGraphIntegration");
166
+
167
+ // src/graph/events-helper.ts
168
+ var GraphEventsPublisher = class _GraphEventsPublisher {
169
+ static {
170
+ __name(this, "GraphEventsPublisher");
171
+ }
172
+ static instance = null;
173
+ productName;
174
+ initialized = false;
175
+ emitter = null;
176
+ constructor(productName = "unknown") {
177
+ this.productName = productName;
178
+ }
179
+ /**
180
+ * Get singleton instance
181
+ */
182
+ static getInstance(productName) {
183
+ if (!_GraphEventsPublisher.instance) {
184
+ _GraphEventsPublisher.instance = new _GraphEventsPublisher(productName);
185
+ }
186
+ return _GraphEventsPublisher.instance;
187
+ }
188
+ /**
189
+ * Set the product name (useful when using singleton)
190
+ */
191
+ setProductName(name) {
192
+ this.productName = name;
193
+ }
194
+ /**
195
+ * Initialize the publisher
196
+ */
197
+ async initialize() {
198
+ if (this.initialized) {
199
+ return;
200
+ }
201
+ try {
202
+ this.emitter = getGraphEventEmitter();
203
+ logger.info("[GraphEventsPublisher] Graph event emitter initialized");
204
+ this.initialized = true;
205
+ const natsUrl = process.env["NATS_URL"] || process.env["NATS_SERVERS"];
206
+ if (natsUrl) {
207
+ logger.info(`[GraphEventsPublisher] NATS configured: ${natsUrl}`);
208
+ } else {
209
+ logger.warn("[GraphEventsPublisher] NATS not configured, using in-memory fallback");
210
+ }
211
+ } catch (error) {
212
+ logger.error("[GraphEventsPublisher] Failed to initialize:", error);
213
+ }
214
+ }
215
+ /**
216
+ * Ensure initialized before publishing
217
+ */
218
+ async ensureInitialized() {
219
+ if (!this.initialized) {
220
+ await this.initialize();
221
+ }
222
+ }
223
+ /**
224
+ * Publish entity created event
225
+ */
226
+ async publishEntityCreated(entity, options) {
227
+ await this.publishEntityEvent("entity.created", entity, options);
228
+ }
229
+ /**
230
+ * Publish entity updated event
231
+ */
232
+ async publishEntityUpdated(entity, options) {
233
+ await this.publishEntityEvent("entity.updated", entity, options);
234
+ }
235
+ /**
236
+ * Publish entity deleted event
237
+ */
238
+ async publishEntityDeleted(entity, options) {
239
+ await this.publishEntityEvent("entity.deleted", entity, options);
240
+ }
241
+ /**
242
+ * Publish relationship created event
243
+ */
244
+ async publishRelationshipCreated(relationship, organizationId, options) {
245
+ await this.publishRelationshipEvent("relationship.created", relationship, organizationId, options);
246
+ }
247
+ /**
248
+ * Publish relationship deleted event
249
+ */
250
+ async publishRelationshipDeleted(relationship, organizationId, options) {
251
+ await this.publishRelationshipEvent("relationship.deleted", relationship, organizationId, options);
252
+ }
253
+ /**
254
+ * Internal method to publish entity events
255
+ */
256
+ async publishEntityEvent(eventType, entity, options) {
257
+ await this.ensureInitialized();
258
+ if (!this.emitter) {
259
+ logger.warn("[GraphEventsPublisher] Emitter not initialized, skipping event");
260
+ return;
261
+ }
262
+ try {
263
+ await this.emitter.publishEntityEvent(eventType, {
264
+ id: entity.id,
265
+ type: entity.type,
266
+ data: entity.data
267
+ }, {
268
+ productName: this.productName,
269
+ organizationId: entity.organizationId || "unknown",
270
+ workspaceId: entity.workspaceId,
271
+ actorId: options?.userId
272
+ });
273
+ logger.debug(`[GraphEventsPublisher] Published ${eventType} for ${entity.type}:${entity.id}`);
274
+ } catch (error) {
275
+ logger.error(`[GraphEventsPublisher] Failed to publish ${eventType} for ${entity.type}:${entity.id}:`, error);
276
+ }
277
+ }
278
+ /**
279
+ * Internal method to publish relationship events
280
+ */
281
+ async publishRelationshipEvent(eventType, relationship, organizationId, options) {
282
+ await this.ensureInitialized();
283
+ if (!this.emitter) {
284
+ logger.warn("[GraphEventsPublisher] Emitter not initialized, skipping event");
285
+ return;
286
+ }
287
+ try {
288
+ await this.emitter.publishEntityEvent(eventType, {
289
+ id: `${relationship.from.id}_${relationship.to.id}`,
290
+ type: relationship.relationType,
291
+ data: {
292
+ from: relationship.from,
293
+ to: relationship.to,
294
+ metadata: relationship.metadata
295
+ }
296
+ }, {
297
+ productName: this.productName,
298
+ organizationId,
299
+ actorId: options?.userId
300
+ });
301
+ logger.debug(`[GraphEventsPublisher] Published ${eventType} for ${relationship.relationType}`);
302
+ } catch (error) {
303
+ logger.error(`[GraphEventsPublisher] Failed to publish ${eventType} for ${relationship.relationType}:`, error);
304
+ }
305
+ }
306
+ /**
307
+ * Shutdown the publisher
308
+ */
309
+ async shutdown() {
310
+ this.initialized = false;
311
+ this.emitter = null;
312
+ logger.info("[GraphEventsPublisher] Shutdown complete");
313
+ }
314
+ /**
315
+ * Reset singleton (for testing)
316
+ */
317
+ static reset() {
318
+ _GraphEventsPublisher.instance = null;
319
+ }
320
+ };
321
+ function getGraphEventsPublisher(productName) {
322
+ return GraphEventsPublisher.getInstance(productName);
323
+ }
324
+ __name(getGraphEventsPublisher, "getGraphEventsPublisher");
325
+ function createGraphEventsHelper(config) {
326
+ const publisher = new GraphEventsPublisher(config.moduleName);
327
+ const helper = {};
328
+ for (const [name, entityConfig] of Object.entries(config.entities)) {
329
+ helper[name] = {
330
+ created: /* @__PURE__ */ __name(async (data, options) => {
331
+ await publisher.publishEntityCreated({
332
+ id: data["id"],
333
+ type: entityConfig.type,
334
+ data,
335
+ organizationId: entityConfig.getOrgId?.(data),
336
+ workspaceId: entityConfig.getWorkspaceId?.(data)
337
+ }, options);
338
+ if (entityConfig.onCreated) {
339
+ await entityConfig.onCreated(data, publisher, options);
340
+ }
341
+ }, "created"),
342
+ updated: /* @__PURE__ */ __name(async (data, options) => {
343
+ await publisher.publishEntityUpdated({
344
+ id: data["id"],
345
+ type: entityConfig.type,
346
+ data,
347
+ organizationId: entityConfig.getOrgId?.(data),
348
+ workspaceId: entityConfig.getWorkspaceId?.(data)
349
+ }, options);
350
+ if (entityConfig.onUpdated) {
351
+ await entityConfig.onUpdated(data, publisher, options);
352
+ }
353
+ }, "updated"),
354
+ deleted: /* @__PURE__ */ __name(async (data, options) => {
355
+ await publisher.publishEntityDeleted({
356
+ id: data["id"],
357
+ type: entityConfig.type,
358
+ data,
359
+ organizationId: entityConfig.getOrgId?.(data),
360
+ workspaceId: entityConfig.getWorkspaceId?.(data)
361
+ }, options);
362
+ if (entityConfig.onDeleted) {
363
+ await entityConfig.onDeleted(data, publisher, options);
364
+ }
365
+ }, "deleted")
366
+ };
367
+ }
368
+ return helper;
369
+ }
370
+ __name(createGraphEventsHelper, "createGraphEventsHelper");
371
+
372
+ // src/graph/export-service.ts
373
+ var GraphExportService = class {
374
+ static {
375
+ __name(this, "GraphExportService");
376
+ }
377
+ moduleName;
378
+ config;
379
+ fetchers;
380
+ relationshipFetchers;
381
+ customTransformer;
382
+ constructor(serviceConfig) {
383
+ this.moduleName = serviceConfig.moduleName;
384
+ this.config = serviceConfig.config;
385
+ this.fetchers = serviceConfig.fetchers;
386
+ this.relationshipFetchers = serviceConfig.relationshipFetchers || {};
387
+ this.customTransformer = serviceConfig.transformEntity;
388
+ }
389
+ /**
390
+ * Get the graph configuration schema
391
+ */
392
+ getSchema() {
393
+ const entities = {};
394
+ const relationships = {};
395
+ for (const [entityType, config] of Object.entries(this.config.entities)) {
396
+ entities[entityType] = {
397
+ fields: Array.isArray(config.fields) ? config.fields : [
398
+ "id",
399
+ "createdAt",
400
+ "updatedAt"
401
+ ],
402
+ collection: config.collection || "product_entities"
403
+ };
404
+ }
405
+ if (this.config.relationships) {
406
+ for (const [relType, config] of Object.entries(this.config.relationships)) {
407
+ relationships[relType] = {
408
+ from: config.from,
409
+ fromType: config.from,
410
+ to: config.to,
411
+ toType: config.to,
412
+ edgeType: config.label || "relates_to"
413
+ };
414
+ }
415
+ }
416
+ return {
417
+ moduleName: this.config.moduleName,
418
+ entities,
419
+ relationships
420
+ };
421
+ }
422
+ /**
423
+ * Export all entities for a given organization/workspace
424
+ */
425
+ async exportEntities(organizationId, workspaceId, entityTypes) {
426
+ const result = {};
427
+ const typesToExport = entityTypes || Object.keys(this.config.entities);
428
+ for (const entityType of typesToExport) {
429
+ if (!this.config.entities[entityType]) {
430
+ continue;
431
+ }
432
+ const fetcher = this.fetchers[entityType];
433
+ if (!fetcher) {
434
+ logger.warn(`[GraphExportService] No fetcher for ${entityType}`);
435
+ result[entityType] = [];
436
+ continue;
437
+ }
438
+ try {
439
+ const entities = await fetcher(organizationId, workspaceId);
440
+ result[entityType] = entities.map((item) => this.transformEntity(entityType, item));
441
+ } catch (error) {
442
+ logger.error(`[GraphExportService] Error fetching ${entityType}:`, error);
443
+ result[entityType] = [];
444
+ }
445
+ }
446
+ return result;
447
+ }
448
+ /**
449
+ * Export all relationships for a given organization/workspace
450
+ */
451
+ async exportRelationships(organizationId, workspaceId) {
452
+ const relationships = [];
453
+ for (const [name, fetcher] of Object.entries(this.relationshipFetchers)) {
454
+ try {
455
+ const rels = await fetcher(organizationId, workspaceId);
456
+ relationships.push(...rels);
457
+ } catch (error) {
458
+ logger.error(`[GraphExportService] Error fetching relationships ${name}:`, error);
459
+ }
460
+ }
461
+ return relationships;
462
+ }
463
+ /**
464
+ * Export complete graph data (schema + entities + relationships)
465
+ */
466
+ async exportAll(organizationId, workspaceId) {
467
+ const schema = this.getSchema();
468
+ const entities = await this.exportEntities(organizationId, workspaceId);
469
+ const relationships = await this.exportRelationships(organizationId, workspaceId);
470
+ const entityCounts = {};
471
+ let totalEntities = 0;
472
+ for (const [type, items] of Object.entries(entities)) {
473
+ entityCounts[type] = items.length;
474
+ totalEntities += items.length;
475
+ }
476
+ return {
477
+ moduleName: this.config.moduleName,
478
+ productSource: this.moduleName,
479
+ exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
480
+ schema: {
481
+ entities: schema.entities,
482
+ relationships: schema.relationships
483
+ },
484
+ data: {
485
+ entities,
486
+ relationships
487
+ },
488
+ stats: {
489
+ totalEntities,
490
+ totalRelationships: relationships.length,
491
+ entityCounts
492
+ }
493
+ };
494
+ }
495
+ /**
496
+ * Transform a database entity to graph export format
497
+ */
498
+ transformEntity(type, item) {
499
+ if (this.customTransformer) {
500
+ return this.customTransformer(type, item);
501
+ }
502
+ const { id, createdAt, updatedAt, workspaceId, tenantId, ...data } = item;
503
+ return {
504
+ id,
505
+ type,
506
+ data,
507
+ organizationId: tenantId,
508
+ workspaceId,
509
+ createdAt: createdAt instanceof Date ? createdAt.toISOString() : String(createdAt),
510
+ updatedAt: updatedAt instanceof Date ? updatedAt.toISOString() : String(updatedAt)
511
+ };
512
+ }
513
+ };
514
+ function createGraphExportService(config) {
515
+ return new GraphExportService(config);
516
+ }
517
+ __name(createGraphExportService, "createGraphExportService");
518
+ function createRelationshipFromEntity(entity, relationConfig, relationType) {
519
+ const fromId = entity[relationConfig.from];
520
+ const toId = entity[relationConfig.to];
521
+ if (!fromId || !toId) {
522
+ return null;
523
+ }
524
+ const metadata = relationConfig.extractMetadata ? relationConfig.extractMetadata(entity) : {};
525
+ return {
526
+ id: `${relationType}_${entity["id"] || fromId}_${toId}`,
527
+ type: relationType,
528
+ fromId,
529
+ fromType: relationConfig.from || "Entity",
530
+ toId,
531
+ toType: relationConfig.to || "Entity",
532
+ metadata,
533
+ createdAt: entity["createdAt"] instanceof Date ? entity["createdAt"].toISOString() : String(entity["createdAt"] || (/* @__PURE__ */ new Date()).toISOString()),
534
+ updatedAt: entity["updatedAt"] instanceof Date ? entity["updatedAt"].toISOString() : String(entity["updatedAt"] || (/* @__PURE__ */ new Date()).toISOString())
535
+ };
536
+ }
537
+ __name(createRelationshipFromEntity, "createRelationshipFromEntity");
538
+
539
+ // src/graph/module-graph.ts
540
+ var GraphEventsPublisherInternal = class GraphEventsPublisherInternal2 {
541
+ static {
542
+ __name(this, "GraphEventsPublisherInternal");
543
+ }
544
+ productName;
545
+ initialized = false;
546
+ emitter = null;
547
+ constructor(productName) {
548
+ this.productName = productName;
549
+ }
550
+ async initialize() {
551
+ if (this.initialized) return;
552
+ try {
553
+ this.emitter = getGraphEventEmitter();
554
+ logger.info(`[ModuleGraph:${this.productName}] Graph event emitter initialized`);
555
+ this.initialized = true;
556
+ const natsUrl = process.env["NATS_URL"] || process.env["NATS_SERVERS"];
557
+ if (natsUrl) {
558
+ logger.info(`[ModuleGraph:${this.productName}] NATS configured: ${natsUrl}`);
559
+ } else {
560
+ logger.warn(`[ModuleGraph:${this.productName}] NATS not configured, using in-memory fallback`);
561
+ }
562
+ } catch (error) {
563
+ logger.error(`[ModuleGraph:${this.productName}] Failed to initialize:`, error);
564
+ }
565
+ }
566
+ async ensureInitialized() {
567
+ if (!this.initialized) {
568
+ await this.initialize();
569
+ }
570
+ }
571
+ async publishEntityCreated(entity, options, rbac) {
572
+ await this.publishEntityEvent("entity.created", entity, options, rbac);
573
+ }
574
+ async publishEntityUpdated(entity, options, rbac) {
575
+ await this.publishEntityEvent("entity.updated", entity, options, rbac);
576
+ }
577
+ async publishEntityDeleted(entity, options, rbac) {
578
+ await this.publishEntityEvent("entity.deleted", entity, options, rbac);
579
+ }
580
+ async publishRelationshipCreated(relationship, organizationId, options) {
581
+ await this.publishRelationshipEvent("relationship.created", relationship, organizationId, options);
582
+ }
583
+ async publishRelationshipDeleted(relationship, organizationId, options) {
584
+ await this.publishRelationshipEvent("relationship.deleted", relationship, organizationId, options);
585
+ }
586
+ async publishEntityEvent(eventType, entity, options, rbac) {
587
+ await this.ensureInitialized();
588
+ if (!this.emitter) {
589
+ logger.warn(`[ModuleGraph:${this.productName}] Emitter not initialized, skipping event`);
590
+ return;
591
+ }
592
+ try {
593
+ await this.emitter.publishEntityEvent(eventType, {
594
+ id: entity.id,
595
+ type: entity.type,
596
+ data: entity.data
597
+ }, {
598
+ productName: this.productName,
599
+ organizationId: entity.organizationId || "unknown",
600
+ workspaceId: entity.workspaceId,
601
+ actorId: options?.actorId
602
+ }, rbac);
603
+ logger.debug(`[ModuleGraph:${this.productName}] Published ${eventType} for ${entity.type}:${entity.id}`, {
604
+ hasRbac: !!rbac
605
+ });
606
+ } catch (error) {
607
+ logger.error(`[ModuleGraph:${this.productName}] Failed to publish ${eventType}:`, error);
608
+ }
609
+ }
610
+ async publishRelationshipEvent(eventType, relationship, organizationId, options) {
611
+ await this.ensureInitialized();
612
+ if (!this.emitter) {
613
+ logger.warn(`[ModuleGraph:${this.productName}] Emitter not initialized, skipping event`);
614
+ return;
615
+ }
616
+ try {
617
+ await this.emitter.publishEntityEvent(eventType, {
618
+ id: `${relationship.from.id}_${relationship.to.id}`,
619
+ type: relationship.relationType,
620
+ data: {
621
+ from: relationship.from,
622
+ to: relationship.to,
623
+ metadata: relationship.metadata
624
+ }
625
+ }, {
626
+ productName: this.productName,
627
+ organizationId,
628
+ actorId: options?.actorId
629
+ });
630
+ logger.debug(`[ModuleGraph:${this.productName}] Published ${eventType} for ${relationship.relationType}`);
631
+ } catch (error) {
632
+ logger.error(`[ModuleGraph:${this.productName}] Failed to publish ${eventType}:`, error);
633
+ }
634
+ }
635
+ async shutdown() {
636
+ this.initialized = false;
637
+ this.emitter = null;
638
+ logger.info(`[ModuleGraph:${this.productName}] Shutdown complete`);
639
+ }
640
+ };
641
+ function defineModuleGraph(definition) {
642
+ const { moduleName, productSource, entities, relationships = {} } = definition;
643
+ const publisher = new GraphEventsPublisherInternal(productSource ?? moduleName);
644
+ const events = {};
645
+ for (const [entityName, entityDef] of Object.entries(entities)) {
646
+ const getOrgId = entityDef.getOrgId || (() => void 0);
647
+ const getWorkspaceId = entityDef.getWorkspaceId || (() => void 0);
648
+ const createEventContext = /* @__PURE__ */ __name(() => ({
649
+ publishRelationship: /* @__PURE__ */ __name(async (data, orgId) => {
650
+ await publisher.publishRelationshipCreated(data, orgId || "unknown");
651
+ }, "publishRelationship"),
652
+ deleteRelationship: /* @__PURE__ */ __name(async (data, orgId) => {
653
+ await publisher.publishRelationshipDeleted(data, orgId || "unknown");
654
+ }, "deleteRelationship"),
655
+ getOrgId,
656
+ getWorkspaceId
657
+ }), "createEventContext");
658
+ const buildRbacMetadata = /* @__PURE__ */ __name((data) => {
659
+ if (!entityDef.rbac) return void 0;
660
+ const rbacConfig = entityDef.rbac;
661
+ if (rbacConfig.createResource === false) return void 0;
662
+ const entityId = data["id"];
663
+ const title = data["name"] || data["title"] || data["label"] || entityId;
664
+ return {
665
+ resourceTypeName: rbacConfig.resourceTypeName,
666
+ name: rbacConfig.extractName?.(data) ?? title,
667
+ identifier: rbacConfig.extractIdentifier?.(data) ?? entityId,
668
+ parentResourceIdentifier: rbacConfig.parentResourceField ? data[rbacConfig.parentResourceField] : void 0,
669
+ createResource: rbacConfig.createResource ?? true
670
+ };
671
+ }, "buildRbacMetadata");
672
+ events[entityName] = {
673
+ created: /* @__PURE__ */ __name(async (data, options) => {
674
+ await publisher.publishEntityCreated({
675
+ id: data["id"],
676
+ type: entityDef.type,
677
+ data,
678
+ organizationId: getOrgId(data),
679
+ workspaceId: getWorkspaceId(data)
680
+ }, options, buildRbacMetadata(data));
681
+ if (entityDef.onCreated) {
682
+ await entityDef.onCreated(data, createEventContext(), options);
683
+ }
684
+ }, "created"),
685
+ updated: /* @__PURE__ */ __name(async (data, options) => {
686
+ await publisher.publishEntityUpdated({
687
+ id: data["id"],
688
+ type: entityDef.type,
689
+ data,
690
+ organizationId: getOrgId(data),
691
+ workspaceId: getWorkspaceId(data)
692
+ }, options, buildRbacMetadata(data));
693
+ if (entityDef.onUpdated) {
694
+ await entityDef.onUpdated(data, createEventContext(), options);
695
+ }
696
+ }, "updated"),
697
+ deleted: /* @__PURE__ */ __name(async (data, options) => {
698
+ await publisher.publishEntityDeleted({
699
+ id: data["id"],
700
+ type: entityDef.type,
701
+ data,
702
+ organizationId: getOrgId(data),
703
+ workspaceId: getWorkspaceId(data)
704
+ }, options, buildRbacMetadata(data));
705
+ if (entityDef.onDeleted) {
706
+ await entityDef.onDeleted(data, createEventContext(), options);
707
+ }
708
+ }, "deleted")
709
+ };
710
+ }
711
+ const getSchema = /* @__PURE__ */ __name(() => {
712
+ const entitySchema = {};
713
+ const relationshipSchema = {};
714
+ for (const [, entityDef] of Object.entries(entities)) {
715
+ entitySchema[entityDef.type] = {
716
+ fields: entityDef.fields || [
717
+ "id",
718
+ "createdAt",
719
+ "updatedAt"
720
+ ],
721
+ collection: entityDef.collection || "entity"
722
+ };
723
+ }
724
+ for (const [relName, relDef] of Object.entries(relationships)) {
725
+ relationshipSchema[relName] = {
726
+ fromType: relDef.fromType,
727
+ toType: relDef.toType,
728
+ edgeType: relDef.edgeType
729
+ };
730
+ }
731
+ return {
732
+ moduleName,
733
+ entities: entitySchema,
734
+ relationships: relationshipSchema
735
+ };
736
+ }, "getSchema");
737
+ const exportEntities = /* @__PURE__ */ __name(async (organizationId, workspaceId, entityTypes) => {
738
+ const result = {};
739
+ for (const [entityName, entityDef] of Object.entries(entities)) {
740
+ if (entityTypes && !entityTypes.includes(entityDef.type)) {
741
+ continue;
742
+ }
743
+ if (!entityDef.fetch) {
744
+ result[entityDef.type] = [];
745
+ continue;
746
+ }
747
+ try {
748
+ const items = await entityDef.fetch(organizationId, workspaceId);
749
+ result[entityDef.type] = items.map((item) => {
750
+ const { id, createdAt, updatedAt, workspaceId: ws, tenantId, ...data } = item;
751
+ return {
752
+ id,
753
+ type: entityDef.type,
754
+ data,
755
+ organizationId: tenantId,
756
+ workspaceId: ws,
757
+ createdAt: createdAt instanceof Date ? createdAt.toISOString() : String(createdAt),
758
+ updatedAt: updatedAt instanceof Date ? updatedAt.toISOString() : String(updatedAt)
759
+ };
760
+ });
761
+ } catch (error) {
762
+ logger.error(`[ModuleGraph:${moduleName}] Error fetching ${entityName}:`, error);
763
+ result[entityDef.type] = [];
764
+ }
765
+ }
766
+ return result;
767
+ }, "exportEntities");
768
+ const exportRelationships = /* @__PURE__ */ __name(async (organizationId, workspaceId) => {
769
+ const result = [];
770
+ for (const [relName, relDef] of Object.entries(relationships)) {
771
+ if (!relDef.fetch) {
772
+ continue;
773
+ }
774
+ try {
775
+ const items = await relDef.fetch(organizationId, workspaceId);
776
+ for (const item of items) {
777
+ result.push({
778
+ id: item.id,
779
+ type: relDef.edgeType,
780
+ fromId: item.fromId,
781
+ fromType: relDef.fromType,
782
+ toId: item.toId,
783
+ toType: relDef.toType,
784
+ metadata: item.metadata || {},
785
+ createdAt: item.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
786
+ updatedAt: item.updatedAt || (/* @__PURE__ */ new Date()).toISOString()
787
+ });
788
+ }
789
+ } catch (error) {
790
+ logger.error(`[ModuleGraph:${moduleName}] Error fetching relationship ${relName}:`, error);
791
+ }
792
+ }
793
+ return result;
794
+ }, "exportRelationships");
795
+ const exportAll = /* @__PURE__ */ __name(async (organizationId, workspaceId) => {
796
+ const schema = getSchema();
797
+ const entitiesData = await exportEntities(organizationId, workspaceId);
798
+ const relationshipsData = await exportRelationships(organizationId, workspaceId);
799
+ const entityCounts = {};
800
+ let totalEntities = 0;
801
+ for (const [type, items] of Object.entries(entitiesData)) {
802
+ entityCounts[type] = items.length;
803
+ totalEntities += items.length;
804
+ }
805
+ return {
806
+ moduleName,
807
+ productSource: productSource ?? moduleName,
808
+ exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
809
+ schema,
810
+ data: {
811
+ entities: entitiesData,
812
+ relationships: relationshipsData
813
+ },
814
+ stats: {
815
+ totalEntities,
816
+ totalRelationships: relationshipsData.length,
817
+ entityCounts
818
+ }
819
+ };
820
+ }, "exportAll");
821
+ return {
822
+ moduleName,
823
+ events,
824
+ initialize: /* @__PURE__ */ __name(() => publisher.initialize(), "initialize"),
825
+ shutdown: /* @__PURE__ */ __name(() => publisher.shutdown(), "shutdown"),
826
+ getSchema,
827
+ exportEntities,
828
+ exportRelationships,
829
+ exportAll,
830
+ getPublisher: /* @__PURE__ */ __name(() => publisher, "getPublisher")
831
+ };
832
+ }
833
+ __name(defineModuleGraph, "defineModuleGraph");
834
+
835
+ // src/graph/config/builder.ts
836
+ var STANDARD_FIELDS = [
837
+ "id",
838
+ "createdAt",
839
+ "updatedAt"
840
+ ];
841
+ var SOFT_DELETE_FIELDS = [
842
+ "deletedAt"
843
+ ];
844
+ var AUDIT_FIELDS = [
845
+ "metadata",
846
+ "context"
847
+ ];
848
+ var TENANT_FIELDS = [
849
+ "workspaceId",
850
+ "tenantId"
851
+ ];
852
+ var DEFAULT_GET_WORKSPACE_ID = /* @__PURE__ */ __name((data) => data["workspaceId"], "DEFAULT_GET_WORKSPACE_ID");
853
+ var DEFAULT_GET_ORG_ID = /* @__PURE__ */ __name((data) => {
854
+ if (data["tenantId"]) {
855
+ return data["tenantId"];
856
+ }
857
+ const context = data["context"];
858
+ return context?.["organizationId"];
859
+ }, "DEFAULT_GET_ORG_ID");
860
+ function createDefaultExtractTitle(entityType) {
861
+ return (data) => {
862
+ const id = data["id"];
863
+ if (typeof id === "string" && id.length > 0) {
864
+ return `${entityType.toLowerCase()}_${id}`;
865
+ }
866
+ return void 0;
867
+ };
868
+ }
869
+ __name(createDefaultExtractTitle, "createDefaultExtractTitle");
870
+ function generateRelationshipLabel(relationshipName) {
871
+ return relationshipName.replace(/([A-Z])/g, "_$1").toUpperCase().replace(/^_/, "");
872
+ }
873
+ __name(generateRelationshipLabel, "generateRelationshipLabel");
874
+ function extractFieldsFromModel(modelName, options, prismaFieldsModule) {
875
+ if (!prismaFieldsModule.hasModel(modelName)) {
876
+ const availableModels = prismaFieldsModule.getAllModelNames().join(", ");
877
+ throw new Error(`Prisma model '${modelName}' not found. Available models: ${availableModels}`);
878
+ }
879
+ const allFields = prismaFieldsModule.getScalarFields(modelName);
880
+ const sdkDefaults = [
881
+ ...STANDARD_FIELDS,
882
+ ...options.softDelete !== false ? SOFT_DELETE_FIELDS : [],
883
+ ...options.multiTenant !== false ? TENANT_FIELDS : [],
884
+ ...options.audit !== false ? AUDIT_FIELDS : []
885
+ ];
886
+ const excluded = /* @__PURE__ */ new Set([
887
+ ...sdkDefaults,
888
+ ...options.exclude ?? []
889
+ ]);
890
+ const filteredFields = allFields.filter((field) => !excluded.has(field));
891
+ const finalFields = [
892
+ ...filteredFields,
893
+ ...options.include ?? []
894
+ ];
895
+ return finalFields;
896
+ }
897
+ __name(extractFieldsFromModel, "extractFieldsFromModel");
898
+ function validateEntityConfig(entityType, config) {
899
+ const errors = [];
900
+ if (!config.fields || config.fields.length === 0) {
901
+ errors.push({
902
+ type: "INVALID_ENTITY_TYPE",
903
+ entityType,
904
+ message: `Entity '${entityType}' must have at least one field`
905
+ });
906
+ }
907
+ if (!config.getWorkspaceId) {
908
+ errors.push({
909
+ type: "MISSING_WORKSPACE_ID",
910
+ entityType,
911
+ message: `Entity '${entityType}' must define getWorkspaceId() to enforce workspace boundary`
912
+ });
913
+ }
914
+ if (!config.getOrgId) {
915
+ errors.push({
916
+ type: "MISSING_ORG_ID",
917
+ entityType,
918
+ message: `Entity '${entityType}' must define getOrgId() for multi-tenant isolation`
919
+ });
920
+ }
921
+ return errors;
922
+ }
923
+ __name(validateEntityConfig, "validateEntityConfig");
924
+ function validateRelationshipConfig(relationshipKey, config, entityTypes) {
925
+ const errors = [];
926
+ if (!entityTypes.has(config.from)) {
927
+ errors.push({
928
+ type: "INVALID_RELATIONSHIP",
929
+ relationshipKey,
930
+ message: `Relationship '${relationshipKey}' references unknown 'from' entity: ${config.from}`
931
+ });
932
+ }
933
+ if (config.to !== "*" && !entityTypes.has(config.to)) {
934
+ errors.push({
935
+ type: "INVALID_RELATIONSHIP",
936
+ relationshipKey,
937
+ message: `Relationship '${relationshipKey}' references unknown 'to' entity: ${config.to}`
938
+ });
939
+ }
940
+ if (config.to === "*" && !config.polymorphicTypeField) {
941
+ errors.push({
942
+ type: "INVALID_RELATIONSHIP",
943
+ relationshipKey,
944
+ message: `Polymorphic relationship '${relationshipKey}' must define polymorphicTypeField`
945
+ });
946
+ }
947
+ if (!config.fromField) {
948
+ errors.push({
949
+ type: "INVALID_RELATIONSHIP",
950
+ relationshipKey,
951
+ message: `Relationship '${relationshipKey}' must define fromField`
952
+ });
953
+ }
954
+ if (!config.label) {
955
+ errors.push({
956
+ type: "INVALID_RELATIONSHIP",
957
+ relationshipKey,
958
+ message: `Relationship '${relationshipKey}' must define label`
959
+ });
960
+ }
961
+ return errors;
962
+ }
963
+ __name(validateRelationshipConfig, "validateRelationshipConfig");
964
+ function validateWorkspaceBoundary(config, _entityTypes) {
965
+ const errors = [];
966
+ const warnings = [];
967
+ const rootTypes = /* @__PURE__ */ new Set([
968
+ "Workspace",
969
+ "Project",
970
+ "Organization",
971
+ "Tenant"
972
+ ]);
973
+ for (const [entityType, entityConfig] of Object.entries(config.entities)) {
974
+ if (entityConfig.enabled === false) continue;
975
+ if (rootTypes.has(entityType)) {
976
+ continue;
977
+ }
978
+ if (!entityConfig.getWorkspaceId) {
979
+ errors.push({
980
+ type: "ORPHANED_ENTITY",
981
+ entityType,
982
+ message: `Entity '${entityType}' has no workspace boundary - every entity must connect to a workspace`
983
+ });
984
+ continue;
985
+ }
986
+ let hasWorkspaceLink = false;
987
+ if (config.relationships) {
988
+ for (const [, relConfig] of Object.entries(config.relationships)) {
989
+ if (relConfig.enabled === false) continue;
990
+ if (relConfig.from === entityType && (relConfig.to === "Workspace" || relConfig.to === "Project" || rootTypes.has(relConfig.to))) {
991
+ hasWorkspaceLink = true;
992
+ break;
993
+ }
994
+ }
995
+ }
996
+ if (!hasWorkspaceLink) {
997
+ warnings.push(`Entity '${entityType}' has no direct relationship to Workspace/Project. Ensure getWorkspaceId() is correctly implemented.`);
998
+ }
999
+ }
1000
+ return {
1001
+ errors,
1002
+ warnings
1003
+ };
1004
+ }
1005
+ __name(validateWorkspaceBoundary, "validateWorkspaceBoundary");
1006
+ function validateNoDuplicates(config, _entityTypes) {
1007
+ const errors = [];
1008
+ const warnings = [];
1009
+ const seenEntityTypes = /* @__PURE__ */ new Set();
1010
+ const relationshipLabels = /* @__PURE__ */ new Set();
1011
+ for (const entityType of Object.keys(config.entities)) {
1012
+ if (seenEntityTypes.has(entityType)) {
1013
+ errors.push({
1014
+ type: "DUPLICATE_ENTITY_TYPE",
1015
+ entityType,
1016
+ message: `Duplicate entity type: ${entityType}`
1017
+ });
1018
+ }
1019
+ seenEntityTypes.add(entityType);
1020
+ }
1021
+ if (config.relationships) {
1022
+ for (const [key, relConfig] of Object.entries(config.relationships)) {
1023
+ const label = relConfig.label;
1024
+ if (relationshipLabels.has(label)) {
1025
+ warnings.push(`Duplicate relationship label: ${label} (in ${key}). This may cause query ambiguity.`);
1026
+ }
1027
+ relationshipLabels.add(label);
1028
+ }
1029
+ }
1030
+ return {
1031
+ errors,
1032
+ warnings
1033
+ };
1034
+ }
1035
+ __name(validateNoDuplicates, "validateNoDuplicates");
1036
+ function validateGraphConfig(config) {
1037
+ const allErrors = [];
1038
+ const allWarnings = [];
1039
+ for (const [entityType, entityConfig] of Object.entries(config.entities)) {
1040
+ if (entityConfig.enabled === false) continue;
1041
+ const errors = validateEntityConfig(entityType, entityConfig);
1042
+ allErrors.push(...errors);
1043
+ }
1044
+ const entityTypes = new Set(Object.keys(config.entities));
1045
+ if (config.relationships) {
1046
+ for (const [relationshipKey, relationshipConfig] of Object.entries(config.relationships)) {
1047
+ if (relationshipConfig.enabled === false) continue;
1048
+ const errors = validateRelationshipConfig(relationshipKey, relationshipConfig, entityTypes);
1049
+ allErrors.push(...errors);
1050
+ }
1051
+ }
1052
+ const boundaryResult = validateWorkspaceBoundary(config);
1053
+ allErrors.push(...boundaryResult.errors);
1054
+ allWarnings.push(...boundaryResult.warnings);
1055
+ const duplicateResult = validateNoDuplicates(config);
1056
+ allErrors.push(...duplicateResult.errors);
1057
+ allWarnings.push(...duplicateResult.warnings);
1058
+ return {
1059
+ valid: allErrors.length === 0,
1060
+ errors: allErrors,
1061
+ warnings: allWarnings
1062
+ };
1063
+ }
1064
+ __name(validateGraphConfig, "validateGraphConfig");
1065
+ function processEntityConfig(entityName, entityOptions, prismaFieldsModule) {
1066
+ const { softDelete = true, multiTenant = true, audit = true, fields, model, exclude, include, collection, getWorkspaceId, getOrgId, extractTitle, rbac, ...rest } = entityOptions;
1067
+ let entityFields;
1068
+ if (model) {
1069
+ if (!prismaFieldsModule) {
1070
+ throw new Error(`Entity '${entityName}' uses model='${model}' but prismaFieldsModule is not provided. Import prisma-fields.ts and pass it to defineGraphConfig({ prismaFieldsModule: ... })`);
1071
+ }
1072
+ entityFields = extractFieldsFromModel(model, {
1073
+ exclude,
1074
+ include,
1075
+ softDelete,
1076
+ multiTenant,
1077
+ audit
1078
+ }, prismaFieldsModule);
1079
+ } else if (fields) {
1080
+ entityFields = fields;
1081
+ } else {
1082
+ throw new Error(`Entity '${entityName}' must specify either 'fields' or 'model' for field definition`);
1083
+ }
1084
+ const autoFields = [
1085
+ ...STANDARD_FIELDS,
1086
+ ...softDelete ? SOFT_DELETE_FIELDS : [],
1087
+ ...multiTenant ? TENANT_FIELDS : [],
1088
+ ...audit ? AUDIT_FIELDS : []
1089
+ ];
1090
+ const mergedFields = [
1091
+ .../* @__PURE__ */ new Set([
1092
+ ...autoFields,
1093
+ ...entityFields
1094
+ ])
1095
+ ];
1096
+ const finalGetWorkspaceId = multiTenant === false ? (_data) => void 0 : getWorkspaceId ?? DEFAULT_GET_WORKSPACE_ID;
1097
+ const finalGetOrgId = multiTenant === false ? (_data) => void 0 : getOrgId ?? DEFAULT_GET_ORG_ID;
1098
+ return {
1099
+ collection: collection ?? "entities",
1100
+ fields: mergedFields,
1101
+ getWorkspaceId: finalGetWorkspaceId,
1102
+ getOrgId: finalGetOrgId,
1103
+ extractTitle: extractTitle ?? createDefaultExtractTitle(entityName),
1104
+ ...rbac && {
1105
+ rbac
1106
+ },
1107
+ ...rest
1108
+ };
1109
+ }
1110
+ __name(processEntityConfig, "processEntityConfig");
1111
+ function processRelationships(relationshipOptions) {
1112
+ const relationships = {};
1113
+ for (const [relationshipName, options] of Object.entries(relationshipOptions)) {
1114
+ const { label, toField, ...rest } = options;
1115
+ relationships[relationshipName] = {
1116
+ toField: toField ?? "id",
1117
+ label: label ?? generateRelationshipLabel(relationshipName),
1118
+ ...rest
1119
+ };
1120
+ }
1121
+ return relationships;
1122
+ }
1123
+ __name(processRelationships, "processRelationships");
1124
+ function logValidationResults(moduleName, validationResult) {
1125
+ if (validationResult.errors.length > 0) {
1126
+ logger.error(`[GraphConfig:${moduleName}] Configuration validation failed:`);
1127
+ for (const error of validationResult.errors) {
1128
+ logger.error(` - ${error.message}`, {
1129
+ type: error.type,
1130
+ entityType: error.entityType,
1131
+ relationshipKey: error.relationshipKey
1132
+ });
1133
+ }
1134
+ throw new Error(`Graph configuration validation failed for ${moduleName}`);
1135
+ }
1136
+ if (validationResult.warnings.length > 0) {
1137
+ logger.warn(`[GraphConfig:${moduleName}] Configuration warnings:`);
1138
+ for (const warning of validationResult.warnings) {
1139
+ logger.warn(` - ${warning}`);
1140
+ }
1141
+ }
1142
+ logger.info(`[GraphConfig:${moduleName}] Configuration validated successfully`, {
1143
+ valid: validationResult.valid,
1144
+ errorCount: validationResult.errors.length,
1145
+ warningCount: validationResult.warnings.length,
1146
+ autoFieldsApplied: true
1147
+ });
1148
+ }
1149
+ __name(logValidationResults, "logValidationResults");
1150
+ function defineGraphConfig(options) {
1151
+ const entities = {};
1152
+ for (const [entityName, entityOptions] of Object.entries(options.entities)) {
1153
+ entities[entityName] = processEntityConfig(entityName, entityOptions, options.prismaFieldsModule);
1154
+ }
1155
+ const relationships = options.relationships ? processRelationships(options.relationships) : {};
1156
+ const config = {
1157
+ moduleName: options.moduleName,
1158
+ entities,
1159
+ relationships
1160
+ };
1161
+ const validationResult = validateGraphConfig(config);
1162
+ logValidationResults(config.moduleName, validationResult);
1163
+ autoRegisterWithRegistry(config);
1164
+ return config;
1165
+ }
1166
+ __name(defineGraphConfig, "defineGraphConfig");
1167
+ function autoRegisterWithRegistry(config) {
1168
+ const { moduleName, entities, relationships = {} } = config;
1169
+ const registryEntities = {};
1170
+ for (const [entityType, entityConfig] of Object.entries(entities)) {
1171
+ registryEntities[entityType] = {
1172
+ fields: entityConfig.fields,
1173
+ collection: entityConfig.collection || "entities",
1174
+ extractTitle: entityConfig.extractTitle,
1175
+ getOrgId: entityConfig.getOrgId,
1176
+ getWorkspaceId: entityConfig.getWorkspaceId,
1177
+ enabled: entityConfig.enabled,
1178
+ // Pass through RBAC config so the Prisma graph extension
1179
+ // can include RBAC metadata in entity lifecycle events
1180
+ ...entityConfig.rbac && {
1181
+ rbac: {
1182
+ resourceTypeName: entityConfig.rbac.resourceTypeName,
1183
+ extractName: entityConfig.rbac.extractName,
1184
+ extractIdentifier: entityConfig.rbac.extractIdentifier,
1185
+ parentResourceField: entityConfig.rbac.parentResourceField,
1186
+ createResource: entityConfig.rbac.createResource
1187
+ }
1188
+ }
1189
+ };
1190
+ }
1191
+ const registryRelationships = {};
1192
+ for (const [key, relConfig] of Object.entries(relationships)) {
1193
+ registryRelationships[key] = {
1194
+ from: relConfig.from,
1195
+ to: relConfig.to,
1196
+ fromField: relConfig.fromField,
1197
+ toField: relConfig.toField,
1198
+ label: relConfig.label,
1199
+ description: relConfig.description,
1200
+ extractMetadata: relConfig.extractMetadata,
1201
+ polymorphicTypeField: relConfig.polymorphicTypeField,
1202
+ enabled: relConfig.enabled
1203
+ };
1204
+ }
1205
+ GraphRegistry.registerModule({
1206
+ moduleName,
1207
+ entities: registryEntities,
1208
+ relationships: registryRelationships
1209
+ });
1210
+ logger.info(`[GraphConfig:${moduleName}] Auto-registered ${Object.keys(entities).length} entities with GraphRegistry`);
1211
+ }
1212
+ __name(autoRegisterWithRegistry, "autoRegisterWithRegistry");
1213
+ function defineEntity(config) {
1214
+ return config;
1215
+ }
1216
+ __name(defineEntity, "defineEntity");
1217
+ function defineRelationship(config) {
1218
+ return config;
1219
+ }
1220
+ __name(defineRelationship, "defineRelationship");
1221
+
1222
+ // src/graph/config/init.ts
1223
+ var RuntimeValidator = class RuntimeValidator2 {
1224
+ static {
1225
+ __name(this, "RuntimeValidator");
1226
+ }
1227
+ config;
1228
+ constructor(config) {
1229
+ this.config = config;
1230
+ }
1231
+ /**
1232
+ * Validate entity data extraction
1233
+ */
1234
+ validateEntityData(entityType, data) {
1235
+ const errors = [];
1236
+ const entityConfig = this.config.entities[entityType];
1237
+ if (!entityConfig) {
1238
+ return {
1239
+ valid: true,
1240
+ errors: []
1241
+ };
1242
+ }
1243
+ try {
1244
+ const workspaceId = entityConfig.getWorkspaceId(data);
1245
+ if (!workspaceId) {
1246
+ errors.push(`Entity ${entityType}:${data["id"]} has no workspaceId`);
1247
+ }
1248
+ } catch (error) {
1249
+ errors.push(`Error extracting workspaceId for ${entityType}: ${error}`);
1250
+ }
1251
+ try {
1252
+ const orgId = entityConfig.getOrgId(data);
1253
+ if (!orgId) {
1254
+ errors.push(`Entity ${entityType}:${data["id"]} has no organizationId`);
1255
+ }
1256
+ } catch (error) {
1257
+ errors.push(`Error extracting organizationId for ${entityType}: ${error}`);
1258
+ }
1259
+ for (const field of entityConfig.fields) {
1260
+ if (!(field in data)) {
1261
+ errors.push(`Entity ${entityType}:${data["id"]} missing configured field: ${field}`);
1262
+ }
1263
+ }
1264
+ return {
1265
+ valid: errors.length === 0,
1266
+ errors
1267
+ };
1268
+ }
1269
+ };
1270
+ function initializeGraph(prismaClient, config, options) {
1271
+ const { productName, eventEmitter, monitoredEntityTypes = [], enabled = true, validateRuntime } = options;
1272
+ const shouldValidate = validateRuntime ?? process.env["NODE_ENV"] !== "production";
1273
+ logger.info(`[GraphInit:${config.moduleName}] Initializing graph integration`, {
1274
+ productName,
1275
+ enabled,
1276
+ validateRuntime: shouldValidate,
1277
+ entities: Object.keys(config.entities).length,
1278
+ relationships: config.relationships ? Object.keys(config.relationships).length : 0
1279
+ });
1280
+ if (!enabled) {
1281
+ logger.warn(`[GraphInit:${config.moduleName}] Graph integration disabled by configuration`);
1282
+ return prismaClient;
1283
+ }
1284
+ registerConfigWithRegistry(config);
1285
+ const validator = shouldValidate ? new RuntimeValidator(config) : null;
1286
+ const wrappedEmitter = {
1287
+ publishEntityEvent: /* @__PURE__ */ __name(async (eventType, entity, context, rbac) => {
1288
+ if (validator && (eventType === "entity.created" || eventType === "entity.updated")) {
1289
+ const validation = validator.validateEntityData(entity.type, entity.data);
1290
+ if (!validation.valid) {
1291
+ logger.error(`[GraphInit:${config.moduleName}] Runtime validation failed for ${entity.type}:${entity.id}`, {
1292
+ errors: validation.errors
1293
+ });
1294
+ }
1295
+ }
1296
+ return eventEmitter.publishEntityEvent(eventType, entity, context, rbac);
1297
+ }, "publishEntityEvent")
1298
+ };
1299
+ const extendedClient = addGraphExtension(prismaClient, {
1300
+ enabled: true,
1301
+ productName,
1302
+ eventEmitter: wrappedEmitter,
1303
+ entityTypes: monitoredEntityTypes
1304
+ });
1305
+ logger.info(`[GraphInit:${config.moduleName}] Graph integration initialized successfully`);
1306
+ return extendedClient;
1307
+ }
1308
+ __name(initializeGraph, "initializeGraph");
1309
+ function registerConfigWithRegistry(config) {
1310
+ const { moduleName, entities, relationships = {} } = config;
1311
+ const registryEntities = {};
1312
+ for (const [entityType, entityConfig] of Object.entries(entities)) {
1313
+ registryEntities[entityType] = {
1314
+ fields: entityConfig.fields,
1315
+ collection: entityConfig.collection || "entities",
1316
+ extractTitle: entityConfig.extractTitle,
1317
+ getOrgId: entityConfig.getOrgId,
1318
+ getWorkspaceId: entityConfig.getWorkspaceId,
1319
+ enabled: entityConfig.enabled
1320
+ };
1321
+ }
1322
+ const registryRelationships = {};
1323
+ for (const [key, relConfig] of Object.entries(relationships)) {
1324
+ registryRelationships[key] = {
1325
+ from: relConfig.from,
1326
+ to: relConfig.to,
1327
+ fromField: relConfig.fromField,
1328
+ toField: relConfig.toField,
1329
+ label: relConfig.label,
1330
+ description: relConfig.description,
1331
+ extractMetadata: relConfig.extractMetadata,
1332
+ polymorphicTypeField: relConfig.polymorphicTypeField,
1333
+ enabled: relConfig.enabled
1334
+ };
1335
+ }
1336
+ GraphRegistry.registerModule({
1337
+ moduleName,
1338
+ entities: registryEntities,
1339
+ relationships: registryRelationships
1340
+ });
1341
+ logger.info(`[GraphInit:${moduleName}] Configuration registered with GraphRegistry`);
1342
+ }
1343
+ __name(registerConfigWithRegistry, "registerConfigWithRegistry");
1344
+ function isGraphInitialized(moduleName) {
1345
+ const registeredModules = GraphRegistry.getRegisteredModules();
1346
+ return registeredModules.includes(moduleName);
1347
+ }
1348
+ __name(isGraphInitialized, "isGraphInitialized");
1349
+ function getGraphStats() {
1350
+ const stats = GraphRegistry.getStats();
1351
+ const registeredModules = GraphRegistry.getRegisteredModules();
1352
+ return {
1353
+ modules: stats.modules,
1354
+ entities: stats.entities,
1355
+ relationships: stats.relationships,
1356
+ registeredModules
1357
+ };
1358
+ }
1359
+ __name(getGraphStats, "getGraphStats");
1360
+
1361
+ // src/graph/index.ts
1362
+ var GraphModule = class {
1363
+ static {
1364
+ __name(this, "GraphModule");
1365
+ }
1366
+ client;
1367
+ context;
1368
+ constructor(client, context) {
1369
+ this.client = client;
1370
+ this.context = context;
1371
+ }
1372
+ /**
1373
+ * Create graph node
1374
+ */
1375
+ async createNode(options) {
1376
+ if (!options.type) {
1377
+ throw new ValidationError("Node type is required");
1378
+ }
1379
+ if (!options.properties || typeof options.properties !== "object") {
1380
+ throw new ValidationError("Node properties must be an object");
1381
+ }
1382
+ logger.debug("[Graph] Creating node", {
1383
+ type: options.type
1384
+ });
1385
+ const mutation = `
1386
+ mutation CreateGraphNode($input: CreateGraphNodeInput!) {
1387
+ createGraphNode(input: $input) {
1388
+ id
1389
+ type
1390
+ properties
1391
+ workspaceId
1392
+ organizationId
1393
+ createdAt
1394
+ updatedAt
1395
+ }
1396
+ }
1397
+ `;
1398
+ const variables = {
1399
+ input: {
1400
+ type: options.type,
1401
+ properties: options.properties,
1402
+ workspaceId: options.workspaceId || this.context.workspaceId,
1403
+ organizationId: options.organizationId
1404
+ }
1405
+ };
1406
+ const response = await this.client.query(mutation, variables, this.context);
1407
+ logger.info("[Graph] Node created", {
1408
+ nodeId: response.createGraphNode.id
1409
+ });
1410
+ return response.createGraphNode;
1411
+ }
1412
+ /**
1413
+ * Create graph edge
1414
+ */
1415
+ async createEdge(options) {
1416
+ if (!options.from) {
1417
+ throw new ValidationError("Source node ID is required");
1418
+ }
1419
+ if (!options.to) {
1420
+ throw new ValidationError("Target node ID is required");
1421
+ }
1422
+ if (!options.type) {
1423
+ throw new ValidationError("Edge type is required");
1424
+ }
1425
+ logger.debug("[Graph] Creating edge", {
1426
+ from: options.from,
1427
+ to: options.to,
1428
+ type: options.type
1429
+ });
1430
+ const mutation = `
1431
+ mutation CreateGraphEdge($input: CreateGraphEdgeInput!) {
1432
+ createGraphEdge(input: $input) {
1433
+ id
1434
+ from
1435
+ to
1436
+ type
1437
+ properties
1438
+ workspaceId
1439
+ organizationId
1440
+ createdAt
1441
+ }
1442
+ }
1443
+ `;
1444
+ const variables = {
1445
+ input: {
1446
+ from: options.from,
1447
+ to: options.to,
1448
+ type: options.type,
1449
+ properties: options.properties,
1450
+ workspaceId: options.workspaceId || this.context.workspaceId,
1451
+ organizationId: options.organizationId
1452
+ }
1453
+ };
1454
+ const response = await this.client.query(mutation, variables, this.context);
1455
+ logger.info("[Graph] Edge created", {
1456
+ edgeId: response.createGraphEdge.id
1457
+ });
1458
+ return response.createGraphEdge;
1459
+ }
1460
+ /**
1461
+ * Get node by ID
1462
+ */
1463
+ async getNode(nodeId) {
1464
+ logger.debug("[Graph] Getting node", {
1465
+ nodeId
1466
+ });
1467
+ const query = `
1468
+ query GetGraphNode($nodeId: ID!) {
1469
+ getGraphNode(nodeId: $nodeId) {
1470
+ id
1471
+ type
1472
+ properties
1473
+ workspaceId
1474
+ organizationId
1475
+ createdAt
1476
+ updatedAt
1477
+ }
1478
+ }
1479
+ `;
1480
+ const response = await this.client.query(query, {
1481
+ nodeId
1482
+ }, this.context);
1483
+ return response.getGraphNode;
1484
+ }
1485
+ /**
1486
+ * Update node
1487
+ */
1488
+ async updateNode(nodeId, properties) {
1489
+ logger.debug("[Graph] Updating node", {
1490
+ nodeId
1491
+ });
1492
+ const mutation = `
1493
+ mutation UpdateGraphNode($nodeId: ID!, $properties: JSON!) {
1494
+ updateGraphNode(nodeId: $nodeId, properties: $properties) {
1495
+ id
1496
+ type
1497
+ properties
1498
+ workspaceId
1499
+ organizationId
1500
+ createdAt
1501
+ updatedAt
1502
+ }
1503
+ }
1504
+ `;
1505
+ const response = await this.client.query(mutation, {
1506
+ nodeId,
1507
+ properties
1508
+ }, this.context);
1509
+ logger.info("[Graph] Node updated", {
1510
+ nodeId
1511
+ });
1512
+ return response.updateGraphNode;
1513
+ }
1514
+ /**
1515
+ * Delete node
1516
+ */
1517
+ async deleteNode(nodeId) {
1518
+ logger.debug("[Graph] Deleting node", {
1519
+ nodeId
1520
+ });
1521
+ const mutation = `
1522
+ mutation DeleteGraphNode($nodeId: ID!) {
1523
+ deleteGraphNode(nodeId: $nodeId) {
1524
+ success
1525
+ }
1526
+ }
1527
+ `;
1528
+ await this.client.query(mutation, {
1529
+ nodeId
1530
+ }, this.context);
1531
+ logger.info("[Graph] Node deleted", {
1532
+ nodeId
1533
+ });
1534
+ return true;
1535
+ }
1536
+ /**
1537
+ * Delete edge
1538
+ */
1539
+ async deleteEdge(edgeId) {
1540
+ logger.debug("[Graph] Deleting edge", {
1541
+ edgeId
1542
+ });
1543
+ const mutation = `
1544
+ mutation DeleteGraphEdge($edgeId: ID!) {
1545
+ deleteGraphEdge(edgeId: $edgeId) {
1546
+ success
1547
+ }
1548
+ }
1549
+ `;
1550
+ await this.client.query(mutation, {
1551
+ edgeId
1552
+ }, this.context);
1553
+ logger.info("[Graph] Edge deleted", {
1554
+ edgeId
1555
+ });
1556
+ return true;
1557
+ }
1558
+ /**
1559
+ * Traverse graph
1560
+ */
1561
+ async traverse(options) {
1562
+ if (!options.startNode) {
1563
+ throw new ValidationError("Start node ID is required");
1564
+ }
1565
+ logger.debug("[Graph] Traversing graph", {
1566
+ startNode: options.startNode,
1567
+ direction: options.direction || "outbound"
1568
+ });
1569
+ const query = `
1570
+ query TraverseGraph(
1571
+ $startNode: ID!
1572
+ $direction: GraphDirection
1573
+ $edgeTypes: [String!]
1574
+ $minDepth: Int
1575
+ $maxDepth: Int
1576
+ $limit: Int
1577
+ ) {
1578
+ traverseGraph(
1579
+ startNode: $startNode
1580
+ direction: $direction
1581
+ edgeTypes: $edgeTypes
1582
+ minDepth: $minDepth
1583
+ maxDepth: $maxDepth
1584
+ limit: $limit
1585
+ ) {
1586
+ nodes {
1587
+ id
1588
+ type
1589
+ properties
1590
+ workspaceId
1591
+ organizationId
1592
+ createdAt
1593
+ updatedAt
1594
+ }
1595
+ edges {
1596
+ id
1597
+ from
1598
+ to
1599
+ type
1600
+ properties
1601
+ workspaceId
1602
+ organizationId
1603
+ createdAt
1604
+ }
1605
+ paths {
1606
+ nodes {
1607
+ id
1608
+ type
1609
+ properties
1610
+ }
1611
+ edges {
1612
+ id
1613
+ from
1614
+ to
1615
+ type
1616
+ }
1617
+ }
1618
+ }
1619
+ }
1620
+ `;
1621
+ const variables = {
1622
+ startNode: options.startNode,
1623
+ direction: options.direction || "outbound",
1624
+ edgeTypes: options.edgeTypes,
1625
+ minDepth: options.minDepth || 1,
1626
+ maxDepth: options.maxDepth || 3,
1627
+ limit: options.limit || 100
1628
+ };
1629
+ const response = await this.client.query(query, variables, this.context);
1630
+ return response.traverseGraph;
1631
+ }
1632
+ /**
1633
+ * Find shortest path between two nodes
1634
+ */
1635
+ async findShortestPath(fromNode, toNode, options) {
1636
+ logger.debug("[Graph] Finding shortest path", {
1637
+ fromNode,
1638
+ toNode
1639
+ });
1640
+ const query = `
1641
+ query FindShortestPath(
1642
+ $fromNode: ID!
1643
+ $toNode: ID!
1644
+ $edgeTypes: [String!]
1645
+ $maxDepth: Int
1646
+ ) {
1647
+ findShortestPath(
1648
+ fromNode: $fromNode
1649
+ toNode: $toNode
1650
+ edgeTypes: $edgeTypes
1651
+ maxDepth: $maxDepth
1652
+ ) {
1653
+ nodes {
1654
+ id
1655
+ type
1656
+ properties
1657
+ }
1658
+ edges {
1659
+ id
1660
+ from
1661
+ to
1662
+ type
1663
+ }
1664
+ distance
1665
+ }
1666
+ }
1667
+ `;
1668
+ const response = await this.client.query(query, {
1669
+ fromNode,
1670
+ toNode,
1671
+ edgeTypes: options?.edgeTypes,
1672
+ maxDepth: options?.maxDepth || 10
1673
+ }, this.context);
1674
+ return response.findShortestPath;
1675
+ }
1676
+ /**
1677
+ * Query graph with nGQL. Proxied to wspace-graph-svc's `executeNGQL` resolver
1678
+ * via the federated GraphQL gateway — no direct graph-DB access.
1679
+ */
1680
+ async query(options) {
1681
+ if (!options.query) {
1682
+ throw new ValidationError("nGQL query is required");
1683
+ }
1684
+ logger.debug("[Graph] Executing nGQL query");
1685
+ const query = `
1686
+ query ExecuteNGQL($query: String!, $bindVars: JSON, $limit: Int) {
1687
+ executeNGQL(query: $query, bindVars: $bindVars, limit: $limit) {
1688
+ results
1689
+ }
1690
+ }
1691
+ `;
1692
+ const variables = {
1693
+ query: options.query,
1694
+ bindVars: options.bindVars,
1695
+ limit: options.limit || 1e3
1696
+ };
1697
+ const response = await this.client.query(query, variables, this.context);
1698
+ return response.executeNGQL.results;
1699
+ }
1700
+ /**
1701
+ * Get neighbors of a node
1702
+ */
1703
+ async getNeighbors(nodeId, options) {
1704
+ logger.debug("[Graph] Getting neighbors", {
1705
+ nodeId
1706
+ });
1707
+ const query = `
1708
+ query GetNeighbors(
1709
+ $nodeId: ID!
1710
+ $direction: GraphDirection
1711
+ $edgeTypes: [String!]
1712
+ $limit: Int
1713
+ ) {
1714
+ getNeighbors(
1715
+ nodeId: $nodeId
1716
+ direction: $direction
1717
+ edgeTypes: $edgeTypes
1718
+ limit: $limit
1719
+ ) {
1720
+ nodes {
1721
+ id
1722
+ type
1723
+ properties
1724
+ workspaceId
1725
+ organizationId
1726
+ createdAt
1727
+ updatedAt
1728
+ }
1729
+ edges {
1730
+ id
1731
+ from
1732
+ to
1733
+ type
1734
+ properties
1735
+ workspaceId
1736
+ organizationId
1737
+ createdAt
1738
+ }
1739
+ }
1740
+ }
1741
+ `;
1742
+ const response = await this.client.query(query, {
1743
+ nodeId,
1744
+ direction: options?.direction || "outbound",
1745
+ edgeTypes: options?.edgeTypes,
1746
+ limit: options?.limit || 100
1747
+ }, this.context);
1748
+ return response.getNeighbors;
1749
+ }
1750
+ /**
1751
+ * Get node degree (number of connections)
1752
+ */
1753
+ async getNodeDegree(nodeId, direction) {
1754
+ logger.debug("[Graph] Getting node degree", {
1755
+ nodeId
1756
+ });
1757
+ const query = `
1758
+ query GetNodeDegree($nodeId: ID!, $direction: GraphDirection) {
1759
+ getNodeDegree(nodeId: $nodeId, direction: $direction) {
1760
+ inbound
1761
+ outbound
1762
+ total
1763
+ }
1764
+ }
1765
+ `;
1766
+ const response = await this.client.query(query, {
1767
+ nodeId,
1768
+ direction
1769
+ }, this.context);
1770
+ return response.getNodeDegree;
1771
+ }
1772
+ /**
1773
+ * Find nodes by properties
1774
+ */
1775
+ async findNodes(type, filters, options) {
1776
+ logger.debug("[Graph] Finding nodes", {
1777
+ type,
1778
+ filters
1779
+ });
1780
+ const query = `
1781
+ query FindGraphNodes(
1782
+ $type: String!
1783
+ $filters: JSON!
1784
+ $limit: Int
1785
+ $offset: Int
1786
+ ) {
1787
+ findGraphNodes(
1788
+ type: $type
1789
+ filters: $filters
1790
+ limit: $limit
1791
+ offset: $offset
1792
+ ) {
1793
+ nodes {
1794
+ id
1795
+ type
1796
+ properties
1797
+ workspaceId
1798
+ organizationId
1799
+ createdAt
1800
+ updatedAt
1801
+ }
1802
+ total
1803
+ }
1804
+ }
1805
+ `;
1806
+ const response = await this.client.query(query, {
1807
+ type,
1808
+ filters,
1809
+ limit: options?.limit || 100,
1810
+ offset: options?.offset || 0
1811
+ }, this.context);
1812
+ return response.findGraphNodes;
1813
+ }
1814
+ /**
1815
+ * Batch create nodes
1816
+ */
1817
+ async createNodesBatch(nodes) {
1818
+ logger.debug("[Graph] Batch creating nodes", {
1819
+ count: nodes.length
1820
+ });
1821
+ const mutation = `
1822
+ mutation CreateGraphNodesBatch($nodes: [CreateGraphNodeInput!]!) {
1823
+ createGraphNodesBatch(nodes: $nodes) {
1824
+ id
1825
+ type
1826
+ properties
1827
+ workspaceId
1828
+ organizationId
1829
+ createdAt
1830
+ updatedAt
1831
+ }
1832
+ }
1833
+ `;
1834
+ const response = await this.client.query(mutation, {
1835
+ nodes
1836
+ }, this.context);
1837
+ logger.info("[Graph] Nodes batch created", {
1838
+ count: response.createGraphNodesBatch.length
1839
+ });
1840
+ return response.createGraphNodesBatch;
1841
+ }
1842
+ /**
1843
+ * Batch create edges
1844
+ */
1845
+ async createEdgesBatch(edges) {
1846
+ logger.debug("[Graph] Batch creating edges", {
1847
+ count: edges.length
1848
+ });
1849
+ const mutation = `
1850
+ mutation CreateGraphEdgesBatch($edges: [CreateGraphEdgeInput!]!) {
1851
+ createGraphEdgesBatch(edges: $edges) {
1852
+ id
1853
+ from
1854
+ to
1855
+ type
1856
+ properties
1857
+ workspaceId
1858
+ organizationId
1859
+ createdAt
1860
+ }
1861
+ }
1862
+ `;
1863
+ const response = await this.client.query(mutation, {
1864
+ edges
1865
+ }, this.context);
1866
+ logger.info("[Graph] Edges batch created", {
1867
+ count: response.createGraphEdgesBatch.length
1868
+ });
1869
+ return response.createGraphEdgesBatch;
1870
+ }
1871
+ };
1872
+
1873
+ export { AUDIT_FIELDS, GraphEventsPublisher, GraphExportService, GraphModule, SOFT_DELETE_FIELDS, STANDARD_FIELDS, TENANT_FIELDS, createGraphEventsHelper, createGraphExportService, createPrismaGraphIntegration, createRelationshipFromEntity, defineEntity, defineGraphConfig, defineModuleGraph, defineRelationship, getGraphEventsPublisher, getGraphStats, graph_exports, initializeGraph, isGraphInitialized };
1874
+ //# sourceMappingURL=chunk-F5XEAGHQ.js.map
1875
+ //# sourceMappingURL=chunk-F5XEAGHQ.js.map