@mastra/factory 0.2.2-alpha.0 → 0.2.2-alpha.2

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 (174) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/auth.d.ts +2 -2
  3. package/dist/auth.d.ts.map +1 -1
  4. package/dist/auth.js +401 -314
  5. package/dist/auth.js.map +1 -1
  6. package/dist/capabilities/connection.js +1 -1
  7. package/dist/capabilities/intake.js +1 -1
  8. package/dist/capabilities/version-control.js +1 -1
  9. package/dist/factory.d.ts.map +1 -1
  10. package/dist/factory.js +441 -39455
  11. package/dist/factory.js.map +1 -1
  12. package/dist/index.js +2 -39466
  13. package/dist/integrations/base.js +1 -1
  14. package/dist/integrations/github/config.js +36 -22
  15. package/dist/integrations/github/config.js.map +1 -1
  16. package/dist/integrations/github/factory-session.js +33 -37
  17. package/dist/integrations/github/factory-session.js.map +1 -1
  18. package/dist/integrations/github/integration.js +1037 -3624
  19. package/dist/integrations/github/integration.js.map +1 -1
  20. package/dist/integrations/github/issue-triage.js +71 -71
  21. package/dist/integrations/github/issue-triage.js.map +1 -1
  22. package/dist/integrations/github/pat.js +47 -36
  23. package/dist/integrations/github/pat.js.map +1 -1
  24. package/dist/integrations/github/provenance.js +72 -101
  25. package/dist/integrations/github/provenance.js.map +1 -1
  26. package/dist/integrations/github/routes.d.ts.map +1 -1
  27. package/dist/integrations/github/routes.js +1272 -1833
  28. package/dist/integrations/github/routes.js.map +1 -1
  29. package/dist/integrations/github/rules.js +203 -471
  30. package/dist/integrations/github/rules.js.map +1 -1
  31. package/dist/integrations/github/sandbox.d.ts +2 -0
  32. package/dist/integrations/github/sandbox.d.ts.map +1 -1
  33. package/dist/integrations/github/sandbox.js +401 -326
  34. package/dist/integrations/github/sandbox.js.map +1 -1
  35. package/dist/integrations/github/session-subscriptions.js +165 -223
  36. package/dist/integrations/github/session-subscriptions.js.map +1 -1
  37. package/dist/integrations/github/subscriptions.js +43 -51
  38. package/dist/integrations/github/subscriptions.js.map +1 -1
  39. package/dist/integrations/github/token-refresh.js +15 -18
  40. package/dist/integrations/github/token-refresh.js.map +1 -1
  41. package/dist/integrations/github/webhook.js +359 -343
  42. package/dist/integrations/github/webhook.js.map +1 -1
  43. package/dist/integrations/linear/agent-tools.js +77 -100
  44. package/dist/integrations/linear/agent-tools.js.map +1 -1
  45. package/dist/integrations/linear/integration.js +611 -1309
  46. package/dist/integrations/linear/integration.js.map +1 -1
  47. package/dist/integrations/linear/routes.js +227 -230
  48. package/dist/integrations/linear/routes.js.map +1 -1
  49. package/dist/integrations/linear/rules.js +126 -346
  50. package/dist/integrations/linear/rules.js.map +1 -1
  51. package/dist/integrations/linear/storage.js +1 -1
  52. package/dist/integrations/platform/api-client.js +131 -135
  53. package/dist/integrations/platform/api-client.js.map +1 -1
  54. package/dist/integrations/platform/github/event-worker.js +275 -573
  55. package/dist/integrations/platform/github/event-worker.js.map +1 -1
  56. package/dist/integrations/platform/github/integration.d.ts.map +1 -1
  57. package/dist/integrations/platform/github/integration.js +845 -3942
  58. package/dist/integrations/platform/github/integration.js.map +1 -1
  59. package/dist/integrations/platform/linear/integration.js +457 -1309
  60. package/dist/integrations/platform/linear/integration.js.map +1 -1
  61. package/dist/integrations/workos/integration.js +80 -85
  62. package/dist/integrations/workos/integration.js.map +1 -1
  63. package/dist/routes/config.d.ts.map +1 -1
  64. package/dist/routes/config.js +933 -915
  65. package/dist/routes/config.js.map +1 -1
  66. package/dist/routes/custom-provider-source.js +110 -93
  67. package/dist/routes/custom-provider-source.js.map +1 -1
  68. package/dist/routes/fs.js +401 -349
  69. package/dist/routes/fs.js.map +1 -1
  70. package/dist/routes/intake.js +165 -165
  71. package/dist/routes/intake.js.map +1 -1
  72. package/dist/routes/oauth.js +447 -25166
  73. package/dist/routes/oauth.js.map +1 -1
  74. package/dist/routes/projects.js +437 -376
  75. package/dist/routes/projects.js.map +1 -1
  76. package/dist/routes/provider-credentials.js +76 -58
  77. package/dist/routes/provider-credentials.js.map +1 -1
  78. package/dist/routes/route.js +12 -8
  79. package/dist/routes/route.js.map +1 -1
  80. package/dist/routes/skills.js +160 -173
  81. package/dist/routes/skills.js.map +1 -1
  82. package/dist/routes/surface.js +250 -28618
  83. package/dist/routes/surface.js.map +1 -1
  84. package/dist/routes/tenant-credentials.js +141 -166
  85. package/dist/routes/tenant-credentials.js.map +1 -1
  86. package/dist/routes/work-items.js +654 -862
  87. package/dist/routes/work-items.js.map +1 -1
  88. package/dist/rules/binding-context.js +23 -35
  89. package/dist/rules/binding-context.js.map +1 -1
  90. package/dist/rules/defaults.js +200 -309
  91. package/dist/rules/defaults.js.map +1 -1
  92. package/dist/rules/dispatcher.d.ts.map +1 -1
  93. package/dist/rules/dispatcher.js +438 -677
  94. package/dist/rules/dispatcher.js.map +1 -1
  95. package/dist/rules/index.js +5 -599
  96. package/dist/rules/processor.js +344 -596
  97. package/dist/rules/processor.js.map +1 -1
  98. package/dist/rules/resolve.js +21 -18
  99. package/dist/rules/resolve.js.map +1 -1
  100. package/dist/rules/start-coordinator.js +168 -157
  101. package/dist/rules/start-coordinator.js.map +1 -1
  102. package/dist/rules/tools.js +50 -85
  103. package/dist/rules/tools.js.map +1 -1
  104. package/dist/rules/transition-service.js +183 -454
  105. package/dist/rules/transition-service.js.map +1 -1
  106. package/dist/rules/types.js +33 -29
  107. package/dist/rules/types.js.map +1 -1
  108. package/dist/rules/validation.js +266 -281
  109. package/dist/rules/validation.js.map +1 -1
  110. package/dist/sandbox/fleet.js +272 -250
  111. package/dist/sandbox/fleet.js.map +1 -1
  112. package/dist/sandbox/reattach.js +13 -6
  113. package/dist/sandbox/reattach.js.map +1 -1
  114. package/dist/server-error.js +12 -16
  115. package/dist/server-error.js.map +1 -1
  116. package/dist/skills/service.js +30 -35
  117. package/dist/skills/service.js.map +1 -1
  118. package/dist/spa-static.d.ts.map +1 -1
  119. package/dist/spa-static.js +91 -64
  120. package/dist/spa-static.js.map +1 -1
  121. package/dist/state-signing.js +73 -44
  122. package/dist/state-signing.js.map +1 -1
  123. package/dist/storage/domains/audit/agent-audit.js +60 -59
  124. package/dist/storage/domains/audit/agent-audit.js.map +1 -1
  125. package/dist/storage/domains/audit/base.js +169 -112
  126. package/dist/storage/domains/audit/base.js.map +1 -1
  127. package/dist/storage/domains/audit/domain.js +155 -153
  128. package/dist/storage/domains/audit/domain.js.map +1 -1
  129. package/dist/storage/domains/credentials/base.js +259 -243
  130. package/dist/storage/domains/credentials/base.js.map +1 -1
  131. package/dist/storage/domains/custom-providers/base.js +138 -143
  132. package/dist/storage/domains/custom-providers/base.js.map +1 -1
  133. package/dist/storage/domains/intake/base.js +75 -57
  134. package/dist/storage/domains/intake/base.js.map +1 -1
  135. package/dist/storage/domains/integrations/base.js +310 -245
  136. package/dist/storage/domains/integrations/base.js.map +1 -1
  137. package/dist/storage/domains/memory-settings/base.js +117 -102
  138. package/dist/storage/domains/memory-settings/base.js.map +1 -1
  139. package/dist/storage/domains/model-packs/base.js +89 -88
  140. package/dist/storage/domains/model-packs/base.js.map +1 -1
  141. package/dist/storage/domains/projects/base.js +97 -92
  142. package/dist/storage/domains/projects/base.js.map +1 -1
  143. package/dist/storage/domains/queue-health/base.js +111 -76
  144. package/dist/storage/domains/queue-health/base.js.map +1 -1
  145. package/dist/storage/domains/source-control/base.d.ts +9 -0
  146. package/dist/storage/domains/source-control/base.d.ts.map +1 -1
  147. package/dist/storage/domains/source-control/base.js +777 -702
  148. package/dist/storage/domains/source-control/base.js.map +1 -1
  149. package/dist/storage/domains/source-control/inmemory.d.ts +4 -0
  150. package/dist/storage/domains/source-control/inmemory.d.ts.map +1 -1
  151. package/dist/storage/domains/source-control/inmemory.js +322 -344
  152. package/dist/storage/domains/source-control/inmemory.js.map +1 -1
  153. package/dist/storage/domains/work-items/base.d.ts.map +1 -1
  154. package/dist/storage/domains/work-items/base.js +1266 -1132
  155. package/dist/storage/domains/work-items/base.js.map +1 -1
  156. package/dist/storage/domains/work-items/metrics.js +202 -184
  157. package/dist/storage/domains/work-items/metrics.js.map +1 -1
  158. package/dist/timing.d.ts +15 -0
  159. package/dist/timing.d.ts.map +1 -0
  160. package/dist/timing.js +34 -0
  161. package/dist/timing.js.map +1 -0
  162. package/dist/workspace.d.ts +2 -3
  163. package/dist/workspace.d.ts.map +1 -1
  164. package/dist/workspace.js +236 -438
  165. package/dist/workspace.js.map +1 -1
  166. package/factory-skills/factory-review/SKILL.md +9 -2
  167. package/package.json +9 -9
  168. package/dist/capabilities/connection.js.map +0 -1
  169. package/dist/capabilities/intake.js.map +0 -1
  170. package/dist/capabilities/version-control.js.map +0 -1
  171. package/dist/index.js.map +0 -1
  172. package/dist/integrations/base.js.map +0 -1
  173. package/dist/integrations/linear/storage.js.map +0 -1
  174. package/dist/rules/index.js.map +0 -1
@@ -1,252 +1,317 @@
1
- // src/storage/domains/integrations/base.ts
2
1
  import { FactoryStorageDomain, UniqueViolationError } from "@mastra/core/storage";
3
- var INTEGRATION_CONNECTIONS_SCHEMA = {
4
- name: "integration_connections",
5
- columns: {
6
- id: { type: "uuid-pk" },
7
- integration_id: { type: "text" },
8
- org_id: { type: "text" },
9
- /** Who connected it (audit only — never scopes reads). */
10
- user_id: { type: "text", nullable: true },
11
- data: { type: "json" },
12
- metadata: { type: "json" },
13
- created_at: { type: "timestamp" },
14
- updated_at: { type: "timestamp" }
15
- },
16
- uniqueIndexes: [{ name: "integration_connections_integration_org_unique", columns: ["integration_id", "org_id"] }]
2
+ //#region src/storage/domains/integrations/base.ts
3
+ /**
4
+ * Generic integration storage — the default persistence surface for
5
+ * `FactoryIntegration`s.
6
+ *
7
+ * Most integrations persist the same three shapes: an org-owned OAuth
8
+ * **connection**, **subscriptions** binding external objects to
9
+ * sessions/threads, and per-`(org, user)` **settings**. This built-in domain
10
+ * stores all three in shared collections keyed by `integration_id`, so an
11
+ * integration author writes zero schema, zero DDL, and zero queries — and
12
+ * org scoping is enforced by construction through the pre-scoped handle
13
+ * returned by {@link IntegrationStorage.forIntegration}.
14
+ *
15
+ * Source-control integrations additionally use the shared, provider-scoped
16
+ * source-control domain for installations, projects, worktrees, and sandboxes.
17
+ *
18
+ * Payloads (`data` / `config`) are JSON documents typed per-integration via
19
+ * the handle's generics. JSON round-trips exactly what JSON can represent:
20
+ * store timestamps inside payloads as epoch millis or ISO strings, not
21
+ * `Date`s.
22
+ */
23
+ const INTEGRATION_CONNECTIONS_SCHEMA = {
24
+ name: "integration_connections",
25
+ columns: {
26
+ id: { type: "uuid-pk" },
27
+ integration_id: { type: "text" },
28
+ org_id: { type: "text" },
29
+ /** Who connected it (audit only — never scopes reads). */
30
+ user_id: {
31
+ type: "text",
32
+ nullable: true
33
+ },
34
+ data: { type: "json" },
35
+ metadata: { type: "json" },
36
+ created_at: { type: "timestamp" },
37
+ updated_at: { type: "timestamp" }
38
+ },
39
+ uniqueIndexes: [{
40
+ name: "integration_connections_integration_org_unique",
41
+ columns: ["integration_id", "org_id"]
42
+ }]
17
43
  };
18
- var INTEGRATION_SUBSCRIPTIONS_SCHEMA = {
19
- name: "integration_subscriptions",
20
- columns: {
21
- id: { type: "uuid-pk" },
22
- integration_id: { type: "text" },
23
- org_id: { type: "text" },
24
- /** Canonical external-object key the integration derives (e.g. `pr:{installation}:{repo}:{number}`). */
25
- target_key: { type: "text" },
26
- session_id: { type: "text", nullable: true },
27
- resource_id: { type: "text", nullable: true },
28
- thread_id: { type: "text", nullable: true },
29
- session_scope: { type: "text", nullable: true },
30
- status: { type: "text" },
31
- data: { type: "json" },
32
- created_at: { type: "timestamp" },
33
- updated_at: { type: "timestamp" }
34
- },
35
- indexes: [
36
- { name: "integration_subscriptions_target_idx", columns: ["integration_id", "target_key"] },
37
- { name: "integration_subscriptions_org_idx", columns: ["integration_id", "org_id"] }
38
- ]
44
+ const INTEGRATION_SUBSCRIPTIONS_SCHEMA = {
45
+ name: "integration_subscriptions",
46
+ columns: {
47
+ id: { type: "uuid-pk" },
48
+ integration_id: { type: "text" },
49
+ org_id: { type: "text" },
50
+ /** Canonical external-object key the integration derives (e.g. `pr:{installation}:{repo}:{number}`). */
51
+ target_key: { type: "text" },
52
+ session_id: {
53
+ type: "text",
54
+ nullable: true
55
+ },
56
+ resource_id: {
57
+ type: "text",
58
+ nullable: true
59
+ },
60
+ thread_id: {
61
+ type: "text",
62
+ nullable: true
63
+ },
64
+ session_scope: {
65
+ type: "text",
66
+ nullable: true
67
+ },
68
+ status: { type: "text" },
69
+ data: { type: "json" },
70
+ created_at: { type: "timestamp" },
71
+ updated_at: { type: "timestamp" }
72
+ },
73
+ indexes: [{
74
+ name: "integration_subscriptions_target_idx",
75
+ columns: ["integration_id", "target_key"]
76
+ }, {
77
+ name: "integration_subscriptions_org_idx",
78
+ columns: ["integration_id", "org_id"]
79
+ }]
39
80
  };
40
- var INTEGRATION_SETTINGS_SCHEMA = {
41
- name: "integration_settings",
42
- columns: {
43
- id: { type: "uuid-pk" },
44
- integration_id: { type: "text" },
45
- org_id: { type: "text" },
46
- user_id: { type: "text" },
47
- config: { type: "json" },
48
- created_at: { type: "timestamp" },
49
- updated_at: { type: "timestamp" }
50
- },
51
- uniqueIndexes: [
52
- { name: "integration_settings_integration_org_user_unique", columns: ["integration_id", "org_id", "user_id"] }
53
- ]
81
+ const INTEGRATION_SETTINGS_SCHEMA = {
82
+ name: "integration_settings",
83
+ columns: {
84
+ id: { type: "uuid-pk" },
85
+ integration_id: { type: "text" },
86
+ org_id: { type: "text" },
87
+ user_id: { type: "text" },
88
+ config: { type: "json" },
89
+ created_at: { type: "timestamp" },
90
+ updated_at: { type: "timestamp" }
91
+ },
92
+ uniqueIndexes: [{
93
+ name: "integration_settings_integration_org_user_unique",
94
+ columns: [
95
+ "integration_id",
96
+ "org_id",
97
+ "user_id"
98
+ ]
99
+ }]
54
100
  };
101
+ /**
102
+ * The built-in generic integration domain, written once against the
103
+ * `FactoryStorageOps` surface — works on any `FactoryStorage` backend.
104
+ */
55
105
  var IntegrationStorage = class extends FactoryStorageDomain {
56
- constructor() {
57
- super("integrations");
58
- }
59
- async init() {
60
- await this.ensureCollections([
61
- INTEGRATION_CONNECTIONS_SCHEMA,
62
- INTEGRATION_SUBSCRIPTIONS_SCHEMA,
63
- INTEGRATION_SETTINGS_SCHEMA
64
- ]);
65
- }
66
- async dangerouslyClearAll() {
67
- await this.ops.deleteMany("integration_subscriptions", {});
68
- await this.ops.deleteMany("integration_settings", {});
69
- await this.ops.deleteMany("integration_connections", {});
70
- }
71
- get #db() {
72
- return this.ops;
73
- }
74
- /** A typed handle pre-scoped to `integrationId`. */
75
- forIntegration(integrationId) {
76
- if (!integrationId) throw new Error("[IntegrationStorage] integrationId is required.");
77
- const db = () => this.#db;
78
- const scoped = { integration_id: integrationId };
79
- const mapConnection = (row) => ({
80
- id: row.id,
81
- orgId: row.org_id,
82
- userId: row.user_id,
83
- data: row.data,
84
- metadata: row.metadata ?? {},
85
- createdAt: row.created_at,
86
- updatedAt: row.updated_at
87
- });
88
- const mapSubscription = (row) => ({
89
- id: row.id,
90
- orgId: row.org_id,
91
- targetKey: row.target_key,
92
- sessionId: row.session_id,
93
- resourceId: row.resource_id,
94
- threadId: row.thread_id,
95
- sessionScope: row.session_scope,
96
- status: row.status,
97
- data: row.data,
98
- createdAt: row.created_at,
99
- updatedAt: row.updated_at
100
- });
101
- return {
102
- integrationId,
103
- connections: {
104
- get: async (orgId) => {
105
- const row = await db().findOne("integration_connections", { ...scoped, org_id: orgId });
106
- return row ? mapConnection(row) : null;
107
- },
108
- upsert: async (orgId, input) => {
109
- const where = { ...scoped, org_id: orgId };
110
- const update = async () => db().updateMany("integration_connections", where, {
111
- user_id: input.userId ?? null,
112
- data: input.data,
113
- metadata: input.metadata ?? {},
114
- updated_at: /* @__PURE__ */ new Date()
115
- });
116
- let lastError;
117
- for (let attempt = 0; attempt < 2; attempt++) {
118
- if (await update() > 0) return;
119
- const now = /* @__PURE__ */ new Date();
120
- try {
121
- await db().insertOne("integration_connections", {
122
- ...where,
123
- user_id: input.userId ?? null,
124
- data: input.data,
125
- metadata: input.metadata ?? {},
126
- created_at: now,
127
- updated_at: now
128
- });
129
- return;
130
- } catch (error) {
131
- if (!(error instanceof UniqueViolationError)) throw error;
132
- lastError = error;
133
- }
134
- }
135
- throw lastError;
136
- },
137
- update: async (orgId, fn) => {
138
- const row = await db().updateAtomic(
139
- "integration_connections",
140
- { ...scoped, org_id: orgId },
141
- (current) => ({ data: fn(current.data), updated_at: /* @__PURE__ */ new Date() })
142
- );
143
- return row ? mapConnection(row) : null;
144
- },
145
- delete: async (orgId) => {
146
- const deleted = await db().deleteMany("integration_connections", { ...scoped, org_id: orgId });
147
- return deleted > 0;
148
- }
149
- },
150
- subscriptions: {
151
- create: async (input) => {
152
- const now = /* @__PURE__ */ new Date();
153
- const row = await db().insertOne("integration_subscriptions", {
154
- ...scoped,
155
- org_id: input.orgId,
156
- target_key: input.targetKey,
157
- session_id: input.sessionId ?? null,
158
- resource_id: input.resourceId ?? null,
159
- thread_id: input.threadId ?? null,
160
- session_scope: input.sessionScope ?? null,
161
- status: input.status ?? "active",
162
- data: input.data ?? {},
163
- created_at: now,
164
- updated_at: now
165
- });
166
- return mapSubscription(row);
167
- },
168
- listByTarget: async (targetKey, opts) => {
169
- const rows = await db().findMany(
170
- "integration_subscriptions",
171
- { ...scoped, target_key: targetKey, ...opts?.status !== void 0 ? { status: opts.status } : {} },
172
- { orderBy: [["created_at", "asc"]] }
173
- );
174
- return rows.map(mapSubscription);
175
- },
176
- listBySession: async (sessionId) => {
177
- const rows = await db().findMany(
178
- "integration_subscriptions",
179
- { ...scoped, session_id: sessionId },
180
- { orderBy: [["created_at", "asc"]] }
181
- );
182
- return rows.map(mapSubscription);
183
- },
184
- listByThread: async (resourceId, threadId) => {
185
- const rows = await db().findMany(
186
- "integration_subscriptions",
187
- { ...scoped, resource_id: resourceId, thread_id: threadId },
188
- { orderBy: [["created_at", "asc"]] }
189
- );
190
- return rows.map(mapSubscription);
191
- },
192
- updateStatus: async (id, status) => {
193
- await db().updateMany("integration_subscriptions", { ...scoped, id }, { status, updated_at: /* @__PURE__ */ new Date() });
194
- },
195
- delete: async (id) => {
196
- const deleted = await db().deleteMany("integration_subscriptions", { ...scoped, id });
197
- return deleted > 0;
198
- },
199
- deleteWhere: async (where) => {
200
- return db().deleteMany("integration_subscriptions", {
201
- ...scoped,
202
- org_id: where.orgId,
203
- ...where.targetKey !== void 0 ? { target_key: where.targetKey } : {},
204
- ...where.sessionId !== void 0 ? { session_id: where.sessionId } : {}
205
- });
206
- }
207
- },
208
- settings: {
209
- get: async (orgId, userId) => {
210
- const row = await db().findOne("integration_settings", {
211
- ...scoped,
212
- org_id: orgId,
213
- user_id: userId
214
- });
215
- return row ? structuredClone(row.config) : null;
216
- },
217
- save: async (orgId, userId, config) => {
218
- const where = { ...scoped, org_id: orgId, user_id: userId };
219
- const update = async () => db().updateMany("integration_settings", where, {
220
- config,
221
- updated_at: /* @__PURE__ */ new Date()
222
- });
223
- let lastError;
224
- for (let attempt = 0; attempt < 2; attempt++) {
225
- if (await update() > 0) return;
226
- const now = /* @__PURE__ */ new Date();
227
- try {
228
- await db().insertOne("integration_settings", {
229
- ...where,
230
- config,
231
- created_at: now,
232
- updated_at: now
233
- });
234
- return;
235
- } catch (error) {
236
- if (!(error instanceof UniqueViolationError)) throw error;
237
- lastError = error;
238
- }
239
- }
240
- throw lastError;
241
- }
242
- }
243
- };
244
- }
245
- };
246
- export {
247
- INTEGRATION_CONNECTIONS_SCHEMA,
248
- INTEGRATION_SETTINGS_SCHEMA,
249
- INTEGRATION_SUBSCRIPTIONS_SCHEMA,
250
- IntegrationStorage
106
+ constructor() {
107
+ super("integrations");
108
+ }
109
+ async init() {
110
+ await this.ensureCollections([
111
+ INTEGRATION_CONNECTIONS_SCHEMA,
112
+ INTEGRATION_SUBSCRIPTIONS_SCHEMA,
113
+ INTEGRATION_SETTINGS_SCHEMA
114
+ ]);
115
+ }
116
+ async dangerouslyClearAll() {
117
+ await this.ops.deleteMany("integration_subscriptions", {});
118
+ await this.ops.deleteMany("integration_settings", {});
119
+ await this.ops.deleteMany("integration_connections", {});
120
+ }
121
+ get #db() {
122
+ return this.ops;
123
+ }
124
+ /** A typed handle pre-scoped to `integrationId`. */
125
+ forIntegration(integrationId) {
126
+ if (!integrationId) throw new Error("[IntegrationStorage] integrationId is required.");
127
+ const db = () => this.#db;
128
+ const scoped = { integration_id: integrationId };
129
+ const mapConnection = (row) => ({
130
+ id: row.id,
131
+ orgId: row.org_id,
132
+ userId: row.user_id,
133
+ data: row.data,
134
+ metadata: row.metadata ?? {},
135
+ createdAt: row.created_at,
136
+ updatedAt: row.updated_at
137
+ });
138
+ const mapSubscription = (row) => ({
139
+ id: row.id,
140
+ orgId: row.org_id,
141
+ targetKey: row.target_key,
142
+ sessionId: row.session_id,
143
+ resourceId: row.resource_id,
144
+ threadId: row.thread_id,
145
+ sessionScope: row.session_scope,
146
+ status: row.status,
147
+ data: row.data,
148
+ createdAt: row.created_at,
149
+ updatedAt: row.updated_at
150
+ });
151
+ return {
152
+ integrationId,
153
+ connections: {
154
+ get: async (orgId) => {
155
+ const row = await db().findOne("integration_connections", {
156
+ ...scoped,
157
+ org_id: orgId
158
+ });
159
+ return row ? mapConnection(row) : null;
160
+ },
161
+ upsert: async (orgId, input) => {
162
+ const where = {
163
+ ...scoped,
164
+ org_id: orgId
165
+ };
166
+ const update = async () => db().updateMany("integration_connections", where, {
167
+ user_id: input.userId ?? null,
168
+ data: input.data,
169
+ metadata: input.metadata ?? {},
170
+ updated_at: /* @__PURE__ */ new Date()
171
+ });
172
+ let lastError;
173
+ for (let attempt = 0; attempt < 2; attempt++) {
174
+ if (await update() > 0) return;
175
+ const now = /* @__PURE__ */ new Date();
176
+ try {
177
+ await db().insertOne("integration_connections", {
178
+ ...where,
179
+ user_id: input.userId ?? null,
180
+ data: input.data,
181
+ metadata: input.metadata ?? {},
182
+ created_at: now,
183
+ updated_at: now
184
+ });
185
+ return;
186
+ } catch (error) {
187
+ if (!(error instanceof UniqueViolationError)) throw error;
188
+ lastError = error;
189
+ }
190
+ }
191
+ throw lastError;
192
+ },
193
+ update: async (orgId, fn) => {
194
+ const row = await db().updateAtomic("integration_connections", {
195
+ ...scoped,
196
+ org_id: orgId
197
+ }, (current) => ({
198
+ data: fn(current.data),
199
+ updated_at: /* @__PURE__ */ new Date()
200
+ }));
201
+ return row ? mapConnection(row) : null;
202
+ },
203
+ delete: async (orgId) => {
204
+ return await db().deleteMany("integration_connections", {
205
+ ...scoped,
206
+ org_id: orgId
207
+ }) > 0;
208
+ }
209
+ },
210
+ subscriptions: {
211
+ create: async (input) => {
212
+ const now = /* @__PURE__ */ new Date();
213
+ const row = await db().insertOne("integration_subscriptions", {
214
+ ...scoped,
215
+ org_id: input.orgId,
216
+ target_key: input.targetKey,
217
+ session_id: input.sessionId ?? null,
218
+ resource_id: input.resourceId ?? null,
219
+ thread_id: input.threadId ?? null,
220
+ session_scope: input.sessionScope ?? null,
221
+ status: input.status ?? "active",
222
+ data: input.data ?? {},
223
+ created_at: now,
224
+ updated_at: now
225
+ });
226
+ return mapSubscription(row);
227
+ },
228
+ listByTarget: async (targetKey, opts) => {
229
+ return (await db().findMany("integration_subscriptions", {
230
+ ...scoped,
231
+ target_key: targetKey,
232
+ ...opts?.status !== void 0 ? { status: opts.status } : {}
233
+ }, { orderBy: [["created_at", "asc"]] })).map(mapSubscription);
234
+ },
235
+ listBySession: async (sessionId) => {
236
+ return (await db().findMany("integration_subscriptions", {
237
+ ...scoped,
238
+ session_id: sessionId
239
+ }, { orderBy: [["created_at", "asc"]] })).map(mapSubscription);
240
+ },
241
+ listByThread: async (resourceId, threadId) => {
242
+ return (await db().findMany("integration_subscriptions", {
243
+ ...scoped,
244
+ resource_id: resourceId,
245
+ thread_id: threadId
246
+ }, { orderBy: [["created_at", "asc"]] })).map(mapSubscription);
247
+ },
248
+ updateStatus: async (id, status) => {
249
+ await db().updateMany("integration_subscriptions", {
250
+ ...scoped,
251
+ id
252
+ }, {
253
+ status,
254
+ updated_at: /* @__PURE__ */ new Date()
255
+ });
256
+ },
257
+ delete: async (id) => {
258
+ return await db().deleteMany("integration_subscriptions", {
259
+ ...scoped,
260
+ id
261
+ }) > 0;
262
+ },
263
+ deleteWhere: async (where) => {
264
+ return db().deleteMany("integration_subscriptions", {
265
+ ...scoped,
266
+ org_id: where.orgId,
267
+ ...where.targetKey !== void 0 ? { target_key: where.targetKey } : {},
268
+ ...where.sessionId !== void 0 ? { session_id: where.sessionId } : {}
269
+ });
270
+ }
271
+ },
272
+ settings: {
273
+ get: async (orgId, userId) => {
274
+ const row = await db().findOne("integration_settings", {
275
+ ...scoped,
276
+ org_id: orgId,
277
+ user_id: userId
278
+ });
279
+ return row ? structuredClone(row.config) : null;
280
+ },
281
+ save: async (orgId, userId, config) => {
282
+ const where = {
283
+ ...scoped,
284
+ org_id: orgId,
285
+ user_id: userId
286
+ };
287
+ const update = async () => db().updateMany("integration_settings", where, {
288
+ config,
289
+ updated_at: /* @__PURE__ */ new Date()
290
+ });
291
+ let lastError;
292
+ for (let attempt = 0; attempt < 2; attempt++) {
293
+ if (await update() > 0) return;
294
+ const now = /* @__PURE__ */ new Date();
295
+ try {
296
+ await db().insertOne("integration_settings", {
297
+ ...where,
298
+ config,
299
+ created_at: now,
300
+ updated_at: now
301
+ });
302
+ return;
303
+ } catch (error) {
304
+ if (!(error instanceof UniqueViolationError)) throw error;
305
+ lastError = error;
306
+ }
307
+ }
308
+ throw lastError;
309
+ }
310
+ }
311
+ };
312
+ }
251
313
  };
314
+ //#endregion
315
+ export { INTEGRATION_CONNECTIONS_SCHEMA, INTEGRATION_SETTINGS_SCHEMA, INTEGRATION_SUBSCRIPTIONS_SCHEMA, IntegrationStorage };
316
+
252
317
  //# sourceMappingURL=base.js.map